Add UnPreMultiplyColor()

Add a Skia-only utility function to un-premultiply FX_ABGR_STRUCT and
similar structs.

Bug: 42271020
Change-Id: Ibf0cc83f1845b8a05b0b0b10a4ab115b3020c737
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/122892
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Tom Sepez <tsepez@google.com>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/core/fxge/dib/fx_dib.h b/core/fxge/dib/fx_dib.h
index 10717f8..fea7565 100644
--- a/core/fxge/dib/fx_dib.h
+++ b/core/fxge/dib/fx_dib.h
@@ -256,6 +256,26 @@
   output.red = static_cast<float>(input.red) * input.alpha / 255.0f;
   return output;
 }
+
+template <typename T>
+T UnPreMultiplyColor(const T& input) {
+  if (input.alpha == 255) {
+    return input;
+  }
+
+  T output;
+  output.alpha = input.alpha;
+  if (input.alpha == 0) {
+    output.blue = 0;
+    output.green = 0;
+    output.red = 0;
+  } else {
+    output.blue = static_cast<float>(input.blue) * 255.0f / input.alpha;
+    output.green = static_cast<float>(input.green) * 255.0f / input.alpha;
+    output.red = static_cast<float>(input.red) * 255.0f / input.alpha;
+  }
+  return output;
+}
 #endif  // defined(PDF_USE_SKIA)
 
 #endif  // CORE_FXGE_DIB_FX_DIB_H_
diff --git a/core/fxge/dib/fx_dib_unittest.cpp b/core/fxge/dib/fx_dib_unittest.cpp
index 6db5793..11b773b 100644
--- a/core/fxge/dib/fx_dib_unittest.cpp
+++ b/core/fxge/dib/fx_dib_unittest.cpp
@@ -56,4 +56,52 @@
   EXPECT_FLOAT_EQ(0.0f, result_f.blue);
   EXPECT_FLOAT_EQ(255.0f, result_f.alpha);
 }
+
+TEST(PreMultiplyTest, UnPreMultiplyColor) {
+  FX_ABGR_STRUCT<uint8_t> result = UnPreMultiplyColor(FX_ABGR_STRUCT<uint8_t>{
+      .alpha = 192, .blue = 0, .green = 192, .red = 100});
+  EXPECT_EQ(192, result.alpha);
+  EXPECT_EQ(0, result.blue);
+  EXPECT_EQ(255, result.green);
+  EXPECT_EQ(132, result.red);
+
+  FX_RGBA_STRUCT<float> result_f = UnPreMultiplyColor(
+      FX_RGBA_STRUCT<float>{.red = 100, .green = 192, .blue = 0, .alpha = 192});
+  EXPECT_FLOAT_EQ(132.8125f, result_f.red);
+  EXPECT_FLOAT_EQ(255.0f, result_f.green);
+  EXPECT_FLOAT_EQ(0.0f, result_f.blue);
+  EXPECT_FLOAT_EQ(192.0f, result_f.alpha);
+}
+
+TEST(PreMultiplyTest, UnPreMultiplyColorFullyTransparent) {
+  FX_ABGR_STRUCT<uint8_t> result = UnPreMultiplyColor(
+      FX_ABGR_STRUCT<uint8_t>{.alpha = 0, .blue = 0, .green = 0, .red = 0});
+  EXPECT_EQ(0, result.alpha);
+  EXPECT_EQ(0, result.blue);
+  EXPECT_EQ(0, result.green);
+  EXPECT_EQ(0, result.red);
+
+  FX_RGBA_STRUCT<float> result_f = UnPreMultiplyColor(
+      FX_RGBA_STRUCT<float>{.red = 0, .green = 0, .blue = 0, .alpha = 0});
+  EXPECT_FLOAT_EQ(0.0f, result_f.red);
+  EXPECT_FLOAT_EQ(0.0f, result_f.green);
+  EXPECT_FLOAT_EQ(0.0f, result_f.blue);
+  EXPECT_FLOAT_EQ(0.0f, result_f.alpha);
+}
+
+TEST(PreMultiplyTest, UnPreMultiplyColorFullyOpaque) {
+  FX_ABGR_STRUCT<uint8_t> result = UnPreMultiplyColor(FX_ABGR_STRUCT<uint8_t>{
+      .alpha = 255, .blue = 0, .green = 255, .red = 100});
+  EXPECT_EQ(255, result.alpha);
+  EXPECT_EQ(0, result.blue);
+  EXPECT_EQ(255, result.green);
+  EXPECT_EQ(100, result.red);
+
+  FX_RGBA_STRUCT<float> result_f = UnPreMultiplyColor(
+      FX_RGBA_STRUCT<float>{.red = 100, .green = 255, .blue = 0, .alpha = 255});
+  EXPECT_FLOAT_EQ(100.0f, result_f.red);
+  EXPECT_FLOAT_EQ(255.0f, result_f.green);
+  EXPECT_FLOAT_EQ(0.0f, result_f.blue);
+  EXPECT_FLOAT_EQ(255.0f, result_f.alpha);
+}
 #endif  // defined(PDF_USE_SKIA)