Get rid of UNSAFE_TODOs in ARGB to 8 BPP CompositeRow functions

Convert CompositeRow_AlphaToMask() and CompositeRow_Argb2Gray() using
Zip() and color structs.

Bug: 42271176
Change-Id: Ie2347b6659d5b313e620f1d1b06bb006071422be
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/123076
Reviewed-by: Tom Sepez <tsepez@google.com>
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fxge/dib/cfx_scanlinecompositor.cpp b/core/fxge/dib/cfx_scanlinecompositor.cpp
index 9473107..f7ab405 100644
--- a/core/fxge/dib/cfx_scanlinecompositor.cpp
+++ b/core/fxge/dib/cfx_scanlinecompositor.cpp
@@ -154,28 +154,34 @@
   output.red = FXDIB_ALPHA_MERGE(input.red, output.red, alpha);
 }
 
-void CompositeRow_AlphaToMask(pdfium::span<uint8_t> dest_span,
-                              pdfium::span<const uint8_t> src_span,
-                              int pixel_count,
-                              pdfium::span<const uint8_t> clip_span,
-                              uint8_t stride) {
-  uint8_t* dest_scan = dest_span.data();
-  const uint8_t* src_scan = src_span.data();
-  const uint8_t* clip_scan = clip_span.data();
-  UNSAFE_TODO({
-    src_scan += stride - 1;
-    for (int col = 0; col < pixel_count; ++col) {
-      int src_alpha = GetAlpha(*src_scan, clip_scan, col);
-      uint8_t back_alpha = *dest_scan;
-      if (!back_alpha) {
-        *dest_scan = src_alpha;
-      } else if (src_alpha) {
-        *dest_scan = back_alpha + src_alpha - back_alpha * src_alpha / 255;
-      }
-      ++dest_scan;
-      src_scan += stride;
+void CompositePixelArgb2Mask(const FX_BGRA_STRUCT<uint8_t>& input,
+                             uint8_t clip,
+                             uint8_t& output) {
+  const uint8_t src_alpha = input.alpha * clip / 255;
+  if (output == 0) {
+    output = src_alpha;
+    return;
+  }
+  if (src_alpha == 0) {
+    return;
+  }
+  output = FXDIB_ALPHA_UNION(output, src_alpha);
+}
+
+void CompositeRowArgb2Mask(pdfium::span<const FX_BGRA_STRUCT<uint8_t>> src_span,
+                           pdfium::span<const uint8_t> clip_span,
+                           pdfium::span<uint8_t> dest_span) {
+  if (clip_span.empty()) {
+    for (auto [input, output] : fxcrt::Zip(src_span, dest_span)) {
+      CompositePixelArgb2Mask(input, /*clip=*/255, output);
     }
-  });
+    return;
+  }
+
+  for (auto [input, clip, output] :
+       fxcrt::Zip(src_span, clip_span, dest_span)) {
+    CompositePixelArgb2Mask(input, clip, output);
+  }
 }
 
 void CompositeRow_Rgb2Mask(pdfium::span<uint8_t> dest_span,
@@ -208,41 +214,48 @@
   }
 }
 
-uint8_t GetGray(const uint8_t* src_scan) {
-  return UNSAFE_TODO(FXRGB2GRAY(src_scan[2], src_scan[1], *src_scan));
-}
-
-uint8_t GetGrayWithBlend(const uint8_t* src_scan,
-                         const uint8_t* dest_scan,
+template <typename T>
+uint8_t GetGrayWithBlend(const T& input,
+                         uint8_t output_value,
                          BlendMode blend_type) {
-  uint8_t gray = GetGray(src_scan);
-  if (IsNonSeparableBlendMode(blend_type))
-    gray = blend_type == BlendMode::kLuminosity ? gray : *dest_scan;
-  else if (blend_type != BlendMode::kNormal)
-    gray = Blend(blend_type, *dest_scan, gray);
+  uint8_t gray = FXRGB2GRAY(input.red, input.green, input.blue);
+  if (IsNonSeparableBlendMode(blend_type)) {
+    return blend_type == BlendMode::kLuminosity ? gray : output_value;
+  }
+  if (blend_type != BlendMode::kNormal) {
+    return Blend(blend_type, output_value, gray);
+  }
   return gray;
 }
 
-void CompositeRow_Argb2Gray(pdfium::span<uint8_t> dest_span,
-                            pdfium::span<const uint8_t> src_span,
-                            int pixel_count,
-                            BlendMode blend_type,
-                            pdfium::span<const uint8_t> clip_span) {
-  uint8_t* dest_scan = dest_span.data();
-  const uint8_t* src_scan = src_span.data();
-  const uint8_t* clip_scan = clip_span.data();
-  constexpr size_t kOffset = 4;
-  UNSAFE_TODO({
-    for (int col = 0; col < pixel_count; ++col) {
-      int src_alpha = GetAlpha(src_scan[3], clip_scan, col);
-      if (src_alpha) {
-        uint8_t gray = GetGrayWithBlend(src_scan, dest_scan, blend_type);
-        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha);
-      }
-      ++dest_scan;
-      src_scan += kOffset;
+void CompositePixelArgb2Gray(const FX_BGRA_STRUCT<uint8_t>& input,
+                             uint8_t clip,
+                             uint8_t& output,
+                             BlendMode blend_type) {
+  const uint8_t src_alpha = input.alpha * clip / 255;
+  if (src_alpha == 0) {
+    return;
+  }
+
+  uint8_t gray = GetGrayWithBlend(input, output, blend_type);
+  output = FXDIB_ALPHA_MERGE(output, gray, src_alpha);
+}
+
+void CompositeRowArgb2Gray(pdfium::span<const FX_BGRA_STRUCT<uint8_t>> src_span,
+                           pdfium::span<const uint8_t> clip_span,
+                           pdfium::span<uint8_t> dest_span,
+                           BlendMode blend_type) {
+  if (clip_span.empty()) {
+    for (auto [input, output] : fxcrt::Zip(src_span, dest_span)) {
+      CompositePixelArgb2Gray(input, /*clip=*/255, output, blend_type);
     }
-  });
+    return;
+  }
+
+  for (auto [input, clip, output] :
+       fxcrt::Zip(src_span, clip_span, dest_span)) {
+    CompositePixelArgb2Gray(input, clip, output, blend_type);
+  }
 }
 
 void CompositeRow_Rgb2Gray(pdfium::span<uint8_t> dest_span,
@@ -256,7 +269,9 @@
   const uint8_t* clip_scan = clip_span.data();
   UNSAFE_TODO({
     for (int col = 0; col < pixel_count; ++col) {
-      uint8_t gray = GetGrayWithBlend(src_scan, dest_scan, blend_type);
+      FX_BGR_STRUCT input = {
+          .blue = src_scan[0], .green = src_scan[1], .red = src_scan[2]};
+      uint8_t gray = GetGrayWithBlend(input, *dest_scan, blend_type);
       if (clip_scan && clip_scan[col] < 255) {
         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, clip_scan[col]);
       } else {
@@ -2401,6 +2416,10 @@
     pdfium::span<const uint8_t> clip_scan) const {
   CHECK_EQ(m_SrcFormat, FXDIB_Format::kArgb);
 
+  auto src_span =
+      fxcrt::reinterpret_span<const FX_BGRA_STRUCT<uint8_t>>(src_scan).first(
+          width);
+
   switch (m_DestFormat) {
     case FXDIB_Format::kInvalid:
     case FXDIB_Format::k1bppRgb:
@@ -2409,19 +2428,15 @@
     }
     case FXDIB_Format::k8bppRgb: {
       CHECK(!m_bRgbByteOrder);  // Disallowed by Init();
-      CompositeRow_Argb2Gray(dest_scan, src_scan, width, m_BlendType,
-                             clip_scan);
+      CompositeRowArgb2Gray(src_span, clip_scan, dest_scan, m_BlendType);
       return;
     }
     case FXDIB_Format::k8bppMask: {
       CHECK(!m_bRgbByteOrder);  // Disallowed by Init();
-      CompositeRow_AlphaToMask(dest_scan, src_scan, width, clip_scan, 4);
+      CompositeRowArgb2Mask(src_span, clip_scan, dest_scan);
       return;
     }
     case FXDIB_Format::kRgb: {
-      auto src_span =
-          fxcrt::reinterpret_span<const FX_BGRA_STRUCT<uint8_t>>(src_scan)
-              .first(width);
       if (m_bRgbByteOrder) {
         auto dest_span =
             fxcrt::reinterpret_span<FX_RGB_STRUCT<uint8_t>>(dest_scan);
@@ -2435,9 +2450,6 @@
       return;
     }
     case FXDIB_Format::kRgb32: {
-      auto src_span =
-          fxcrt::reinterpret_span<const FX_BGRA_STRUCT<uint8_t>>(src_scan)
-              .first(width);
       if (m_bRgbByteOrder) {
         auto dest_span =
             fxcrt::reinterpret_span<FX_RGBA_STRUCT<uint8_t>>(dest_scan);
@@ -2451,9 +2463,6 @@
       return;
     }
     case FXDIB_Format::kArgb: {
-      auto src_span =
-          fxcrt::reinterpret_span<const FX_BGRA_STRUCT<uint8_t>>(src_scan)
-              .first(width);
       if (m_bRgbByteOrder) {
         auto dest_span =
             fxcrt::reinterpret_span<FX_RGBA_STRUCT<uint8_t>>(dest_scan);