Remove UNSAFE_TODO() in core/fpdfapi/page/cpdf_transferfuncdib.cpp

Switch to spans and Zip(). Get rid of the INCR_ON_APPLE() macro and
replace it with MakePlatformRGBStruct(). Then it becomes a bit more
obvious why Apple platforms behave differently.

Bug: 42271176
Change-Id: I39ef9f565614dfe5e8e74b933396fd9d17a0d007
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/121572
Reviewed-by: Tom Sepez <tsepez@google.com>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/page/cpdf_transferfuncdib.cpp b/core/fpdfapi/page/cpdf_transferfuncdib.cpp
index 460f59f..689022b 100644
--- a/core/fpdfapi/page/cpdf_transferfuncdib.cpp
+++ b/core/fpdfapi/page/cpdf_transferfuncdib.cpp
@@ -10,16 +10,24 @@
 
 #include "build/build_config.h"
 #include "core/fpdfapi/page/cpdf_transferfunc.h"
-#include "core/fpdfapi/parser/cpdf_dictionary.h"
 #include "core/fxcrt/check.h"
-#include "core/fxcrt/compiler_specific.h"
+#include "core/fxcrt/zip.h"
 #include "core/fxge/calculate_pitch.h"
 
-#if BUILDFLAG(IS_APPLE)
-#define INCR_ON_APPLE(x) ++x
-#else
-#define INCR_ON_APPLE(x)
-#endif
+namespace {
+
+CFX_DIBBase::kPlatformRGBStruct MakePlatformRGBStruct(uint8_t red,
+                                                      uint8_t green,
+                                                      uint8_t blue) {
+  // Note that the return value may have an alpha value that will be set to 0.
+  return {
+      .blue = blue,
+      .green = green,
+      .red = red,
+  };
+}
+
+}  // namespace
 
 CPDF_TransferFuncDIB::CPDF_TransferFuncDIB(
     RetainPtr<const CFX_DIBBase> src,
@@ -53,112 +61,93 @@
 
 void CPDF_TransferFuncDIB::TranslateScanline(
     pdfium::span<const uint8_t> src_span) const {
-  const uint8_t* src_buf = src_span.data();
-  bool skip = false;
+  auto scanline_span = pdfium::make_span(scanline_);
   switch (src_->GetFormat()) {
     case FXDIB_Format::kInvalid: {
       break;
     }
     case FXDIB_Format::k1bppRgb: {
-      int r0 = r_samples_[0];
-      int g0 = g_samples_[0];
-      int b0 = b_samples_[0];
-      int r1 = r_samples_[255];
-      int g1 = g_samples_[255];
-      int b1 = b_samples_[255];
-      int index = 0;
-      UNSAFE_TODO({
-        for (int i = 0; i < GetWidth(); i++) {
-          if (src_buf[i / 8] & (1 << (7 - i % 8))) {
-            scanline_[index++] = b1;
-            scanline_[index++] = g1;
-            scanline_[index++] = r1;
-          } else {
-            scanline_[index++] = b0;
-            scanline_[index++] = g0;
-            scanline_[index++] = r0;
-          }
-          INCR_ON_APPLE(index);
-        }
-      });
+      const auto color0 =
+          MakePlatformRGBStruct(r_samples_[0], g_samples_[0], b_samples_[0]);
+      const auto color1 = MakePlatformRGBStruct(
+          r_samples_[255], g_samples_[255], b_samples_[255]);
+      auto dest = fxcrt::reinterpret_span<kPlatformRGBStruct>(scanline_span);
+      for (int i = 0; i < GetWidth(); i++) {
+        const bool is_on = (src_span[i / 8] & (1 << (7 - i % 8)));
+        dest[i] = is_on ? color1 : color0;
+      }
       break;
     }
     case FXDIB_Format::k1bppMask: {
-      int m0 = r_samples_[0];
-      int m1 = r_samples_[255];
-      int index = 0;
-      UNSAFE_TODO({
-        for (int i = 0; i < GetWidth(); i++) {
-          if (src_buf[i / 8] & (1 << (7 - i % 8))) {
-            scanline_[index++] = m1;
-          } else {
-            scanline_[index++] = m0;
-          }
-        }
-      });
+      const int m0 = r_samples_[0];
+      const int m1 = r_samples_[255];
+      for (int i = 0; i < GetWidth(); i++) {
+        const bool is_on = (src_span[i / 8] & (1 << (7 - i % 8)));
+        scanline_[i] = is_on ? m1 : m0;
+      }
       break;
     }
     case FXDIB_Format::k8bppRgb: {
       pdfium::span<const uint32_t> src_palette = src_->GetPaletteSpan();
-      int index = 0;
-      UNSAFE_TODO({
-        for (int i = 0; i < GetWidth(); i++) {
-          if (src_->HasPalette()) {
-            FX_ARGB src_argb = src_palette[*src_buf];
-            scanline_[index++] = b_samples_[FXARGB_R(src_argb)];
-            scanline_[index++] = g_samples_[FXARGB_G(src_argb)];
-            scanline_[index++] = r_samples_[FXARGB_B(src_argb)];
-          } else {
-            uint32_t src_byte = *src_buf;
-            scanline_[index++] = b_samples_[src_byte];
-            scanline_[index++] = g_samples_[src_byte];
-            scanline_[index++] = r_samples_[src_byte];
-          }
-          src_buf++;
-          INCR_ON_APPLE(index);
+      auto dest = fxcrt::reinterpret_span<kPlatformRGBStruct>(scanline_span);
+      auto zip = fxcrt::Zip(src_span.first(GetWidth()), dest);
+      if (src_->HasPalette()) {
+        for (auto [input, output] : zip) {
+          const FX_ARGB src_argb = src_palette[input];
+          output = MakePlatformRGBStruct(r_samples_[FXARGB_B(src_argb)],
+                                         g_samples_[FXARGB_G(src_argb)],
+                                         b_samples_[FXARGB_R(src_argb)]);
         }
-      });
+      } else {
+        for (auto [input, output] : zip) {
+          output = MakePlatformRGBStruct(r_samples_[input], g_samples_[input],
+                                         b_samples_[input]);
+        }
+      }
       break;
     }
     case FXDIB_Format::k8bppMask: {
-      int index = 0;
-      UNSAFE_TODO({
-        for (int i = 0; i < GetWidth(); i++) {
-          scanline_[index++] = r_samples_[*(src_buf++)];
-        }
-      });
+      for (auto [input, output] :
+           fxcrt::Zip(src_span.first(GetWidth()), scanline_span)) {
+        output = r_samples_[input];
+      }
       break;
     }
     case FXDIB_Format::kRgb: {
-      int index = 0;
-      UNSAFE_TODO({
-        for (int i = 0; i < GetWidth(); i++) {
-          scanline_[index++] = b_samples_[*(src_buf++)];
-          scanline_[index++] = g_samples_[*(src_buf++)];
-          scanline_[index++] = r_samples_[*(src_buf++)];
-          INCR_ON_APPLE(index);
-        }
-      });
+      auto src =
+          fxcrt::reinterpret_span<const FX_BGR_STRUCT<uint8_t>>(src_span);
+      auto dest = fxcrt::reinterpret_span<kPlatformRGBStruct>(scanline_span);
+      for (auto [input, output] : fxcrt::Zip(src.first(GetWidth()), dest)) {
+        output = MakePlatformRGBStruct(r_samples_[input.red],
+                                       g_samples_[input.green],
+                                       b_samples_[input.blue]);
+      }
       break;
     }
-    case FXDIB_Format::kRgb32:
-      skip = true;
-      [[fallthrough]];
+    case FXDIB_Format::kRgb32: {
+      auto src =
+          fxcrt::reinterpret_span<const FX_BGRA_STRUCT<uint8_t>>(src_span);
+      auto dest = fxcrt::reinterpret_span<kPlatformRGBStruct>(scanline_span);
+      for (auto [input, output] : fxcrt::Zip(src.first(GetWidth()), dest)) {
+        output = MakePlatformRGBStruct(r_samples_[input.red],
+                                       g_samples_[input.green],
+                                       b_samples_[input.blue]);
+      }
+      break;
+    }
     case FXDIB_Format::kArgb: {
-      int index = 0;
-      UNSAFE_TODO({
-        for (int i = 0; i < GetWidth(); i++) {
-          scanline_[index++] = b_samples_[*(src_buf++)];
-          scanline_[index++] = g_samples_[*(src_buf++)];
-          scanline_[index++] = r_samples_[*(src_buf++)];
-          if (skip) {
-            INCR_ON_APPLE(index);
-          } else {
-            scanline_[index++] = *src_buf;
-          }
-          src_buf++;
-        }
-      });
+      auto src =
+          fxcrt::reinterpret_span<const FX_BGRA_STRUCT<uint8_t>>(src_span);
+      auto dest =
+          fxcrt::reinterpret_span<FX_BGRA_STRUCT<uint8_t>>(scanline_span);
+      for (auto [input, output] : fxcrt::Zip(src.first(GetWidth()), dest)) {
+        output = {
+            .blue = b_samples_[input.blue],
+            .green = g_samples_[input.green],
+            .red = r_samples_[input.red],
+            .alpha = input.alpha,
+        };
+      }
       break;
     }
   }
diff --git a/core/fxge/dib/cfx_dibbase.h b/core/fxge/dib/cfx_dibbase.h
index ec9ca09..756acc7 100644
--- a/core/fxge/dib/cfx_dibbase.h
+++ b/core/fxge/dib/cfx_dibbase.h
@@ -37,8 +37,10 @@
 #if BUILDFLAG(IS_APPLE)
   // Matches Apple's kCGBitmapByteOrder32Little in fx_quartz_device.cpp.
   static constexpr FXDIB_Format kPlatformRGBFormat = FXDIB_Format::kRgb32;
+  using kPlatformRGBStruct = FX_BGRA_STRUCT<uint8_t>;
 #else   // BUILDFLAG(IS_APPLE)
   static constexpr FXDIB_Format kPlatformRGBFormat = FXDIB_Format::kRgb;
+  using kPlatformRGBStruct = FX_BGR_STRUCT<uint8_t>;
 #endif  // BUILDFLAG(IS_APPLE)
 
   static constexpr uint32_t kPaletteSize = 256;