Change cfx_cmyk_to_srgb code to return struct FX_RGB

Use FX_RGB consistently for color representation.

Change-Id: I282232f7eb6b91816af068edd152dccd46364596
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/117391
Reviewed-by: Thomas 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_devicecs.cpp b/core/fpdfapi/page/cpdf_devicecs.cpp
index d152938..c1986f7 100644
--- a/core/fpdfapi/page/cpdf_devicecs.cpp
+++ b/core/fpdfapi/page/cpdf_devicecs.cpp
@@ -64,9 +64,12 @@
         *G = 1.0f - std::min(1.0f, pBuf[1] + k);
         *B = 1.0f - std::min(1.0f, pBuf[2] + k);
       } else {
-        std::tie(*R, *G, *B) = AdobeCMYK_to_sRGB(
+        FX_RGB<float> rgb = AdobeCMYK_to_sRGB(
             NormalizeChannel(pBuf[0]), NormalizeChannel(pBuf[1]),
             NormalizeChannel(pBuf[2]), NormalizeChannel(pBuf[3]));
+        *R = rgb.red;
+        *G = rgb.green;
+        *B = rgb.blue;
       }
       return true;
     default:
@@ -132,9 +135,11 @@
           }
         } else {
           for (int i = 0; i < pixels; i++) {
-            std::tie(pDestBuf[2], pDestBuf[1], pDestBuf[0]) =
-                AdobeCMYK_to_sRGB1(pSrcBuf[0], pSrcBuf[1], pSrcBuf[2],
-                                   pSrcBuf[3]);
+            FX_RGB<uint8_t> rgb = AdobeCMYK_to_sRGB1(pSrcBuf[0], pSrcBuf[1],
+                                                     pSrcBuf[2], pSrcBuf[3]);
+            pDestBuf[0] = rgb.blue;
+            pDestBuf[1] = rgb.green;
+            pDestBuf[2] = rgb.red;
             pSrcBuf += 4;
             pDestBuf += 3;
           }
diff --git a/core/fxcodec/progressive_decoder.cpp b/core/fxcodec/progressive_decoder.cpp
index 332df51..320b226 100644
--- a/core/fxcodec/progressive_decoder.cpp
+++ b/core/fxcodec/progressive_decoder.cpp
@@ -1353,7 +1353,8 @@
           src_line += 4;
         }
       }
-    } break;
+      break;
+    }
     case FXDIB_Format::kRgb:
     case FXDIB_Format::kRgb32: {
       int32_t desBpp =
@@ -1373,7 +1374,8 @@
           src_line += 4;
         }
       }
-    } break;
+      break;
+    }
     default:
       break;
   }
@@ -1596,7 +1598,8 @@
         default:
           m_TransMethod = -1;
       }
-    } break;
+      break;
+    }
     case FXDIB_Format::k8bppMask:
     case FXDIB_Format::k8bppRgb: {
       switch (src_format) {
@@ -1621,7 +1624,8 @@
         default:
           m_TransMethod = -1;
       }
-    } break;
+      break;
+    }
     case FXDIB_Format::kRgb: {
       switch (src_format) {
         case FXCodec_1bppGray:
@@ -1645,7 +1649,8 @@
         default:
           m_TransMethod = -1;
       }
-    } break;
+      break;
+    }
     case FXDIB_Format::kRgb32:
     case FXDIB_Format::kArgb: {
       switch (src_format) {
@@ -1676,7 +1681,8 @@
         default:
           m_TransMethod = -1;
       }
-    } break;
+      break;
+    }
     default:
       m_TransMethod = -1;
   }
@@ -1713,7 +1719,8 @@
           dest_g += pixel_weight * src_scan[j];
         }
         *dest_scan++ = CStretchEngine::PixelFromFixed(dest_g);
-      } break;
+        break;
+      }
       case 3: {
         uint32_t dest_r = 0;
         uint32_t dest_g = 0;
@@ -1731,7 +1738,8 @@
             FXRGB2GRAY(CStretchEngine::PixelFromFixed(dest_r),
                        CStretchEngine::PixelFromFixed(dest_g),
                        CStretchEngine::PixelFromFixed(dest_b)));
-      } break;
+        break;
+      }
       case 4: {
         uint32_t dest_b = 0;
         uint32_t dest_g = 0;
@@ -1749,31 +1757,30 @@
             FXRGB2GRAY(CStretchEngine::PixelFromFixed(dest_r),
                        CStretchEngine::PixelFromFixed(dest_g),
                        CStretchEngine::PixelFromFixed(dest_b)));
-      } break;
+        break;
+      }
       case 5: {
-        uint32_t dest_b = 0;
-        uint32_t dest_g = 0;
         uint32_t dest_r = 0;
+        uint32_t dest_g = 0;
+        uint32_t dest_b = 0;
         for (int j = pPixelWeights->m_SrcStart; j <= pPixelWeights->m_SrcEnd;
              j++) {
           uint32_t pixel_weight =
               pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
           const uint8_t* src_pixel = src_scan + j * src_bytes_per_pixel;
-          uint8_t src_b = 0;
-          uint8_t src_g = 0;
-          uint8_t src_r = 0;
-          std::tie(src_r, src_g, src_b) =
+          FX_RGB<uint8_t> src_rgb =
               AdobeCMYK_to_sRGB1(255 - src_pixel[0], 255 - src_pixel[1],
                                  255 - src_pixel[2], 255 - src_pixel[3]);
-          dest_b += pixel_weight * src_b;
-          dest_g += pixel_weight * src_g;
-          dest_r += pixel_weight * src_r;
+          dest_r += pixel_weight * src_rgb.red;
+          dest_g += pixel_weight * src_rgb.green;
+          dest_b += pixel_weight * src_rgb.blue;
         }
         *dest_scan++ = static_cast<uint8_t>(
             FXRGB2GRAY(CStretchEngine::PixelFromFixed(dest_r),
                        CStretchEngine::PixelFromFixed(dest_g),
                        CStretchEngine::PixelFromFixed(dest_b)));
-      } break;
+        break;
+      }
       case 6:
         return;
       case 7: {
@@ -1786,7 +1793,8 @@
         }
         memset(dest_scan, CStretchEngine::PixelFromFixed(dest_g), 3);
         dest_scan += dest_bytes_per_pixel;
-      } break;
+        break;
+      }
       case 8: {
         uint32_t dest_r = 0;
         uint32_t dest_g = 0;
@@ -1804,7 +1812,8 @@
         *dest_scan++ = CStretchEngine::PixelFromFixed(dest_g);
         *dest_scan++ = CStretchEngine::PixelFromFixed(dest_r);
         dest_scan += dest_bytes_per_pixel - 3;
-      } break;
+        break;
+      }
       case 12: {
 #ifdef PDF_ENABLE_XFA_BMP
         if (m_pBmpContext) {
@@ -1845,7 +1854,8 @@
         *dest_scan++ = CStretchEngine::PixelFromFixed(dest_g);
         *dest_scan++ = CStretchEngine::PixelFromFixed(dest_r);
         *dest_scan++ = CStretchEngine::PixelFromFixed(dest_a);
-      } break;
+        break;
+      }
       case 9: {
         uint32_t dest_b = 0;
         uint32_t dest_g = 0;
@@ -1863,7 +1873,8 @@
         *dest_scan++ = CStretchEngine::PixelFromFixed(dest_g);
         *dest_scan++ = CStretchEngine::PixelFromFixed(dest_r);
         dest_scan += dest_bytes_per_pixel - 3;
-      } break;
+        break;
+      }
       case 10: {
         uint32_t dest_b = 0;
         uint32_t dest_g = 0;
@@ -1873,21 +1884,19 @@
           uint32_t pixel_weight =
               pPixelWeights->m_Weights[j - pPixelWeights->m_SrcStart];
           const uint8_t* src_pixel = src_scan + j * src_bytes_per_pixel;
-          uint8_t src_b = 0;
-          uint8_t src_g = 0;
-          uint8_t src_r = 0;
-          std::tie(src_r, src_g, src_b) =
+          FX_RGB<uint8_t> src_rgb =
               AdobeCMYK_to_sRGB1(255 - src_pixel[0], 255 - src_pixel[1],
                                  255 - src_pixel[2], 255 - src_pixel[3]);
-          dest_b += pixel_weight * src_b;
-          dest_g += pixel_weight * src_g;
-          dest_r += pixel_weight * src_r;
+          dest_b += pixel_weight * src_rgb.blue;
+          dest_g += pixel_weight * src_rgb.green;
+          dest_r += pixel_weight * src_rgb.red;
         }
         *dest_scan++ = CStretchEngine::PixelFromFixed(dest_b);
         *dest_scan++ = CStretchEngine::PixelFromFixed(dest_g);
         *dest_scan++ = CStretchEngine::PixelFromFixed(dest_r);
         dest_scan += dest_bytes_per_pixel - 3;
-      } break;
+        break;
+      }
       case 11: {
         uint32_t dest_alpha = 0;
         uint32_t dest_r = 0;
@@ -1908,7 +1917,8 @@
         *dest_scan++ = CStretchEngine::PixelFromFixed(dest_g);
         *dest_scan++ = CStretchEngine::PixelFromFixed(dest_r);
         *dest_scan++ = CStretchEngine::PixelFromFixed(dest_alpha * 255);
-      } break;
+        break;
+      }
       default:
         return;
     }
diff --git a/core/fxge/dib/cfx_cmyk_to_srgb.cpp b/core/fxge/dib/cfx_cmyk_to_srgb.cpp
index 4abf3e1..8262cb0 100644
--- a/core/fxge/dib/cfx_cmyk_to_srgb.cpp
+++ b/core/fxge/dib/cfx_cmyk_to_srgb.cpp
@@ -7,7 +7,6 @@
 #include "core/fxge/dib/cfx_cmyk_to_srgb.h"
 
 #include <algorithm>
-#include <tuple>
 
 #include "core/fxcrt/check_op.h"
 #include "core/fxcrt/fx_system.h"
@@ -1662,10 +1661,7 @@
 
 }  // namespace
 
-std::tuple<uint8_t, uint8_t, uint8_t> AdobeCMYK_to_sRGB1(uint8_t c,
-                                                         uint8_t m,
-                                                         uint8_t y,
-                                                         uint8_t k) {
+FX_RGB<uint8_t> AdobeCMYK_to_sRGB1(uint8_t c, uint8_t m, uint8_t y, uint8_t k) {
   int fix_c = c << 8;
   int fix_m = m << 8;
   int fix_y = y << 8;
@@ -1715,17 +1711,15 @@
   fix_g += (kCMYK[pos][1] - kCMYK[k1_pos][1]) * k_rate / 32;
   fix_b += (kCMYK[pos][2] - kCMYK[k1_pos][2]) * k_rate / 32;
 
-  fix_r = std::max(fix_r, 0);
-  fix_g = std::max(fix_g, 0);
-  fix_b = std::max(fix_b, 0);
+  fix_r = std::max(fix_r, 0) >> 8;
+  fix_g = std::max(fix_g, 0) >> 8;
+  fix_b = std::max(fix_b, 0) >> 8;
 
-  return std::make_tuple(fix_r >> 8, fix_g >> 8, fix_b >> 8);
+  return {static_cast<uint8_t>(fix_r), static_cast<uint8_t>(fix_g),
+          static_cast<uint8_t>(fix_b)};
 }
 
-std::tuple<float, float, float> AdobeCMYK_to_sRGB(float c,
-                                                  float m,
-                                                  float y,
-                                                  float k) {
+FX_RGB<float> AdobeCMYK_to_sRGB(float c, float m, float y, float k) {
   // Convert to uint8_t with round-to-nearest. Avoid using FXSYS_roundf because
   // it is incredibly expensive with VC++ (tested on VC++ 2015) because round()
   // is very expensive.
@@ -1735,24 +1729,26 @@
   // That value is close to the cusp but zero is the correct answer, and
   // getting the same answer as before is desirable.
   // All floats from 0.0 to 1.0 were tested and now give the same results.
-  const float rounding_offset = 0.49999997f;
-  uint8_t c1 = static_cast<int>(c * 255.f + rounding_offset);
-  uint8_t m1 = static_cast<int>(m * 255.f + rounding_offset);
-  uint8_t y1 = static_cast<int>(y * 255.f + rounding_offset);
-  uint8_t k1 = static_cast<int>(k * 255.f + rounding_offset);
+  constexpr float kRoundingOffset = 0.49999997f;
+  uint8_t c1 = static_cast<int>(c * 255.f + kRoundingOffset);
+  uint8_t m1 = static_cast<int>(m * 255.f + kRoundingOffset);
+  uint8_t y1 = static_cast<int>(y * 255.f + kRoundingOffset);
+  uint8_t k1 = static_cast<int>(k * 255.f + kRoundingOffset);
 
   DCHECK_EQ(c1, FXSYS_roundf(c * 255));
   DCHECK_EQ(m1, FXSYS_roundf(m * 255));
   DCHECK_EQ(y1, FXSYS_roundf(y * 255));
   DCHECK_EQ(k1, FXSYS_roundf(k * 255));
 
-  uint8_t r;
-  uint8_t g;
-  uint8_t b;
-  std::tie(r, g, b) = AdobeCMYK_to_sRGB1(c1, m1, y1, k1);
+  FX_RGB<uint8_t> int_results = AdobeCMYK_to_sRGB1(c1, m1, y1, k1);
   // Multiply by a constant rather than dividing because division is much
   // more expensive.
-  return std::make_tuple(r * (1.0f / 255), g * (1.0f / 255), b * (1.0f / 255));
+  constexpr float kToFloat = 1.0f / 255.0f;
+  return {
+      int_results.red * kToFloat,
+      int_results.green * kToFloat,
+      int_results.blue * kToFloat,
+  };
 }
 
 }  // namespace fxge
diff --git a/core/fxge/dib/cfx_cmyk_to_srgb.h b/core/fxge/dib/cfx_cmyk_to_srgb.h
index e38e57c..3481154 100644
--- a/core/fxge/dib/cfx_cmyk_to_srgb.h
+++ b/core/fxge/dib/cfx_cmyk_to_srgb.h
@@ -9,18 +9,12 @@
 
 #include <stdint.h>
 
-#include <tuple>
+#include "core/fxge/dib/fx_dib.h"
 
 namespace fxge {
 
-std::tuple<float, float, float> AdobeCMYK_to_sRGB(float c,
-                                                  float m,
-                                                  float y,
-                                                  float k);
-std::tuple<uint8_t, uint8_t, uint8_t> AdobeCMYK_to_sRGB1(uint8_t c,
-                                                         uint8_t m,
-                                                         uint8_t y,
-                                                         uint8_t k);
+FX_RGB<float> AdobeCMYK_to_sRGB(float c, float m, float y, float k);
+FX_RGB<uint8_t> AdobeCMYK_to_sRGB1(uint8_t c, uint8_t m, uint8_t y, uint8_t k);
 
 }  // namespace fxge
 
diff --git a/core/fxge/dib/cfx_cmyk_to_srgb_unittest.cpp b/core/fxge/dib/cfx_cmyk_to_srgb_unittest.cpp
index d28f9cd..b2d5c5b 100644
--- a/core/fxge/dib/cfx_cmyk_to_srgb_unittest.cpp
+++ b/core/fxge/dib/cfx_cmyk_to_srgb_unittest.cpp
@@ -19,14 +19,12 @@
   // range.
   constexpr float kStartValue = 0.001f;
   constexpr float kEndValue = 0.003f;
-  float R = 0.0f;
-  float G = 0.0f;
-  float B = 0.0f;
+  FX_RGB<float> rgb;
   // Iterate through floats by incrementing the representation, as discussed in
   // https://randomascii.wordpress.com/2012/01/23/stupid-float-tricks-2/
   for (Float_t f = kStartValue; f.f < kEndValue; f.i++) {
-    std::tie(R, G, B) = AdobeCMYK_to_sRGB(f.f, f.f, f.f, f.f);
+    rgb = AdobeCMYK_to_sRGB(f.f, f.f, f.f, f.f);
   }
   // Check various other 'special' numbers.
-  std::tie(R, G, B) = AdobeCMYK_to_sRGB(0.0f, 0.25f, 0.5f, 1.0f);
+  rgb = AdobeCMYK_to_sRGB(0.0f, 0.25f, 0.5f, 1.0f);
 }