Add CFX_DIBSource::GetWritableScanline().

Remove a bunch of const_cast<uint8_t*> or equivalent.  This will also
help when we convert to span<>, since casting spans is a nuisance.

Change-Id: I330e5041cbaf33a84425fc4242a3dfacf5ca8011
Reviewed-on: https://pdfium-review.googlesource.com/39831
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/render/cpdf_dibsource.cpp b/core/fpdfapi/render/cpdf_dibsource.cpp
index 72dec67..fec439a 100644
--- a/core/fpdfapi/render/cpdf_dibsource.cpp
+++ b/core/fpdfapi/render/cpdf_dibsource.cpp
@@ -640,7 +640,7 @@
       m_bpc < 8) {
     int scale = 8 - m_bpc;
     for (uint32_t row = 0; row < height; ++row) {
-      uint8_t* scanline = const_cast<uint8_t*>(pCachedBitmap->GetScanline(row));
+      uint8_t* scanline = pCachedBitmap->GetWritableScanline(row);
       for (uint32_t col = 0; col < width; ++col) {
         *scanline = (*scanline) >> scale;
         ++scanline;
diff --git a/core/fpdfapi/render/cpdf_imagerenderer.cpp b/core/fpdfapi/render/cpdf_imagerenderer.cpp
index d3e7075..c7334f6 100644
--- a/core/fpdfapi/render/cpdf_imagerenderer.cpp
+++ b/core/fpdfapi/render/cpdf_imagerenderer.cpp
@@ -247,8 +247,7 @@
   int matte_g = FXARGB_G(m_Loader.m_MatteColor);
   int matte_b = FXARGB_B(m_Loader.m_MatteColor);
   for (int row = 0; row < rect.Height(); row++) {
-    uint8_t* dest_scan =
-        const_cast<uint8_t*>(pBitmapDevice1->GetBitmap()->GetScanline(row));
+    uint8_t* dest_scan = pBitmapDevice1->GetBitmap()->GetWritableScanline(row);
     const uint8_t* mask_scan = pBitmapDevice2->GetBitmap()->GetScanline(row);
     for (int col = 0; col < rect.Width(); col++) {
       int alpha = *mask_scan++;
diff --git a/core/fxcodec/codec/ccodec_tiffmodule.cpp b/core/fxcodec/codec/ccodec_tiffmodule.cpp
index 1a7a51a..5f74b28 100644
--- a/core/fxcodec/codec/ccodec_tiffmodule.cpp
+++ b/core/fxcodec/codec/ccodec_tiffmodule.cpp
@@ -463,7 +463,7 @@
                                   (uint32*)pDIBitmap->GetBuffer(), rotation,
                                   1)) {
       for (uint32_t row = 0; row < img_height; row++) {
-        uint8_t* row_buf = (uint8_t*)pDIBitmap->GetScanline(row);
+        uint8_t* row_buf = pDIBitmap->GetWritableScanline(row);
         TiffBGRA2RGBA(row_buf, img_width, 4);
       }
       return true;
diff --git a/core/fxcodec/codec/fx_codec_progress.cpp b/core/fxcodec/codec/fx_codec_progress.cpp
index 6b91e86..d1c04b9 100644
--- a/core/fxcodec/codec/fx_codec_progress.cpp
+++ b/core/fxcodec/codec/fx_codec_progress.cpp
@@ -361,7 +361,7 @@
   if (line >= m_clipBox.top && line < m_clipBox.bottom) {
     double scale_y = static_cast<double>(m_sizeY) / m_clipBox.Height();
     int32_t row = (int32_t)((line - m_clipBox.top) * scale_y) + m_startY;
-    uint8_t* src_scan = (uint8_t*)pDIBitmap->GetScanline(row);
+    const uint8_t* src_scan = pDIBitmap->GetScanline(row);
     uint8_t* dest_scan = m_pDecodeBuf;
     *pSrcBuf = m_pDecodeBuf;
     int32_t src_Bpp = pDIBitmap->GetBPP() >> 3;
@@ -522,7 +522,7 @@
   FX_ARGB argb = m_pSrcPalette[pal_index];
   for (int row = 0; row < sizeY; row++) {
     uint8_t* pScanline =
-        (uint8_t*)pDevice->GetScanline(row + startY) + startX * Bpp;
+        pDevice->GetWritableScanline(row + startY) + startX * Bpp;
     switch (m_TransMethod) {
       case 3: {
         uint8_t gray =
@@ -600,12 +600,11 @@
   int dest_Bpp = pDIBitmap->GetBPP() >> 3;
   uint32_t dest_ScanOffet = m_startX * dest_Bpp;
   if (dest_row + (int)scale_y >= dest_bottom - 1) {
-    uint8_t* scan_src =
-        (uint8_t*)pDIBitmap->GetScanline(dest_row) + dest_ScanOffet;
+    const uint8_t* scan_src = pDIBitmap->GetScanline(dest_row) + dest_ScanOffet;
     int cur_row = dest_row;
     while (++cur_row < dest_bottom) {
       uint8_t* scan_des =
-          (uint8_t*)pDIBitmap->GetScanline(cur_row) + dest_ScanOffet;
+          pDIBitmap->GetWritableScanline(cur_row) + dest_ScanOffet;
       uint32_t size = m_sizeX * dest_Bpp;
       memmove(scan_des, scan_src, size);
     }
@@ -667,11 +666,11 @@
   check_dest_row_1 += pdfium::base::checked_cast<int>(scale_y);
   int dest_row_1 = check_dest_row_1.ValueOrDie();
   if (dest_row_1 >= dest_bottom - 1) {
-    uint8_t* scan_src =
-        (uint8_t*)pDeviceBitmap->GetScanline(dest_row) + dest_ScanOffet;
+    const uint8_t* scan_src =
+        pDeviceBitmap->GetScanline(dest_row) + dest_ScanOffet;
     while (++dest_row < dest_bottom) {
       uint8_t* scan_des =
-          (uint8_t*)pDeviceBitmap->GetScanline(dest_row) + dest_ScanOffet;
+          pDeviceBitmap->GetWritableScanline(dest_row) + dest_ScanOffet;
       uint32_t size = m_sizeX * dest_Bpp;
       memmove(scan_des, scan_src, size);
     }
@@ -679,7 +678,7 @@
   }
   for (; dest_row_1 > dest_row; dest_row_1--) {
     uint8_t* scan_des =
-        (uint8_t*)pDeviceBitmap->GetScanline(dest_row_1) + dest_ScanOffet;
+        pDeviceBitmap->GetWritableScanline(dest_row_1) + dest_ScanOffet;
     PixelWeight* pWeight = m_WeightVert.GetPixelWeight(dest_row_1 - dest_top);
     const uint8_t* scan_src1 =
         pDeviceBitmap->GetScanline(pWeight->m_SrcStart + dest_top) +
@@ -1089,7 +1088,7 @@
   dest_row_1 = std::max(dest_row_1, dest_top);
   for (; dest_row_1 < dest_row; dest_row_1++) {
     uint8_t* scan_des =
-        (uint8_t*)pDeviceBitmap->GetScanline(dest_row_1) + dest_ScanOffet;
+        pDeviceBitmap->GetWritableScanline(dest_row_1) + dest_ScanOffet;
     PixelWeight* pWeight = m_WeightVert.GetPixelWeight(dest_row_1 - dest_top);
     const uint8_t* scan_src1 =
         pDeviceBitmap->GetScanline(pWeight->m_SrcStart + dest_top) +
@@ -1339,7 +1338,7 @@
     int32_t dest_line,
     uint8_t* src_scan,
     FXCodec_Format src_format) {
-  uint8_t* dest_scan = (uint8_t*)pDeviceBitmap->GetScanline(dest_line);
+  uint8_t* dest_scan = pDeviceBitmap->GetWritableScanline(dest_line);
   int32_t src_Bpp = (m_SrcFormat & 0xff) >> 3;
   int32_t dest_Bpp = pDeviceBitmap->GetBPP() >> 3;
   int32_t src_left = m_clipBox.left;
@@ -1667,8 +1666,8 @@
     case FXDIB_8bppRgb:
     case FXDIB_8bppMask: {
       for (int32_t row = 0; row < pClipBitmap->GetHeight(); row++) {
-        uint8_t* src_line = (uint8_t*)pClipBitmap->GetScanline(row);
-        uint8_t* dest_line = (uint8_t*)pFormatBitmap->GetScanline(row);
+        const uint8_t* src_line = pClipBitmap->GetScanline(row);
+        uint8_t* dest_line = pFormatBitmap->GetWritableScanline(row);
         for (int32_t col = 0; col < pClipBitmap->GetWidth(); col++) {
           uint8_t _a = 255 - src_line[3];
           uint8_t b = (src_line[0] * src_line[3] + 0xFF * _a) / 255;
@@ -1683,8 +1682,8 @@
     case FXDIB_Rgb32: {
       int32_t desBpp = (m_pDeviceBitmap->GetFormat() == FXDIB_Rgb) ? 3 : 4;
       for (int32_t row = 0; row < pClipBitmap->GetHeight(); row++) {
-        uint8_t* src_line = (uint8_t*)pClipBitmap->GetScanline(row);
-        uint8_t* dest_line = (uint8_t*)pFormatBitmap->GetScanline(row);
+        const uint8_t* src_line = pClipBitmap->GetScanline(row);
+        uint8_t* dest_line = pFormatBitmap->GetWritableScanline(row);
         for (int32_t col = 0; col < pClipBitmap->GetWidth(); col++) {
           uint8_t _a = 255 - src_line[3];
           uint8_t b = (src_line[0] * src_line[3] + 0xFF * _a) / 255;
@@ -2193,11 +2192,11 @@
   if (dest_row_1 < dest_top) {
     int dest_bottom = dest_top + m_sizeY;
     if (dest_row + (int)scale_y >= dest_bottom - 1) {
-      uint8_t* scan_src =
-          (uint8_t*)pDeviceBitmap->GetScanline(dest_row) + dest_ScanOffet;
+      const uint8_t* scan_src =
+          pDeviceBitmap->GetScanline(dest_row) + dest_ScanOffet;
       while (++dest_row < dest_bottom) {
         uint8_t* scan_des =
-            (uint8_t*)pDeviceBitmap->GetScanline(dest_row) + dest_ScanOffet;
+            pDeviceBitmap->GetWritableScanline(dest_row) + dest_ScanOffet;
         uint32_t size = m_sizeX * dest_Bpp;
         memmove(scan_des, scan_src, size);
       }
@@ -2206,7 +2205,7 @@
   }
   for (; dest_row_1 < dest_row; dest_row_1++) {
     uint8_t* scan_des =
-        (uint8_t*)pDeviceBitmap->GetScanline(dest_row_1) + dest_ScanOffet;
+        pDeviceBitmap->GetWritableScanline(dest_row_1) + dest_ScanOffet;
     PixelWeight* pWeight = m_WeightVert.GetPixelWeight(dest_row_1 - dest_top);
     const uint8_t* scan_src1 =
         pDeviceBitmap->GetScanline(pWeight->m_SrcStart + dest_top) +
@@ -2273,11 +2272,11 @@
   }
   int dest_bottom = dest_top + m_sizeY;
   if (dest_row + (int)scale_y >= dest_bottom - 1) {
-    uint8_t* scan_src =
-        (uint8_t*)pDeviceBitmap->GetScanline(dest_row) + dest_ScanOffet;
+    const uint8_t* scan_src =
+        pDeviceBitmap->GetScanline(dest_row) + dest_ScanOffet;
     while (++dest_row < dest_bottom) {
       uint8_t* scan_des =
-          (uint8_t*)pDeviceBitmap->GetScanline(dest_row) + dest_ScanOffet;
+          pDeviceBitmap->GetWritableScanline(dest_row) + dest_ScanOffet;
       uint32_t size = m_sizeX * dest_Bpp;
       memmove(scan_des, scan_src, size);
     }
diff --git a/core/fxge/agg/fx_agg_driver.cpp b/core/fxge/agg/fx_agg_driver.cpp
index affabba..3d35e12 100644
--- a/core/fxge/agg/fx_agg_driver.cpp
+++ b/core/fxge/agg/fx_agg_driver.cpp
@@ -164,9 +164,8 @@
   if (dest_format == src_format) {
     for (int row = 0; row < height; row++) {
       uint8_t* dest_scan = buffer + (dest_top + row) * pitch + dest_left * Bpp;
-      uint8_t* src_scan =
-          const_cast<uint8_t*>(pSrcBitmap->GetScanline(src_top + row)) +
-          src_left * Bpp;
+      const uint8_t* src_scan =
+          pSrcBitmap->GetScanline(src_top + row) + src_left * Bpp;
       if (Bpp == 4) {
         for (int col = 0; col < width; col++) {
           FXARGB_SETDIB(dest_scan, ArgbEncode(src_scan[3], src_scan[0],
@@ -191,9 +190,8 @@
     ASSERT(src_format == FXDIB_Rgb32);
     for (int row = 0; row < height; row++) {
       uint8_t* dest_scan = dest_buf + row * pitch;
-      uint8_t* src_scan =
-          const_cast<uint8_t*>(pSrcBitmap->GetScanline(src_top + row)) +
-          src_left * 4;
+      const uint8_t* src_scan =
+          pSrcBitmap->GetScanline(src_top + row) + src_left * 4;
       for (int col = 0; col < width; col++) {
         *dest_scan++ = src_scan[2];
         *dest_scan++ = src_scan[1];
@@ -208,9 +206,8 @@
   if (src_format == FXDIB_Rgb) {
     for (int row = 0; row < height; row++) {
       uint8_t* dest_scan = dest_buf + row * pitch;
-      uint8_t* src_scan =
-          const_cast<uint8_t*>(pSrcBitmap->GetScanline(src_top + row)) +
-          src_left * 3;
+      const uint8_t* src_scan =
+          pSrcBitmap->GetScanline(src_top + row) + src_left * 3;
       for (int col = 0; col < width; col++) {
         FXARGB_SETDIB(dest_scan,
                       ArgbEncode(0xff, src_scan[0], src_scan[1], src_scan[2]));
@@ -225,9 +222,8 @@
   ASSERT(dest_format == FXDIB_Argb);
   for (int row = 0; row < height; row++) {
     uint8_t* dest_scan = dest_buf + row * pitch;
-    uint8_t* src_scan =
-        const_cast<uint8_t*>(pSrcBitmap->GetScanline(src_top + row)) +
-        src_left * 4;
+    const uint8_t* src_scan =
+        pSrcBitmap->GetScanline(src_top + row) + src_left * 4;
     for (int col = 0; col < width; col++) {
       FXARGB_SETDIB(dest_scan,
                     ArgbEncode(0xff, src_scan[0], src_scan[1], src_scan[2]));
diff --git a/core/fxge/dib/cfx_bitmapcomposer.cpp b/core/fxge/dib/cfx_bitmapcomposer.cpp
index 3854949..22e1bc9 100644
--- a/core/fxge/dib/cfx_bitmapcomposer.cpp
+++ b/core/fxge/dib/cfx_bitmapcomposer.cpp
@@ -112,13 +112,11 @@
                     m_pClipMask->GetPitch() +
                 (m_DestLeft - m_pClipRgn->GetBox().left);
   }
-  uint8_t* dest_scan =
-      const_cast<uint8_t*>(m_pBitmap->GetScanline(line + m_DestTop)) +
-      m_DestLeft * m_pBitmap->GetBPP() / 8;
+  uint8_t* dest_scan = m_pBitmap->GetWritableScanline(line + m_DestTop) +
+                       m_DestLeft * m_pBitmap->GetBPP() / 8;
   uint8_t* dest_alpha_scan =
       m_pBitmap->m_pAlphaMask
-          ? const_cast<uint8_t*>(
-                m_pBitmap->m_pAlphaMask->GetScanline(line + m_DestTop)) +
+          ? m_pBitmap->m_pAlphaMask->GetWritableScanline(line + m_DestTop) +
                 m_DestLeft
           : nullptr;
   DoCompose(dest_scan, scanline, m_DestWidth, clip_scan, scan_extra_alpha,
diff --git a/core/fxge/dib/cfx_bitmapstorer.cpp b/core/fxge/dib/cfx_bitmapstorer.cpp
index f649e0c..d5b26f2 100644
--- a/core/fxge/dib/cfx_bitmapstorer.cpp
+++ b/core/fxge/dib/cfx_bitmapstorer.cpp
@@ -25,10 +25,10 @@
 void CFX_BitmapStorer::ComposeScanline(int line,
                                        const uint8_t* scanline,
                                        const uint8_t* scan_extra_alpha) {
-  uint8_t* dest_buf = const_cast<uint8_t*>(m_pBitmap->GetScanline(line));
+  uint8_t* dest_buf = m_pBitmap->GetWritableScanline(line);
   uint8_t* dest_alpha_buf =
       m_pBitmap->m_pAlphaMask
-          ? const_cast<uint8_t*>(m_pBitmap->m_pAlphaMask->GetScanline(line))
+          ? m_pBitmap->m_pAlphaMask->GetWritableScanline(line)
           : nullptr;
   if (dest_buf)
     memcpy(dest_buf, scanline, m_pBitmap->GetPitch());
diff --git a/core/fxge/dib/cfx_dibitmap.cpp b/core/fxge/dib/cfx_dibitmap.cpp
index f17ca52..3d642c2 100644
--- a/core/fxge/dib/cfx_dibitmap.cpp
+++ b/core/fxge/dib/cfx_dibitmap.cpp
@@ -372,7 +372,7 @@
   int srcBytes = pSrcClone->GetBPP() / 8;
   int destBytes = pDst->GetBPP() / 8;
   for (int row = 0; row < m_Height; row++) {
-    uint8_t* dest_pos = (uint8_t*)pDst->GetScanline(row) + destOffset;
+    uint8_t* dest_pos = pDst->GetWritableScanline(row) + destOffset;
     const uint8_t* src_pos = pSrcClone->GetScanline(row) + srcOffset;
     for (int col = 0; col < m_Width; col++) {
       *dest_pos = *src_pos;
@@ -923,7 +923,7 @@
                       : nullptr;
     uint8_t* dst_scan_extra_alpha =
         m_pAlphaMask
-            ? (uint8_t*)m_pAlphaMask->GetScanline(dest_top + row) + dest_left
+            ? m_pAlphaMask->GetWritableScanline(dest_top + row) + dest_left
             : nullptr;
     const uint8_t* clip_scan = nullptr;
     if (pClipMask) {
@@ -995,7 +995,7 @@
     const uint8_t* src_scan = pMask->GetScanline(src_top + row);
     uint8_t* dst_scan_extra_alpha =
         m_pAlphaMask
-            ? (uint8_t*)m_pAlphaMask->GetScanline(dest_top + row) + dest_left
+            ? m_pAlphaMask->GetWritableScanline(dest_top + row) + dest_left
             : nullptr;
     const uint8_t* clip_scan = nullptr;
     if (pClipMask) {
@@ -1084,10 +1084,8 @@
       index = (static_cast<uint8_t>(color) == 0xff) ? 1 : 0;
     }
     for (int row = rect.top; row < rect.bottom; row++) {
-      uint8_t* dest_scan_top =
-          const_cast<uint8_t*>(GetScanline(row)) + rect.left / 8;
-      uint8_t* dest_scan_top_r =
-          const_cast<uint8_t*>(GetScanline(row)) + rect.right / 8;
+      uint8_t* dest_scan_top = GetWritableScanline(row) + rect.left / 8;
+      uint8_t* dest_scan_top_r = GetWritableScanline(row) + rect.right / 8;
       uint8_t left_flag = *dest_scan_top & (255 << (8 - left_shift));
       uint8_t right_flag = *dest_scan_top_r & (255 >> right_shift);
       if (new_width) {
@@ -1126,7 +1124,7 @@
     for (int row = rect.top; row < rect.bottom; row++) {
       uint8_t* dest_scan = m_pBuffer.Get() + row * m_Pitch + rect.left * Bpp;
       uint8_t* dest_scan_alpha =
-          m_pAlphaMask ? (uint8_t*)m_pAlphaMask->GetScanline(row) + rect.left
+          m_pAlphaMask ? m_pAlphaMask->GetWritableScanline(row) + rect.left
                        : nullptr;
       if (dest_scan_alpha) {
         memset(dest_scan_alpha, 0xff, width);
@@ -1171,7 +1169,7 @@
         }
       } else {
         uint8_t* dest_scan_alpha =
-            (uint8_t*)m_pAlphaMask->GetScanline(row) + rect.left;
+            m_pAlphaMask->GetWritableScanline(row) + rect.left;
         for (int col = 0; col < width; col++) {
           uint8_t back_alpha = *dest_scan_alpha;
           if (back_alpha == 0) {
diff --git a/core/fxge/dib/cfx_dibsource.cpp b/core/fxge/dib/cfx_dibsource.cpp
index 7575477..4608b51 100644
--- a/core/fxge/dib/cfx_dibsource.cpp
+++ b/core/fxge/dib/cfx_dibsource.cpp
@@ -349,11 +349,10 @@
   }
   int32_t lut_1 = lut - 1;
   for (int row = 0; row < height; ++row) {
-    uint8_t* src_scan =
-        const_cast<uint8_t*>(pSrcBitmap->GetScanline(src_top + row)) + src_left;
+    const uint8_t* src_scan = pSrcBitmap->GetScanline(src_top + row) + src_left;
     uint8_t* dest_scan = dest_buf + row * dest_pitch;
     for (int col = 0; col < width; ++col) {
-      uint8_t* src_port = src_scan + col * bpp;
+      const uint8_t* src_port = src_scan + col * bpp;
       int r = src_port[2] & 0xf0;
       int g = src_port[1] & 0xf0;
       int b = src_port[0] & 0xf0;
@@ -748,8 +747,10 @@
     int right_shift = 32 - left_shift;
     int dword_count = pNewBitmap->m_Pitch / 4;
     for (int row = rect.top; row < rect.bottom; ++row) {
-      uint32_t* src_scan = (uint32_t*)GetScanline(row) + rect.left / 32;
-      uint32_t* dest_scan = (uint32_t*)pNewBitmap->GetScanline(row - rect.top);
+      const uint32_t* src_scan =
+          reinterpret_cast<const uint32_t*>(GetScanline(row)) + rect.left / 32;
+      uint32_t* dest_scan = reinterpret_cast<uint32_t*>(
+          pNewBitmap->GetWritableScanline(row - rect.top));
       for (int i = 0; i < dword_count; ++i) {
         dest_scan[i] =
             (src_scan[i] << left_shift) | (src_scan[i + 1] >> right_shift);
@@ -762,7 +763,7 @@
 
     for (int row = rect.top; row < rect.bottom; ++row) {
       const uint8_t* src_scan = GetScanline(row) + rect.left * m_bpp / 8;
-      uint8_t* dest_scan = (uint8_t*)pNewBitmap->GetScanline(row - rect.top);
+      uint8_t* dest_scan = pNewBitmap->GetWritableScanline(row - rect.top);
       memcpy(dest_scan, src_scan, copy_len);
     }
   }
@@ -932,8 +933,7 @@
 
   for (int row = rect.top; row < rect.bottom; ++row) {
     const uint8_t* src_scan = GetScanline(row) + rect.left * 4 + 3;
-    uint8_t* dest_scan =
-        const_cast<uint8_t*>(pMask->GetScanline(row - rect.top));
+    uint8_t* dest_scan = pMask->GetWritableScanline(row - rect.top);
     for (int col = rect.left; col < rect.right; ++col) {
       *dest_scan++ = *src_scan;
       src_scan += 4;
@@ -963,7 +963,7 @@
       return false;
   }
   for (int row = 0; row < m_Height; ++row) {
-    memcpy(const_cast<uint8_t*>(m_pAlphaMask->GetScanline(row)),
+    memcpy(m_pAlphaMask->GetWritableScanline(row),
            pAlphaMask->GetScanline(row + rect.top) + rect.left,
            m_pAlphaMask->m_Pitch);
   }
@@ -1126,7 +1126,8 @@
       if (bYFlip)
         dest_scan += (result_height - 1) * dest_pitch;
       if (nBytes == 4) {
-        uint32_t* src_scan = (uint32_t*)GetScanline(row) + col_start;
+        const uint32_t* src_scan =
+            reinterpret_cast<const uint32_t*>(GetScanline(row)) + col_start;
         for (int col = col_start; col < col_end; ++col) {
           *(uint32_t*)dest_scan = *src_scan++;
           dest_scan += dest_step;
diff --git a/core/fxge/dib/cfx_dibsource.h b/core/fxge/dib/cfx_dibsource.h
index 0e7fb27..064dbe2 100644
--- a/core/fxge/dib/cfx_dibsource.h
+++ b/core/fxge/dib/cfx_dibsource.h
@@ -44,6 +44,9 @@
                                   int clip_left,
                                   int clip_width) const = 0;
 
+  uint8_t* GetWritableScanline(int line) {
+    return const_cast<uint8_t*>(GetScanline(line));
+  }
   int GetWidth() const { return m_Width; }
   int GetHeight() const { return m_Height; }
 
diff --git a/core/fxge/dib/cfx_imagetransformer.cpp b/core/fxge/dib/cfx_imagetransformer.cpp
index 9cd5cea..37f56b5 100644
--- a/core/fxge/dib/cfx_imagetransformer.cpp
+++ b/core/fxge/dib/cfx_imagetransformer.cpp
@@ -480,7 +480,7 @@
     std::function<void(const BilinearData&, uint8_t*)> func) {
   CFX_BilinearMatrix matrix_fix(cdata.matrix);
   for (int row = 0; row < m_result.Height(); row++) {
-    uint8_t* dest = const_cast<uint8_t*>(cdata.bitmap->GetScanline(row));
+    const uint8_t* dest = cdata.bitmap->GetScanline(row);
     for (int col = 0; col < m_result.Width(); col++) {
       BilinearData d;
       d.res_x = 0;
@@ -496,7 +496,7 @@
         AdjustCoords(&d.src_col_r, &d.src_row_r);
         d.row_offset_l = d.src_row_l * cdata.pitch;
         d.row_offset_r = d.src_row_r * cdata.pitch;
-        func(d, dest);
+        func(d, const_cast<uint8_t*>(dest));
       }
       dest += increment;
     }
@@ -509,7 +509,7 @@
     std::function<void(const BicubicData&, uint8_t*)> func) {
   CFX_BilinearMatrix matrix_fix(cdata.matrix);
   for (int row = 0; row < m_result.Height(); row++) {
-    uint8_t* dest = const_cast<uint8_t*>(cdata.bitmap->GetScanline(row));
+    const uint8_t* dest = cdata.bitmap->GetScanline(row);
     for (int col = 0; col < m_result.Width(); col++) {
       BicubicData d;
       d.res_x = 0;
@@ -523,7 +523,7 @@
         bicubic_get_pos_weight(d.pos_pixel, d.u_w, d.v_w, d.src_col_l,
                                d.src_row_l, d.res_x, d.res_y, stretch_width(),
                                stretch_height());
-        func(d, dest);
+        func(d, const_cast<uint8_t*>(dest));
       }
       dest += increment;
     }
@@ -536,7 +536,7 @@
     std::function<void(const DownSampleData&, uint8_t*)> func) {
   CPDF_FixedMatrix matrix_fix(cdata.matrix);
   for (int row = 0; row < m_result.Height(); row++) {
-    uint8_t* dest = const_cast<uint8_t*>(cdata.bitmap->GetScanline(row));
+    const uint8_t* dest = cdata.bitmap->GetScanline(row);
     for (int col = 0; col < m_result.Width(); col++) {
       DownSampleData d;
       d.src_col = 0;
@@ -544,7 +544,7 @@
       matrix_fix.Transform(col, row, &d.src_col, &d.src_row);
       if (LIKELY(InStretchBounds(d.src_col, d.src_row))) {
         AdjustCoords(&d.src_col, &d.src_row);
-        func(d, dest);
+        func(d, const_cast<uint8_t*>(dest));
       }
       dest += increment;
     }
diff --git a/core/fxge/skia/fx_skia_device.cpp b/core/fxge/skia/fx_skia_device.cpp
index 4fa5a08..0b96cdc 100644
--- a/core/fxge/skia/fx_skia_device.cpp
+++ b/core/fxge/skia/fx_skia_device.cpp
@@ -80,8 +80,8 @@
   if (dest_format == src_format) {
     for (int row = 0; row < height; row++) {
       uint8_t* dest_scan = buffer + (dest_top + row) * pitch + dest_left * Bpp;
-      uint8_t* src_scan =
-          (uint8_t*)pSrcBitmap->GetScanline(src_top + row) + src_left * Bpp;
+      const uint8_t* src_scan =
+          pSrcBitmap->GetScanline(src_top + row) + src_left * Bpp;
       if (Bpp == 4) {
         for (int col = 0; col < width; col++) {
           FXARGB_SETDIB(dest_scan, ArgbEncode(src_scan[3], src_scan[0],
@@ -106,8 +106,8 @@
     if (src_format == FXDIB_Rgb32) {
       for (int row = 0; row < height; row++) {
         uint8_t* dest_scan = dest_buf + row * pitch;
-        uint8_t* src_scan =
-            (uint8_t*)pSrcBitmap->GetScanline(src_top + row) + src_left * 4;
+        const uint8_t* src_scan =
+            pSrcBitmap->GetScanline(src_top + row) + src_left * 4;
         for (int col = 0; col < width; col++) {
           *dest_scan++ = src_scan[2];
           *dest_scan++ = src_scan[1];
@@ -125,8 +125,8 @@
     if (src_format == FXDIB_Rgb) {
       for (int row = 0; row < height; row++) {
         uint8_t* dest_scan = (uint8_t*)(dest_buf + row * pitch);
-        uint8_t* src_scan =
-            (uint8_t*)pSrcBitmap->GetScanline(src_top + row) + src_left * 3;
+        const uint8_t* src_scan =
+            pSrcBitmap->GetScanline(src_top + row) + src_left * 3;
         for (int col = 0; col < width; col++) {
           FXARGB_SETDIB(dest_scan, ArgbEncode(0xff, src_scan[0], src_scan[1],
                                               src_scan[2]));
@@ -138,8 +138,8 @@
       ASSERT(dest_format == FXDIB_Argb);
       for (int row = 0; row < height; row++) {
         uint8_t* dest_scan = dest_buf + row * pitch;
-        uint8_t* src_scan =
-            (uint8_t*)(pSrcBitmap->GetScanline(src_top + row) + src_left * 4);
+        const uint8_t* src_scan =
+            pSrcBitmap->GetScanline(src_top + row) + src_left * 4;
         for (int col = 0; col < width; col++) {
           FXARGB_SETDIB(dest_scan, ArgbEncode(0xff, src_scan[0], src_scan[1],
                                               src_scan[2]));