Replace some CFX_DIBitmap::GetBuffer() calls with GetScanline()

Since these are all called on the final CFX_DIBitmap class, we
know they won't execute the complex logic of other subclasses, and
we expect the compiler to de-virtualize them. The logic gets simpler
as a result.

-- Spell ReSample as Resample while at it.
-- add a missing const in one place.

Change-Id: I2ee443916ec9ac14872651bdb45cebc432e60897
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/85733
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/render/cpdf_rendershading.cpp b/core/fpdfapi/render/cpdf_rendershading.cpp
index a43adb6..08807f7 100644
--- a/core/fpdfapi/render/cpdf_rendershading.cpp
+++ b/core/fpdfapi/render/cpdf_rendershading.cpp
@@ -129,11 +129,10 @@
   std::array<FX_ARGB, kShadingSteps> shading_steps =
       GetShadingSteps(t_min, t_max, funcs, pCS, alpha, total_results);
 
-  int pitch = pBitmap->GetPitch();
   CFX_Matrix matrix = mtObject2Bitmap.GetInverse();
   for (int row = 0; row < height; row++) {
     uint32_t* dib_buf =
-        reinterpret_cast<uint32_t*>(pBitmap->GetBuffer() + row * pitch);
+        reinterpret_cast<uint32_t*>(pBitmap->GetWritableScanline(row).data());
     for (int column = 0; column < width; column++) {
       CFX_PointF pos = matrix.Transform(
           CFX_PointF(static_cast<float>(column), static_cast<float>(row)));
@@ -201,14 +200,12 @@
 
   int width = pBitmap->GetWidth();
   int height = pBitmap->GetHeight();
-  int pitch = pBitmap->GetPitch();
-
   bool bDecreasing = dr < 0 && static_cast<int>(FXSYS_sqrt2(dx, dy)) < -dr;
 
   CFX_Matrix matrix = mtObject2Bitmap.GetInverse();
   for (int row = 0; row < height; row++) {
     uint32_t* dib_buf =
-        reinterpret_cast<uint32_t*>(pBitmap->GetBuffer() + row * pitch);
+        reinterpret_cast<uint32_t*>(pBitmap->GetWritableScanline(row).data());
     for (int column = 0; column < width; column++) {
       CFX_PointF pos = matrix.Transform(
           CFX_PointF(static_cast<float>(column), static_cast<float>(row)));
@@ -283,13 +280,13 @@
       mtObject2Bitmap.GetInverse() * mtDomain2Target.GetInverse();
   int width = pBitmap->GetWidth();
   int height = pBitmap->GetHeight();
-  int pitch = pBitmap->GetPitch();
 
   DCHECK(total_results >= CountOutputsFromFunctions(funcs));
   DCHECK(total_results >= pCS->CountComponents());
   std::vector<float> result_array(total_results);
   for (int row = 0; row < height; ++row) {
-    uint32_t* dib_buf = (uint32_t*)(pBitmap->GetBuffer() + row * pitch);
+    uint32_t* dib_buf =
+        reinterpret_cast<uint32_t*>(pBitmap->GetWritableScanline(row).data());
     for (int column = 0; column < width; column++) {
       CFX_PointF pos = matrix.Transform(
           CFX_PointF(static_cast<float>(column), static_cast<float>(row)));
@@ -395,7 +392,7 @@
     int end_x = std::min(max_x, pBitmap->GetWidth());
 
     uint8_t* dib_buf =
-        pBitmap->GetBuffer() + y * pBitmap->GetPitch() + start_x * 4;
+        pBitmap->GetWritableScanline(y).subspan(start_x * 4).data();
     float r_unit = (r[end_index] - r[start_index]) / (max_x - min_x);
     float g_unit = (g[end_index] - g[start_index]) / (max_x - min_x);
     float b_unit = (b[end_index] - b[start_index]) / (max_x - min_x);
diff --git a/core/fpdfapi/render/cpdf_rendertiling.cpp b/core/fpdfapi/render/cpdf_rendertiling.cpp
index 17575ef..6ccd590 100644
--- a/core/fpdfapi/render/cpdf_rendertiling.cpp
+++ b/core/fpdfapi/render/cpdf_rendertiling.cpp
@@ -225,7 +225,7 @@
           continue;
         }
         uint32_t* dest_buf = reinterpret_cast<uint32_t*>(
-            pScreen->GetBuffer() + pScreen->GetPitch() * start_y + start_x * 4);
+            pScreen->GetWritableScanline(start_y).subspan(start_x * 4).data());
         if (pPattern->colored()) {
           const auto* src_buf32 = reinterpret_cast<const uint32_t*>(src_buf);
           *dest_buf = *src_buf32;
diff --git a/core/fpdfapi/render/cpdf_type3cache.cpp b/core/fpdfapi/render/cpdf_type3cache.cpp
index b2c9405..45b35e1 100644
--- a/core/fpdfapi/render/cpdf_type3cache.cpp
+++ b/core/fpdfapi/render/cpdf_type3cache.cpp
@@ -68,12 +68,11 @@
 
 int DetectFirstScan(const RetainPtr<CFX_DIBitmap>& pBitmap) {
   const int height = pBitmap->GetHeight();
-  const int pitch = pBitmap->GetPitch();
   const int width = pBitmap->GetWidth();
   const int bpp = pBitmap->GetBPP();
-  const uint8_t* pBuf = pBitmap->GetBuffer();
   for (int line = 0; line < height; ++line) {
-    if (IsScanLineBpp(bpp, pBuf + line * pitch, width))
+    const uint8_t* pBuf = pBitmap->GetScanline(line).data();
+    if (IsScanLineBpp(bpp, pBuf, width))
       return line;
   }
   return -1;
@@ -81,12 +80,11 @@
 
 int DetectLastScan(const RetainPtr<CFX_DIBitmap>& pBitmap) {
   const int height = pBitmap->GetHeight();
-  const int pitch = pBitmap->GetPitch();
   const int bpp = pBitmap->GetBPP();
   const int width = pBitmap->GetWidth();
-  const uint8_t* pBuf = pBitmap->GetBuffer();
   for (int line = height - 1; line >= 0; --line) {
-    if (IsScanLineBpp(bpp, pBuf + line * pitch, width))
+    const uint8_t* pBuf = pBitmap->GetScanline(line).data();
+    if (IsScanLineBpp(bpp, pBuf, width))
       return line;
   }
   return -1;
diff --git a/core/fxcodec/progressive_decoder.cpp b/core/fxcodec/progressive_decoder.cpp
index d717394..9ca1974 100644
--- a/core/fxcodec/progressive_decoder.cpp
+++ b/core/fxcodec/progressive_decoder.cpp
@@ -476,7 +476,7 @@
   if (dest_row >= dest_top + dest_height)
     return;
 
-  ReSampleScanline(pDIBitmap, dest_row, m_DecodeBuf.data(), m_SrcFormat);
+  ResampleScanline(pDIBitmap, dest_row, m_DecodeBuf.data(), m_SrcFormat);
   if (scale_y > 1.0 && m_SrcPassNumber == 1) {
     ResampleVert(pDIBitmap, scale_y, dest_row);
     return;
@@ -534,7 +534,7 @@
   if (dest_row >= dest_top + dest_height)
     return;
 
-  ReSampleScanline(pDIBitmap, dest_row, m_DecodeBuf.data(), m_SrcFormat);
+  ResampleScanline(pDIBitmap, dest_row, m_DecodeBuf.data(), m_SrcFormat);
   if (scale_y <= 1.0)
     return;
 
@@ -1682,15 +1682,14 @@
   }
 }
 
-void ProgressiveDecoder::ReSampleScanline(
+void ProgressiveDecoder::ResampleScanline(
     const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
     int dest_line,
     uint8_t* src_scan,
     FXCodec_Format src_format) {
   int src_left = m_clipBox.left;
   int dest_left = m_startX;
-  uint8_t* dest_scan =
-      pDeviceBitmap->GetBuffer() + dest_line * pDeviceBitmap->GetPitch();
+  uint8_t* dest_scan = pDeviceBitmap->GetWritableScanline(dest_line).data();
   int src_bytes_per_pixel = (src_format & 0xff) / 8;
   int dest_bytes_per_pixel = pDeviceBitmap->GetBPP() / 8;
   src_scan += src_left * src_bytes_per_pixel;
@@ -2035,7 +2034,7 @@
     if (dest_row >= dest_top + dest_height)
       return;
 
-    ReSampleScanline(pDeviceBitmap, dest_row, m_DecodeBuf.data(), src_format);
+    ResampleScanline(pDeviceBitmap, dest_row, m_DecodeBuf.data(), src_format);
     if (scale_y > 1.0)
       ResampleVert(pDeviceBitmap, scale_y, dest_row);
   }
diff --git a/core/fxcodec/progressive_decoder.h b/core/fxcodec/progressive_decoder.h
index 30be383..e9f74ba 100644
--- a/core/fxcodec/progressive_decoder.h
+++ b/core/fxcodec/progressive_decoder.h
@@ -203,7 +203,7 @@
   int GetDownScale();
   void GetTransMethod(FXDIB_Format dest_format, FXCodec_Format src_format);
 
-  void ReSampleScanline(const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
+  void ResampleScanline(const RetainPtr<CFX_DIBitmap>& pDeviceBitmap,
                         int32_t dest_line,
                         uint8_t* src_scan,
                         FXCodec_Format src_format);
diff --git a/core/fxcodec/tiff/tiff_decoder.cpp b/core/fxcodec/tiff/tiff_decoder.cpp
index f66ab19..fc9dd2f 100644
--- a/core/fxcodec/tiff/tiff_decoder.cpp
+++ b/core/fxcodec/tiff/tiff_decoder.cpp
@@ -366,12 +366,11 @@
     TIFFError(TIFFFileName(m_tif_ctx.get()), "No space for scanline buffer");
     return false;
   }
-  uint8_t* bitMapbuffer = (uint8_t*)pDIBitmap->GetBuffer();
-  uint32_t pitch = pDIBitmap->GetPitch();
   for (int32_t row = 0; row < height; row++) {
+    uint8_t* bitMapbuffer = pDIBitmap->GetWritableScanline(row).data();
     TIFFReadScanline(m_tif_ctx.get(), buf, row, 0);
     for (int32_t j = 0; j < size; j++) {
-      bitMapbuffer[row * pitch + j] = buf[j];
+      bitMapbuffer[j] = buf[j];
     }
   }
   _TIFFfree(buf);
@@ -394,18 +393,17 @@
     TIFFError(TIFFFileName(m_tif_ctx.get()), "No space for scanline buffer");
     return false;
   }
-  uint8_t* bitMapbuffer = (uint8_t*)pDIBitmap->GetBuffer();
-  uint32_t pitch = pDIBitmap->GetPitch();
   for (int32_t row = 0; row < height; row++) {
+    uint8_t* bitMapbuffer = pDIBitmap->GetWritableScanline(row).data();
     TIFFReadScanline(m_tif_ctx.get(), buf, row, 0);
     for (int32_t j = 0; j < size; j++) {
       switch (bps) {
         case 4:
-          bitMapbuffer[row * pitch + 2 * j + 0] = (buf[j] & 0xF0) >> 4;
-          bitMapbuffer[row * pitch + 2 * j + 1] = (buf[j] & 0x0F) >> 0;
+          bitMapbuffer[2 * j + 0] = (buf[j] & 0xF0) >> 4;
+          bitMapbuffer[2 * j + 1] = (buf[j] & 0x0F) >> 0;
           break;
         case 8:
-          bitMapbuffer[row * pitch + j] = buf[j];
+          bitMapbuffer[j] = buf[j];
           break;
       }
     }
@@ -428,14 +426,13 @@
     TIFFError(TIFFFileName(m_tif_ctx.get()), "No space for scanline buffer");
     return false;
   }
-  uint8_t* bitMapbuffer = (uint8_t*)pDIBitmap->GetBuffer();
-  uint32_t pitch = pDIBitmap->GetPitch();
   for (int32_t row = 0; row < height; row++) {
+    uint8_t* bitMapbuffer = pDIBitmap->GetWritableScanline(row).data();
     TIFFReadScanline(m_tif_ctx.get(), buf, row, 0);
     for (int32_t j = 0; j < size - 2; j += 3) {
-      bitMapbuffer[row * pitch + j + 0] = buf[j + 2];
-      bitMapbuffer[row * pitch + j + 1] = buf[j + 1];
-      bitMapbuffer[row * pitch + j + 2] = buf[j + 0];
+      bitMapbuffer[j + 0] = buf[j + 2];
+      bitMapbuffer[j + 1] = buf[j + 1];
+      bitMapbuffer[j + 2] = buf[j + 0];
     }
   }
   _TIFFfree(buf);
diff --git a/core/fxge/cfx_cliprgn.cpp b/core/fxge/cfx_cliprgn.cpp
index b99ae75..79555d8 100644
--- a/core/fxge/cfx_cliprgn.cpp
+++ b/core/fxge/cfx_cliprgn.cpp
@@ -10,6 +10,7 @@
 
 #include <utility>
 
+#include "core/fxcrt/span_util.h"
 #include "core/fxge/dib/cfx_dibitmap.h"
 #include "third_party/base/check_op.h"
 #include "third_party/base/notreached.h"
@@ -47,11 +48,11 @@
   m_Mask->Create(m_Box.Width(), m_Box.Height(), FXDIB_Format::k8bppMask);
   const int offset = m_Box.left - mask_rect.left;
   for (int row = m_Box.top; row < m_Box.bottom; row++) {
-    uint8_t* dest_scan =
-        m_Mask->GetBuffer() + m_Mask->GetPitch() * (row - m_Box.top);
+    pdfium::span<uint8_t> dest_scan =
+        m_Mask->GetWritableScanline(row - m_Box.top);
     pdfium::span<const uint8_t> src_scan =
         pOldMask->GetScanline(row - mask_rect.top);
-    memcpy(dest_scan, &src_scan[offset], m_Box.Width());
+    fxcrt::spancpy(dest_scan, src_scan.subspan(offset, m_Box.Width()));
   }
 }
 
@@ -79,8 +80,7 @@
   for (int row = new_box.top; row < new_box.bottom; row++) {
     pdfium::span<const uint8_t> old_scan = m_Mask->GetScanline(row - m_Box.top);
     pdfium::span<const uint8_t> mask_scan = pMask->GetScanline(row - top);
-    uint8_t* new_scan =
-        new_dib->GetBuffer() + (row - new_box.top) * new_dib->GetPitch();
+    uint8_t* new_scan = new_dib->GetWritableScanline(row - new_box.top).data();
     for (int col = new_box.left; col < new_box.right; col++) {
       new_scan[col - new_box.left] =
           old_scan[col - m_Box.left] * mask_scan[col - left] / 255;
diff --git a/core/fxge/cfx_renderdevice.cpp b/core/fxge/cfx_renderdevice.cpp
index 4d3457c..a2a3c8a 100644
--- a/core/fxge/cfx_renderdevice.cpp
+++ b/core/fxge/cfx_renderdevice.cpp
@@ -201,7 +201,7 @@
     NormalizeArgb(src_value, r, g, b, a, dest, src_alpha);
 }
 
-void NextPixel(uint8_t** src_scan, uint8_t** dst_scan, int bpp) {
+void NextPixel(const uint8_t** src_scan, uint8_t** dst_scan, int bpp) {
   *src_scan += 3;
   *dst_scan += bpp;
 }
@@ -225,18 +225,16 @@
                           int g,
                           int b) {
   const bool has_alpha = bitmap->GetFormat() == FXDIB_Format::kArgb;
-  uint8_t* src_buf = pGlyph->GetBuffer();
-  int src_pitch = pGlyph->GetPitch();
-  uint8_t* dest_buf = bitmap->GetBuffer();
-  int dest_pitch = bitmap->GetPitch();
   const int Bpp = has_alpha ? 4 : bitmap->GetBPP() / 8;
   for (int row = 0; row < nrows; ++row) {
     int dest_row = row + top;
     if (dest_row < 0 || dest_row >= bitmap->GetHeight())
       continue;
 
-    uint8_t* src_scan = src_buf + row * src_pitch + (start_col - left) * 3;
-    uint8_t* dest_scan = dest_buf + dest_row * dest_pitch + start_col * Bpp;
+    const uint8_t* src_scan =
+        pGlyph->GetScanline(row).subspan((start_col - left) * 3).data();
+    uint8_t* dest_scan =
+        bitmap->GetWritableScanline(dest_row).subspan(start_col * Bpp).data();
     if (x_subpixel == 0) {
       for (int col = start_col; col < end_col; ++col) {
         if (normalize) {
diff --git a/core/fxge/dib/cfx_bitmapcomposer.cpp b/core/fxge/dib/cfx_bitmapcomposer.cpp
index 23a59bd..4aa97dd 100644
--- a/core/fxge/dib/cfx_bitmapcomposer.cpp
+++ b/core/fxge/dib/cfx_bitmapcomposer.cpp
@@ -109,10 +109,11 @@
   }
   const uint8_t* clip_scan = nullptr;
   if (m_pClipMask) {
-    clip_scan = m_pClipMask->GetBuffer() +
-                (m_DestTop + line - m_pClipRgn->GetBox().top) *
-                    m_pClipMask->GetPitch() +
-                (m_DestLeft - m_pClipRgn->GetBox().left);
+    clip_scan =
+        m_pClipMask
+            ->GetWritableScanline(m_DestTop + line - m_pClipRgn->GetBox().top)
+            .subspan(m_DestLeft - m_pClipRgn->GetBox().left)
+            .data();
   }
   uint8_t* dest_scan = m_pBitmap->GetWritableScanline(line + m_DestTop).data();
   if (dest_scan) {
@@ -180,9 +181,9 @@
     clip_scan = m_pClipScanV.data();
     int clip_pitch = m_pClipMask->GetPitch();
     const uint8_t* src_clip =
-        m_pClipMask->GetBuffer() +
-        (m_DestTop - m_pClipRgn->GetBox().top) * clip_pitch +
-        (dest_x - m_pClipRgn->GetBox().left);
+        m_pClipMask->GetScanline(m_DestTop - m_pClipRgn->GetBox().top)
+            .subspan(dest_x - m_pClipRgn->GetBox().left)
+            .data();
     if (m_bFlipY) {
       src_clip += clip_pitch * (m_DestHeight - 1);
       clip_pitch = -clip_pitch;
diff --git a/core/fxge/dib/cfx_dibbase.cpp b/core/fxge/dib/cfx_dibbase.cpp
index 2bfae7a..b29298f 100644
--- a/core/fxge/dib/cfx_dibbase.cpp
+++ b/core/fxge/dib/cfx_dibbase.cpp
@@ -692,8 +692,9 @@
     m_pAlphaMask = nullptr;
     return false;
   }
-  memset(m_pAlphaMask->GetBuffer(), 0xff,
-         m_pAlphaMask->GetHeight() * m_pAlphaMask->GetPitch());
+  for (int i = 0; i < m_pAlphaMask->GetHeight(); ++i) {
+    fxcrt::spanset(m_pAlphaMask->GetWritableScanline(i), 0xff);
+  }
   return true;
 }
 
@@ -928,12 +929,11 @@
     return nullptr;
 
   pFlipped->SetPalette(GetPaletteSpan());
-  uint8_t* pDestBuffer = pFlipped->GetBuffer();
   int Bpp = GetBppFromFormat(m_Format) / 8;
   for (int row = 0; row < m_Height; ++row) {
     const uint8_t* src_scan = GetScanline(row).data();
     uint8_t* dest_scan =
-        pDestBuffer + m_Pitch * (bYFlip ? (m_Height - row - 1) : row);
+        pFlipped->GetWritableScanline(bYFlip ? m_Height - row - 1 : row).data();
     if (!bXFlip) {
       memcpy(dest_scan, src_scan, m_Pitch);
       continue;
@@ -974,12 +974,13 @@
     }
   }
   if (m_pAlphaMask) {
-    pDestBuffer = pFlipped->m_pAlphaMask->GetBuffer();
     uint32_t dest_pitch = pFlipped->m_pAlphaMask->GetPitch();
     for (int row = 0; row < m_Height; ++row) {
       const uint8_t* src_scan = m_pAlphaMask->GetScanline(row).data();
       uint8_t* dest_scan =
-          pDestBuffer + dest_pitch * (bYFlip ? (m_Height - row - 1) : row);
+          pFlipped->m_pAlphaMask
+              ->GetWritableScanline(bYFlip ? m_Height - row - 1 : row)
+              .data();
       if (!bXFlip) {
         memcpy(dest_scan, src_scan, dest_pitch);
         continue;
diff --git a/xfa/fgas/graphics/cfgas_gegraphics.cpp b/xfa/fgas/graphics/cfgas_gegraphics.cpp
index f145d52..7efda45 100644
--- a/xfa/fgas/graphics/cfgas_gegraphics.cpp
+++ b/xfa/fgas/graphics/cfgas_gegraphics.cpp
@@ -289,7 +289,6 @@
   auto bmp = pdfium::MakeRetain<CFX_DIBitmap>();
   bmp->Create(width, height, FXDIB_Format::kArgb);
   m_renderDevice->GetDIBits(bmp, 0, 0);
-  int32_t pitch = bmp->GetPitch();
   bool result = false;
   switch (m_info.fillColor.GetShading()->GetType()) {
     case CFGAS_GEShading::Type::kAxial: {
@@ -298,7 +297,7 @@
       float axis_len_square = (x_span * x_span) + (y_span * y_span);
       for (int32_t row = 0; row < height; row++) {
         uint32_t* dib_buf =
-            reinterpret_cast<uint32_t*>(bmp->GetBuffer() + row * pitch);
+            reinterpret_cast<uint32_t*>(bmp->GetWritableScanline(row).data());
         for (int32_t column = 0; column < width; column++) {
           float scale = 0.0f;
           if (axis_len_square) {
@@ -331,7 +330,8 @@
                 ((start_y - end_y) * (start_y - end_y)) -
                 ((start_r - end_r) * (start_r - end_r));
       for (int32_t row = 0; row < height; row++) {
-        uint32_t* dib_buf = (uint32_t*)(bmp->GetBuffer() + row * pitch);
+        uint32_t* dib_buf =
+            reinterpret_cast<uint32_t*>(bmp->GetWritableScanline(row).data());
         for (int32_t column = 0; column < width; column++) {
           float x = (float)(column);
           float y = (float)(row);