Replace ArgbDecode() with ArgbToRGBAStruct()

Remove ArgbDecode() and replace it with ArgbToRGBAStruct(). In some
cases where the alpha value is not needed, use ArgbToBGRStruct()
instead. Then pass the struct around in several places instead of 3 or 4
separate parameters.

Change-Id: Id954975be17e27ac1084d9aa13fd6bfd499a95f0
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/121491
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/fpdfapi/page/cpdf_image.cpp b/core/fpdfapi/page/cpdf_image.cpp
index 9dd8428..f50f334 100644
--- a/core/fpdfapi/page/cpdf_image.cpp
+++ b/core/fpdfapi/page/cpdf_image.cpp
@@ -196,23 +196,15 @@
   size_t dest_pitch = 0;
   bool bCopyWithoutAlpha = true;
   if (bpp == 1) {
-    int32_t reset_a = 0;
-    int32_t reset_r = 0;
-    int32_t reset_g = 0;
-    int32_t reset_b = 0;
-    int32_t set_a = 0;
-    int32_t set_r = 0;
-    int32_t set_g = 0;
-    int32_t set_b = 0;
+    FX_BGRA_STRUCT<uint8_t> reset_bgra;
+    FX_BGRA_STRUCT<uint8_t> set_bgra;
     if (!pBitmap->IsMaskFormat()) {
-      std::tie(reset_a, reset_r, reset_g, reset_b) =
-          ArgbDecode(pBitmap->GetPaletteArgb(0));
-      std::tie(set_a, set_r, set_g, set_b) =
-          ArgbDecode(pBitmap->GetPaletteArgb(1));
+      reset_bgra = ArgbToBGRAStruct(pBitmap->GetPaletteArgb(0));
+      set_bgra = ArgbToBGRAStruct(pBitmap->GetPaletteArgb(1));
     }
-    if (set_a == 0 || reset_a == 0) {
+    if (set_bgra.alpha == 0 || reset_bgra.alpha == 0) {
       pDict->SetNewFor<CPDF_Boolean>("ImageMask", true);
-      if (reset_a == 0) {
+      if (reset_bgra.alpha == 0) {
         auto pArray = pDict->SetNewFor<CPDF_Array>("Decode");
         pArray->AppendNew<CPDF_Number>(1);
         pArray->AppendNew<CPDF_Number>(0);
@@ -222,10 +214,8 @@
       pCS->AppendNew<CPDF_Name>("Indexed");
       pCS->AppendNew<CPDF_Name>("DeviceRGB");
       pCS->AppendNew<CPDF_Number>(1);
-      uint8_t ct[6] = {
-          static_cast<uint8_t>(reset_r), static_cast<uint8_t>(reset_g),
-          static_cast<uint8_t>(reset_b), static_cast<uint8_t>(set_r),
-          static_cast<uint8_t>(set_g),   static_cast<uint8_t>(set_b)};
+      const uint8_t ct[6] = {reset_bgra.red, reset_bgra.green, reset_bgra.blue,
+                             set_bgra.red,   set_bgra.green,   set_bgra.blue};
       pCS->AppendNew<CPDF_String>(ct, CPDF_String::DataType::kIsHex);
     }
     pDict->SetNewFor<CPDF_Number>("BitsPerComponent", 1);
diff --git a/core/fpdfapi/render/cpdf_renderoptions.cpp b/core/fpdfapi/render/cpdf_renderoptions.cpp
index b8ac374..c53d418 100644
--- a/core/fpdfapi/render/cpdf_renderoptions.cpp
+++ b/core/fpdfapi/render/cpdf_renderoptions.cpp
@@ -36,13 +36,9 @@
   if (ColorModeIs(kAlpha))
     return argb;
 
-  int a;
-  int r;
-  int g;
-  int b;
-  std::tie(a, r, g, b) = ArgbDecode(argb);
-  int gray = FXRGB2GRAY(r, g, b);
-  return ArgbEncode(a, gray, gray, gray);
+  const FX_BGRA_STRUCT<uint8_t> bgra = ArgbToBGRAStruct(argb);
+  const int gray = FXRGB2GRAY(bgra.red, bgra.green, bgra.blue);
+  return ArgbEncode(bgra.alpha, gray, gray, gray);
 }
 
 FX_ARGB CPDF_RenderOptions::TranslateObjectFillColor(
diff --git a/core/fxge/agg/fx_agg_driver.cpp b/core/fxge/agg/fx_agg_driver.cpp
index e940c82..54931d1 100644
--- a/core/fxge/agg/fx_agg_driver.cpp
+++ b/core/fxge/agg/fx_agg_driver.cpp
@@ -474,9 +474,8 @@
   }
 
   int m_Alpha;
-  int m_Red;
-  int m_Green;
-  int m_Blue;
+  FX_BGR_STRUCT<uint8_t> m_BGR;
+  // TODO(thestig): Should `m_BGR` and `m_Gray` be together in a variant?
   int m_Gray;
   const uint32_t m_Color;
   const bool m_bFullCover;
@@ -501,6 +500,7 @@
                                  const uint8_t* clip_scan) {
   int col_start = GetColStart(span_left, clip_left);
   int col_end = GetColEnd(span_left, span_len, clip_right);
+  const auto& bgr = m_BGR;
   UNSAFE_TODO({
     if (Bpp) {
       dest_scan += col_start * Bpp;
@@ -519,17 +519,17 @@
           int alpha_ratio = src_alpha * 255 / dest_alpha;
           if (m_bFullCover) {
             *dest_scan++ =
-                FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Red, alpha_ratio);
+                FXDIB_ALPHA_MERGE(*backdrop_scan++, bgr.red, alpha_ratio);
             *dest_scan++ =
-                FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Green, alpha_ratio);
+                FXDIB_ALPHA_MERGE(*backdrop_scan++, bgr.green, alpha_ratio);
             *dest_scan++ =
-                FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Blue, alpha_ratio);
+                FXDIB_ALPHA_MERGE(*backdrop_scan++, bgr.blue, alpha_ratio);
             dest_scan++;
             backdrop_scan++;
           } else {
-            int r = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Red, alpha_ratio);
-            int g = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Green, alpha_ratio);
-            int b = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Blue, alpha_ratio);
+            int r = FXDIB_ALPHA_MERGE(*backdrop_scan++, bgr.red, alpha_ratio);
+            int g = FXDIB_ALPHA_MERGE(*backdrop_scan++, bgr.green, alpha_ratio);
+            int b = FXDIB_ALPHA_MERGE(*backdrop_scan++, bgr.blue, alpha_ratio);
             backdrop_scan++;
             *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]);
             dest_scan++;
@@ -544,9 +544,9 @@
       if (Bpp == 3 || Bpp == 4) {
         for (int col = col_start; col < col_end; col++) {
           int src_alpha = GetSrcAlpha(clip_scan, col);
-          int r = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Red, src_alpha);
-          int g = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Green, src_alpha);
-          int b = FXDIB_ALPHA_MERGE(*backdrop_scan, m_Blue, src_alpha);
+          int r = FXDIB_ALPHA_MERGE(*backdrop_scan++, bgr.red, src_alpha);
+          int g = FXDIB_ALPHA_MERGE(*backdrop_scan++, bgr.green, src_alpha);
+          int b = FXDIB_ALPHA_MERGE(*backdrop_scan, bgr.blue, src_alpha);
           backdrop_scan += Bpp - 2;
           *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, r, cover_scan[col]);
           dest_scan++;
@@ -568,27 +568,27 @@
         }
         if (cover_scan[col] == 255) {
           dest_scan[3] = src_alpha_covered;
-          *dest_scan++ = m_Blue;
-          *dest_scan++ = m_Green;
-          *dest_scan = m_Red;
+          *dest_scan++ = bgr.blue;
+          *dest_scan++ = bgr.green;
+          *dest_scan = bgr.red;
           dest_scan += 2;
           continue;
         }
         if (dest_scan[3] == 0) {
           dest_scan[3] = src_alpha_covered;
-          *dest_scan++ = m_Blue;
-          *dest_scan++ = m_Green;
-          *dest_scan = m_Red;
+          *dest_scan++ = bgr.blue;
+          *dest_scan++ = bgr.green;
+          *dest_scan = bgr.red;
           dest_scan += 2;
           continue;
         }
         uint8_t cover = cover_scan[col];
         dest_scan[3] = FXDIB_ALPHA_MERGE(dest_scan[3], src_alpha, cover);
-        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, cover);
+        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, bgr.blue, cover);
         dest_scan++;
-        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, cover);
+        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, bgr.green, cover);
         dest_scan++;
-        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, cover);
+        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, bgr.red, cover);
         dest_scan += 2;
       }
       return;
@@ -597,17 +597,18 @@
       for (int col = col_start; col < col_end; col++) {
         int src_alpha = GetSrcAlpha(clip_scan, col);
         if (m_bFullCover) {
-          *dest_scan++ = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Blue, src_alpha);
           *dest_scan++ =
-              FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Green, src_alpha);
-          *dest_scan = FXDIB_ALPHA_MERGE(*backdrop_scan, m_Red, src_alpha);
+              FXDIB_ALPHA_MERGE(*backdrop_scan++, bgr.blue, src_alpha);
+          *dest_scan++ =
+              FXDIB_ALPHA_MERGE(*backdrop_scan++, bgr.green, src_alpha);
+          *dest_scan = FXDIB_ALPHA_MERGE(*backdrop_scan, bgr.red, src_alpha);
           dest_scan += Bpp - 2;
           backdrop_scan += Bpp - 2;
           continue;
         }
-        int b = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Blue, src_alpha);
-        int g = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Green, src_alpha);
-        int r = FXDIB_ALPHA_MERGE(*backdrop_scan, m_Red, src_alpha);
+        int b = FXDIB_ALPHA_MERGE(*backdrop_scan++, bgr.blue, src_alpha);
+        int g = FXDIB_ALPHA_MERGE(*backdrop_scan++, bgr.green, src_alpha);
+        int r = FXDIB_ALPHA_MERGE(*backdrop_scan, bgr.red, src_alpha);
         backdrop_scan += Bpp - 2;
         *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, b, cover_scan[col]);
         dest_scan++;
@@ -619,14 +620,16 @@
       return;
     }
     if (Bpp == 1) {
+      const int gray = m_Gray;
       for (int col = col_start; col < col_end; col++) {
         int src_alpha = GetSrcAlpha(clip_scan, col);
         if (m_bFullCover) {
-          *dest_scan = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Gray, src_alpha);
+          *dest_scan = FXDIB_ALPHA_MERGE(*backdrop_scan++, gray, src_alpha);
           continue;
         }
-        int gray = FXDIB_ALPHA_MERGE(*backdrop_scan++, m_Gray, src_alpha);
-        *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, cover_scan[col]);
+        int gray_merged = FXDIB_ALPHA_MERGE(*backdrop_scan++, gray, src_alpha);
+        *dest_scan =
+            FXDIB_ALPHA_MERGE(*dest_scan, gray_merged, cover_scan[col]);
         dest_scan++;
       }
       return;
@@ -663,15 +666,16 @@
   DCHECK(!m_bRgbByteOrder);
   int col_start = GetColStart(span_left, clip_left);
   int col_end = GetColEnd(span_left, span_len, clip_right);
+  const int gray = m_Gray;
   UNSAFE_TODO({
     dest_scan += col_start;
     for (int col = col_start; col < col_end; col++) {
       int src_alpha = GetSourceAlpha(cover_scan, clip_scan, col);
       if (src_alpha) {
         if (src_alpha == 255) {
-          *dest_scan = m_Gray;
+          *dest_scan = gray;
         } else {
-          *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Gray, src_alpha);
+          *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, gray, src_alpha);
         }
       }
       dest_scan++;
@@ -689,6 +693,7 @@
                                      const uint8_t* clip_scan) {
   int col_start = GetColStart(span_left, clip_left);
   int col_end = GetColEnd(span_left, span_len, clip_right);
+  const auto& bgr = m_BGR;
   UNSAFE_TODO({
     dest_scan += col_start * Bpp;
     if (m_bRgbByteOrder) {
@@ -704,11 +709,11 @@
                 dest_scan[3] + src_alpha - dest_scan[3] * src_alpha / 255;
             dest_scan[3] = dest_alpha;
             int alpha_ratio = src_alpha * 255 / dest_alpha;
-            *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio);
+            *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, bgr.red, alpha_ratio);
             dest_scan++;
-            *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio);
+            *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, bgr.green, alpha_ratio);
             dest_scan++;
-            *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio);
+            *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, bgr.blue, alpha_ratio);
             dest_scan += 2;
             continue;
           }
@@ -726,9 +731,9 @@
         } else {
           if (dest_scan[3] == 0) {
             dest_scan[3] = src_alpha;
-            *dest_scan++ = m_Blue;
-            *dest_scan++ = m_Green;
-            *dest_scan = m_Red;
+            *dest_scan++ = bgr.blue;
+            *dest_scan++ = bgr.green;
+            *dest_scan = bgr.red;
             dest_scan += 2;
             continue;
           }
@@ -736,11 +741,11 @@
               dest_scan[3] + src_alpha - dest_scan[3] * src_alpha / 255;
           dest_scan[3] = dest_alpha;
           int alpha_ratio = src_alpha * 255 / dest_alpha;
-          *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, alpha_ratio);
+          *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, bgr.blue, alpha_ratio);
           dest_scan++;
-          *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, alpha_ratio);
+          *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, bgr.green, alpha_ratio);
           dest_scan++;
-          *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, alpha_ratio);
+          *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, bgr.red, alpha_ratio);
           dest_scan += 2;
           continue;
         }
@@ -760,6 +765,7 @@
                                     const uint8_t* clip_scan) {
   int col_start = GetColStart(span_left, clip_left);
   int col_end = GetColEnd(span_left, span_len, clip_right);
+  const auto& bgr = m_BGR;
   UNSAFE_TODO({
     dest_scan += col_start * Bpp;
     if (m_bRgbByteOrder) {
@@ -770,17 +776,17 @@
             if (Bpp == 4) {
               *(uint32_t*)dest_scan = m_Color;
             } else if (Bpp == 3) {
-              *dest_scan++ = m_Red;
-              *dest_scan++ = m_Green;
-              *dest_scan++ = m_Blue;
+              *dest_scan++ = bgr.red;
+              *dest_scan++ = bgr.green;
+              *dest_scan++ = bgr.blue;
               continue;
             }
           } else {
-            *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha);
+            *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, bgr.red, src_alpha);
             dest_scan++;
-            *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha);
+            *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, bgr.green, src_alpha);
             dest_scan++;
-            *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha);
+            *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, bgr.blue, src_alpha);
             dest_scan += Bpp - 2;
             continue;
           }
@@ -797,17 +803,17 @@
           if (Bpp == 4) {
             *(uint32_t*)dest_scan = m_Color;
           } else if (Bpp == 3) {
-            *dest_scan++ = m_Blue;
-            *dest_scan++ = m_Green;
-            *dest_scan++ = m_Red;
+            *dest_scan++ = bgr.blue;
+            *dest_scan++ = bgr.green;
+            *dest_scan++ = bgr.red;
             continue;
           }
         } else {
-          *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Blue, src_alpha);
+          *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, bgr.blue, src_alpha);
           dest_scan++;
-          *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Green, src_alpha);
+          *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, bgr.green, src_alpha);
           dest_scan++;
-          *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, m_Red, src_alpha);
+          *dest_scan = FXDIB_ALPHA_MERGE(*dest_scan, bgr.red, src_alpha);
           dest_scan += Bpp - 2;
           continue;
         }
@@ -842,7 +848,7 @@
     return;
   }
 
-  std::tie(m_Alpha, m_Red, m_Green, m_Blue) = ArgbDecode(color);
+  m_BGR = ArgbToBGRStruct(color);
 }
 
 template <class Scanline>
diff --git a/core/fxge/apple/fx_quartz_device.cpp b/core/fxge/apple/fx_quartz_device.cpp
index a0757c2..5b60b81 100644
--- a/core/fxge/apple/fx_quartz_device.cpp
+++ b/core/fxge/apple/fx_quartz_device.cpp
@@ -88,12 +88,9 @@
   CGContextSetFont(context, (CGFontRef)font);
   CGContextSetFontSize(context, font_size);
 
-  int32_t a;
-  int32_t r;
-  int32_t g;
-  int32_t b;
-  std::tie(a, r, g, b) = ArgbDecode(argb);
-  CGContextSetRGBFillColor(context, r / 255.f, g / 255.f, b / 255.f, a / 255.f);
+  const FX_BGRA_STRUCT<uint8_t> bgra = ArgbToBGRAStruct(argb);
+  CGContextSetRGBFillColor(context, bgra.red / 255.f, bgra.green / 255.f,
+                           bgra.blue / 255.f, bgra.alpha / 255.f);
   CGContextSaveGState(context);
 #if CGFLOAT_IS_DOUBLE
   auto glyph_positions_cg =
diff --git a/core/fxge/cfx_renderdevice.cpp b/core/fxge/cfx_renderdevice.cpp
index 6b247b5..c449910 100644
--- a/core/fxge/cfx_renderdevice.cpp
+++ b/core/fxge/cfx_renderdevice.cpp
@@ -115,15 +115,12 @@
 }
 
 void MergeGammaAdjustRgb(const uint8_t* src,
-                         int r,
-                         int g,
-                         int b,
-                         int a,
+                         const FX_BGRA_STRUCT<uint8_t>& bgra,
                          uint8_t* dest) {
   UNSAFE_TODO({
-    MergeGammaAdjust(src[2], b, a, &dest[0]);
-    MergeGammaAdjust(src[1], g, a, &dest[1]);
-    MergeGammaAdjust(src[0], r, a, &dest[2]);
+    MergeGammaAdjust(src[2], bgra.blue, bgra.alpha, &dest[0]);
+    MergeGammaAdjust(src[1], bgra.green, bgra.alpha, &dest[1]);
+    MergeGammaAdjust(src[0], bgra.red, bgra.alpha, &dest[2]);
   });
 }
 
@@ -135,75 +132,65 @@
   return back_alpha + src_alpha - back_alpha * src_alpha / 255;
 }
 
-void ApplyAlpha(uint8_t* dest, int b, int g, int r, int alpha) {
+void ApplyAlpha(uint8_t* dest, const FX_BGRA_STRUCT<uint8_t>& bgra, int alpha) {
   UNSAFE_TODO({
-    dest[0] = FXDIB_ALPHA_MERGE(dest[0], b, alpha);
-    dest[1] = FXDIB_ALPHA_MERGE(dest[1], g, alpha);
-    dest[2] = FXDIB_ALPHA_MERGE(dest[2], r, alpha);
+    dest[0] = FXDIB_ALPHA_MERGE(dest[0], bgra.blue, alpha);
+    dest[1] = FXDIB_ALPHA_MERGE(dest[1], bgra.green, alpha);
+    dest[2] = FXDIB_ALPHA_MERGE(dest[2], bgra.red, alpha);
   });
 }
 
 void ApplyDestAlpha(uint8_t back_alpha,
                     int src_alpha,
-                    int r,
-                    int g,
-                    int b,
+                    const FX_BGRA_STRUCT<uint8_t>& bgra,
                     uint8_t* dest) {
   uint8_t dest_alpha = CalculateDestAlpha(back_alpha, src_alpha);
-  ApplyAlpha(dest, b, g, r, src_alpha * 255 / dest_alpha);
+  ApplyAlpha(dest, bgra, src_alpha * 255 / dest_alpha);
   UNSAFE_TODO(dest[3] = dest_alpha);
 }
 
 void NormalizeArgb(int src_value,
-                   int r,
-                   int g,
-                   int b,
-                   int a,
+                   const FX_BGRA_STRUCT<uint8_t>& bgra,
                    uint8_t* dest,
                    int src_alpha) {
   UNSAFE_TODO({
     uint8_t back_alpha = dest[3];
     if (back_alpha == 0) {
-      FXARGB_SetDIB(dest, ArgbEncode(src_alpha, r, g, b));
+      FXARGB_SetDIB(dest,
+                    ArgbEncode(src_alpha, bgra.red, bgra.green, bgra.blue));
     } else if (src_alpha != 0) {
-      ApplyDestAlpha(back_alpha, src_alpha, r, g, b, dest);
+      ApplyDestAlpha(back_alpha, src_alpha, bgra, dest);
     }
   });
 }
 
 void NormalizeDest(bool has_alpha,
                    int src_value,
-                   int r,
-                   int g,
-                   int b,
-                   int a,
+                   const FX_BGRA_STRUCT<uint8_t>& bgra,
                    uint8_t* dest) {
   if (has_alpha) {
-    NormalizeArgb(src_value, r, g, b, a, dest,
-                  CalcAlpha(TextGammaAdjust(src_value), a));
+    NormalizeArgb(src_value, bgra, dest,
+                  CalcAlpha(TextGammaAdjust(src_value), bgra.alpha));
     return;
   }
-  int src_alpha = CalcAlpha(TextGammaAdjust(src_value), a);
+  int src_alpha = CalcAlpha(TextGammaAdjust(src_value), bgra.alpha);
   if (src_alpha == 0)
     return;
 
-  ApplyAlpha(dest, b, g, r, src_alpha);
+  ApplyAlpha(dest, bgra, src_alpha);
 }
 
 void NormalizeSrc(bool has_alpha,
                   int src_value,
-                  int r,
-                  int g,
-                  int b,
-                  int a,
+                  const FX_BGRA_STRUCT<uint8_t>& bgra,
                   uint8_t* dest) {
   if (!has_alpha) {
-    ApplyAlpha(dest, b, g, r, CalcAlpha(TextGammaAdjust(src_value), a));
+    ApplyAlpha(dest, bgra, CalcAlpha(TextGammaAdjust(src_value), bgra.alpha));
     return;
   }
-  int src_alpha = CalcAlpha(TextGammaAdjust(src_value), a);
+  int src_alpha = CalcAlpha(TextGammaAdjust(src_value), bgra.alpha);
   if (src_alpha != 0)
-    NormalizeArgb(src_value, r, g, b, a, dest, src_alpha);
+    NormalizeArgb(src_value, bgra, dest, src_alpha);
 }
 
 void NextPixel(const uint8_t** src_scan, uint8_t** dst_scan, int bpp) {
@@ -228,10 +215,7 @@
                           int end_col,
                           bool normalize,
                           int x_subpixel,
-                          int a,
-                          int r,
-                          int g,
-                          int b) {
+                          const FX_BGRA_STRUCT<uint8_t>& bgra) {
   const bool has_alpha = bitmap->GetFormat() == FXDIB_Format::kArgb;
   const int Bpp = has_alpha ? 4 : bitmap->GetBPP() / 8;
   for (int row = 0; row < nrows; ++row) {
@@ -247,9 +231,9 @@
       for (int col = start_col; col < end_col; ++col) {
         if (normalize) {
           int src_value = AverageRgb(&src_scan[0]);
-          NormalizeDest(has_alpha, src_value, r, g, b, a, dest_scan);
+          NormalizeDest(has_alpha, src_value, bgra, dest_scan);
         } else {
-          MergeGammaAdjustRgb(&src_scan[0], r, g, b, a, &dest_scan[0]);
+          MergeGammaAdjustRgb(&src_scan[0], bgra, &dest_scan[0]);
           SetAlpha(has_alpha, dest_scan);
         }
         NextPixel(&src_scan, &dest_scan, Bpp);
@@ -261,22 +245,22 @@
         if (normalize) {
           int src_value = start_col > left ? AverageRgb(&src_scan[-1])
                                            : (src_scan[0] + src_scan[1]) / 3;
-          NormalizeSrc(has_alpha, src_value, r, g, b, a, dest_scan);
+          NormalizeSrc(has_alpha, src_value, bgra, dest_scan);
         } else {
           if (start_col > left) {
-            MergeGammaAdjust(src_scan[-1], r, a, &dest_scan[2]);
+            MergeGammaAdjust(src_scan[-1], bgra.red, bgra.alpha, &dest_scan[2]);
           }
-          MergeGammaAdjust(src_scan[0], g, a, &dest_scan[1]);
-          MergeGammaAdjust(src_scan[1], b, a, &dest_scan[0]);
+          MergeGammaAdjust(src_scan[0], bgra.green, bgra.alpha, &dest_scan[1]);
+          MergeGammaAdjust(src_scan[1], bgra.blue, bgra.alpha, &dest_scan[0]);
           SetAlpha(has_alpha, dest_scan);
         }
         NextPixel(&src_scan, &dest_scan, Bpp);
         for (int col = start_col + 1; col < end_col; ++col) {
           if (normalize) {
             int src_value = AverageRgb(&src_scan[-1]);
-            NormalizeDest(has_alpha, src_value, r, g, b, a, dest_scan);
+            NormalizeDest(has_alpha, src_value, bgra, dest_scan);
           } else {
-            MergeGammaAdjustRgb(&src_scan[-1], r, g, b, a, &dest_scan[0]);
+            MergeGammaAdjustRgb(&src_scan[-1], bgra, &dest_scan[0]);
             SetAlpha(has_alpha, dest_scan);
           }
           NextPixel(&src_scan, &dest_scan, Bpp);
@@ -286,22 +270,22 @@
       if (normalize) {
         int src_value =
             start_col > left ? AverageRgb(&src_scan[-2]) : src_scan[0] / 3;
-        NormalizeSrc(has_alpha, src_value, r, g, b, a, dest_scan);
+        NormalizeSrc(has_alpha, src_value, bgra, dest_scan);
       } else {
         if (start_col > left) {
-          MergeGammaAdjust(src_scan[-2], r, a, &dest_scan[2]);
-          MergeGammaAdjust(src_scan[-1], g, a, &dest_scan[1]);
+          MergeGammaAdjust(src_scan[-2], bgra.red, bgra.alpha, &dest_scan[2]);
+          MergeGammaAdjust(src_scan[-1], bgra.green, bgra.alpha, &dest_scan[1]);
         }
-        MergeGammaAdjust(src_scan[0], b, a, &dest_scan[0]);
+        MergeGammaAdjust(src_scan[0], bgra.blue, bgra.alpha, &dest_scan[0]);
         SetAlpha(has_alpha, dest_scan);
       }
       NextPixel(&src_scan, &dest_scan, Bpp);
       for (int col = start_col + 1; col < end_col; ++col) {
         if (normalize) {
           int src_value = AverageRgb(&src_scan[-2]);
-          NormalizeDest(has_alpha, src_value, r, g, b, a, dest_scan);
+          NormalizeDest(has_alpha, src_value, bgra, dest_scan);
         } else {
-          MergeGammaAdjustRgb(&src_scan[-2], r, g, b, a, &dest_scan[0]);
+          MergeGammaAdjustRgb(&src_scan[-2], bgra, &dest_scan[0]);
           SetAlpha(has_alpha, dest_scan);
         }
         NextPixel(&src_scan, &dest_scan, Bpp);
@@ -1184,12 +1168,10 @@
       return false;
   }
   int dest_width = pixel_width;
-  int a = 0;
-  int r = 0;
-  int g = 0;
-  int b = 0;
-  if (anti_alias == FT_RENDER_MODE_LCD)
-    std::tie(a, r, g, b) = ArgbDecode(fill_color);
+  FX_BGRA_STRUCT<uint8_t> bgra;
+  if (anti_alias == FT_RENDER_MODE_LCD) {
+    bgra = ArgbToBGRAStruct(fill_color);
+  }
 
   for (const TextGlyphPos& glyph : glyphs) {
     if (!glyph.m_pGlyph)
@@ -1223,7 +1205,7 @@
       continue;
 
     DrawNormalTextHelper(bitmap, pGlyph, nrows, point->x, point->y, start_col,
-                         end_col, normalize, x_subpixel, a, r, g, b);
+                         end_col, normalize, x_subpixel, bgra);
   }
 
   if (bitmap->IsMaskFormat()) {
diff --git a/core/fxge/dib/cfx_imagestretcher.cpp b/core/fxge/dib/cfx_imagestretcher.cpp
index 7c1f67e..944e40e 100644
--- a/core/fxge/dib/cfx_imagestretcher.cpp
+++ b/core/fxge/dib/cfx_imagestretcher.cpp
@@ -44,24 +44,18 @@
   DCHECK_EQ(FXDIB_Format::k1bppRgb, source->GetFormat());
   DCHECK(source->HasPalette());
 
-  int a0;
-  int r0;
-  int g0;
-  int b0;
-  std::tie(a0, r0, g0, b0) = ArgbDecode(source->GetPaletteArgb(0));
-  int a1;
-  int r1;
-  int g1;
-  int b1;
-  std::tie(a1, r1, g1, b1) = ArgbDecode(source->GetPaletteArgb(1));
-  DCHECK_EQ(255, a0);
-  DCHECK_EQ(255, a1);
+  const FX_BGRA_STRUCT<uint8_t> bgra0 =
+      ArgbToBGRAStruct(source->GetPaletteArgb(0));
+  const FX_BGRA_STRUCT<uint8_t> bgra1 =
+      ArgbToBGRAStruct(source->GetPaletteArgb(1));
+  CHECK_EQ(255, bgra0.alpha);
+  CHECK_EQ(255, bgra1.alpha);
 
   DataVector<uint32_t> palette(CFX_DIBBase::kPaletteSize);
   for (int i = 0; i < static_cast<int>(CFX_DIBBase::kPaletteSize); ++i) {
-    int r = r0 + (r1 - r0) * i / 255;
-    int g = g0 + (g1 - g0) * i / 255;
-    int b = b0 + (b1 - b0) * i / 255;
+    int r = bgra0.red + (bgra1.red - bgra0.red) * i / 255;
+    int g = bgra0.green + (bgra1.green - bgra0.green) * i / 255;
+    int b = bgra0.blue + (bgra1.blue - bgra0.blue) * i / 255;
     palette[i] = ArgbEncode(255, r, g, b);
   }
   return palette;
diff --git a/core/fxge/dib/fx_dib.cpp b/core/fxge/dib/fx_dib.cpp
index 1cc5e85..d43ed3a 100644
--- a/core/fxge/dib/fx_dib.cpp
+++ b/core/fxge/dib/fx_dib.cpp
@@ -60,13 +60,12 @@
   return bInterpolateBilinear || bHalftone || bNoSmoothing || bLossy;
 }
 
-FX_BGR_STRUCT<uint8_t> ArgbToBGRStruct(FX_ARGB argb) {
-  return {FXARGB_B(argb), FXARGB_G(argb), FXARGB_R(argb)};
+FX_BGRA_STRUCT<uint8_t> ArgbToBGRAStruct(FX_ARGB argb) {
+  return {FXARGB_B(argb), FXARGB_G(argb), FXARGB_R(argb), FXARGB_A(argb)};
 }
 
-std::tuple<int, int, int, int> ArgbDecode(FX_ARGB argb) {
-  return std::make_tuple(FXARGB_A(argb), FXARGB_R(argb), FXARGB_G(argb),
-                         FXARGB_B(argb));
+FX_BGR_STRUCT<uint8_t> ArgbToBGRStruct(FX_ARGB argb) {
+  return {FXARGB_B(argb), FXARGB_G(argb), FXARGB_R(argb)};
 }
 
 std::pair<int, FX_COLORREF> ArgbToAlphaAndColorRef(FX_ARGB argb) {
diff --git a/core/fxge/dib/fx_dib.h b/core/fxge/dib/fx_dib.h
index 83da668..d590241 100644
--- a/core/fxge/dib/fx_dib.h
+++ b/core/fxge/dib/fx_dib.h
@@ -9,7 +9,6 @@
 
 #include <stdint.h>
 
-#include <tuple>
 #include <utility>
 
 #include "core/fxcrt/compiler_specific.h"
@@ -162,12 +161,11 @@
 
 FXDIB_Format MakeRGBFormat(int bpp);
 
+FX_BGRA_STRUCT<uint8_t> ArgbToBGRAStruct(FX_ARGB argb);
+
 // Ignores alpha.
 FX_BGR_STRUCT<uint8_t> ArgbToBGRStruct(FX_ARGB argb);
 
-// Returns (a, r, g, b)
-std::tuple<int, int, int, int> ArgbDecode(FX_ARGB argb);
-
 // Returns (a, FX_COLORREF)
 std::pair<int, FX_COLORREF> ArgbToAlphaAndColorRef(FX_ARGB argb);
 
diff --git a/fxjs/cjs_field.cpp b/fxjs/cjs_field.cpp
index 6441613..d230b06 100644
--- a/fxjs/cjs_field.cpp
+++ b/fxjs/cjs_field.cpp
@@ -1912,13 +1912,10 @@
   if (maybe_type_argb_pair.has_value() &&
       maybe_type_argb_pair.value().color_type !=
           CFX_Color::Type::kTransparent) {
-    int32_t a;
-    int32_t r;
-    int32_t g;
-    int32_t b;
-    std::tie(a, r, g, b) = ArgbDecode(maybe_type_argb_pair.value().argb);
-    crRet =
-        CFX_Color(CFX_Color::Type::kRGB, r / 255.0f, g / 255.0f, b / 255.0f);
+    FX_BGR_STRUCT<uint8_t> bgr =
+        ArgbToBGRStruct(maybe_type_argb_pair.value().argb);
+    crRet = CFX_Color(CFX_Color::Type::kRGB, bgr.red / 255.0f,
+                      bgr.green / 255.0f, bgr.blue / 255.0f);
   }
 
   v8::Local<v8::Value> array =
diff --git a/fxjs/xfa/cjx_object.cpp b/fxjs/xfa/cjx_object.cpp
index 6aac6c9..e61183e 100644
--- a/fxjs/xfa/cjx_object.cpp
+++ b/fxjs/xfa/cjx_object.cpp
@@ -98,6 +98,13 @@
   return {r, g, b};
 }
 
+v8::Local<v8::String> ColorToV8String(v8::Isolate* isolate, FX_ARGB color) {
+  FX_BGR_STRUCT<uint8_t> bgr = ArgbToBGRStruct(color);
+  return fxv8::NewStringHelper(
+      isolate, ByteString::Format("%d,%d,%d", bgr.red, bgr.green, bgr.blue)
+                   .AsStringView());
+}
+
 }  // namespace
 
 CJX_Object::CJX_Object(CXFA_Object* obj) : object_(obj) {}
@@ -1091,13 +1098,7 @@
     return;
   }
 
-  int32_t a;
-  int32_t r;
-  int32_t g;
-  int32_t b;
-  std::tie(a, r, g, b) = ArgbDecode(font->GetColor());
-  *pValue = fxv8::NewStringHelper(
-      pIsolate, ByteString::Format("%d,%d,%d", r, g, b).AsStringView());
+  *pValue = ColorToV8String(pIsolate, font->GetColor());
 }
 
 void CJX_Object::ScriptSomFillColor(v8::Isolate* pIsolate,
@@ -1120,14 +1121,7 @@
     return;
   }
 
-  FX_ARGB color = borderfill->GetFillColor();
-  int32_t a;
-  int32_t r;
-  int32_t g;
-  int32_t b;
-  std::tie(a, r, g, b) = ArgbDecode(color);
-  *pValue = fxv8::NewStringHelper(
-      pIsolate, ByteString::Format("%d,%d,%d", r, g, b).AsStringView());
+  *pValue = ColorToV8String(pIsolate, borderfill->GetFillColor());
 }
 
 void CJX_Object::ScriptSomBorderColor(v8::Isolate* pIsolate,
@@ -1154,13 +1148,7 @@
 
   CXFA_Edge* edge = border->GetEdgeIfExists(0);
   FX_ARGB color = edge ? edge->GetColor() : CXFA_Edge::kDefaultColor;
-  int32_t a;
-  int32_t r;
-  int32_t g;
-  int32_t b;
-  std::tie(a, r, g, b) = ArgbDecode(color);
-  *pValue = fxv8::NewStringHelper(
-      pIsolate, ByteString::Format("%d,%d,%d", r, g, b).AsStringView());
+  *pValue = ColorToV8String(pIsolate, color);
 }
 
 void CJX_Object::ScriptSomBorderWidth(v8::Isolate* pIsolate,
diff --git a/xfa/fgas/graphics/cfgas_geshading.cpp b/xfa/fgas/graphics/cfgas_geshading.cpp
index d2f9193..cadca3b 100644
--- a/xfa/fgas/graphics/cfgas_geshading.cpp
+++ b/xfa/fgas/graphics/cfgas_geshading.cpp
@@ -42,23 +42,20 @@
 
 CFGAS_GEShading::~CFGAS_GEShading() = default;
 
-void CFGAS_GEShading::InitArgbArray(FX_ARGB beginArgb, FX_ARGB endArgb) {
-  auto [a1, r1, g1, b1] = ArgbDecode(beginArgb);
-  auto [a2, r2, g2, b2] = ArgbDecode(endArgb);
+void CFGAS_GEShading::InitArgbArray(FX_ARGB begin_argb, FX_ARGB end_argb) {
+  FX_BGRA_STRUCT<uint8_t> bgra0 = ArgbToBGRAStruct(begin_argb);
+  FX_BGRA_STRUCT<uint8_t> bgra1 = ArgbToBGRAStruct(end_argb);
 
-  float f = static_cast<float>(kSteps - 1);
-  float aScale = 1.0 * (a2 - a1) / f;
-  float rScale = 1.0 * (r2 - r1) / f;
-  float gScale = 1.0 * (g2 - g1) / f;
-  float bScale = 1.0 * (b2 - b1) / f;
+  constexpr float f = static_cast<float>(kSteps - 1);
+  const float a_scale = 1.0 * (bgra1.alpha - bgra0.alpha) / f;
+  const float r_scale = 1.0 * (bgra1.red - bgra0.red) / f;
+  const float g_scale = 1.0 * (bgra1.green - bgra0.green) / f;
+  const float b_scale = 1.0 * (bgra1.blue - bgra0.blue) / f;
 
   for (size_t i = 0; i < kSteps; i++) {
-    int32_t a3 = static_cast<int32_t>(i * aScale);
-    int32_t r3 = static_cast<int32_t>(i * rScale);
-    int32_t g3 = static_cast<int32_t>(i * gScale);
-    int32_t b3 = static_cast<int32_t>(i * bScale);
-
-    // TODO(dsinclair): Add overloads for FX_ARGB. pdfium:437
-    m_argbArray[i] = ArgbEncode(a1 + a3, r1 + r3, g1 + g3, b1 + b3);
+    m_argbArray[i] = ArgbEncode(static_cast<int32_t>(i * a_scale) + bgra0.alpha,
+                                static_cast<int32_t>(i * r_scale) + bgra0.red,
+                                static_cast<int32_t>(i * g_scale) + bgra0.green,
+                                static_cast<int32_t>(i * b_scale) + bgra0.blue);
   }
 }
diff --git a/xfa/fgas/graphics/cfgas_geshading.h b/xfa/fgas/graphics/cfgas_geshading.h
index f4e7e84..0ceeb14 100644
--- a/xfa/fgas/graphics/cfgas_geshading.h
+++ b/xfa/fgas/graphics/cfgas_geshading.h
@@ -52,7 +52,7 @@
  private:
   static constexpr size_t kSteps = 256;
 
-  void InitArgbArray(FX_ARGB beginArgb, FX_ARGB endArgb);
+  void InitArgbArray(FX_ARGB begin_argb, FX_ARGB end_argb);
 
   const Type m_type;
   const CFX_PointF m_beginPoint;
diff --git a/xfa/fxfa/parser/cxfa_color.cpp b/xfa/fxfa/parser/cxfa_color.cpp
index f09251e..e848838 100644
--- a/xfa/fxfa/parser/cxfa_color.cpp
+++ b/xfa/fxfa/parser/cxfa_color.cpp
@@ -110,11 +110,8 @@
 }
 
 void CXFA_Color::SetValue(FX_ARGB color) {
-  int a;
-  int r;
-  int g;
-  int b;
-  std::tie(a, r, g, b) = ArgbDecode(color);
-  JSObject()->SetCData(XFA_Attribute::Value,
-                       WideString::Format(L"%d,%d,%d", r, g, b));
+  FX_BGR_STRUCT<uint8_t> bgr = ArgbToBGRStruct(color);
+  JSObject()->SetCData(
+      XFA_Attribute::Value,
+      WideString::Format(L"%d,%d,%d", bgr.red, bgr.green, bgr.blue));
 }
diff --git a/xfa/fxfa/parser/cxfa_stroke.cpp b/xfa/fxfa/parser/cxfa_stroke.cpp
index d1af2fe..6bba800 100644
--- a/xfa/fxfa/parser/cxfa_stroke.cpp
+++ b/xfa/fxfa/parser/cxfa_stroke.cpp
@@ -125,13 +125,10 @@
   if (!pNode)
     return;
 
-  int a;
-  int r;
-  int g;
-  int b;
-  std::tie(a, r, g, b) = ArgbDecode(argb);
-  pNode->JSObject()->SetCData(XFA_Attribute::Value,
-                              WideString::Format(L"%d,%d,%d", r, g, b));
+  FX_BGR_STRUCT<uint8_t> bgr = ArgbToBGRStruct(argb);
+  pNode->JSObject()->SetCData(
+      XFA_Attribute::Value,
+      WideString::Format(L"%d,%d,%d", bgr.red, bgr.green, bgr.blue));
 }
 
 XFA_AttributeValue CXFA_Stroke::GetJoinType() {