[Skia] Support pre-multiplied MultiplyAlpha()

Supports MultiplyAlpha() directly on pre-multiplied alpha using native
Skia operations, rather than wrapping the CFX_DIBitmap implementation
with conversions to un-pre-multiplied alpha and back.

The Skia operations round slightly differently in some cases, requiring
expectation updates.

Fixed: pdfium:1949
Change-Id: I44b4467aa9cc0a99175e4bf99be4dd31c7c2ad78
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/105310
Reviewed-by: Nigi <nigi@chromium.org>
Commit-Queue: K. Moon <kmoon@chromium.org>
diff --git a/DEPS b/DEPS
index c3238b0..4ea051e 100644
--- a/DEPS
+++ b/DEPS
@@ -140,7 +140,7 @@
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling pdfium_tests
   # and whatever else without interference from each other.
-  'pdfium_tests_revision': '1259848ad6b0cc58c720aa7224d523ebf3256cf8',
+  'pdfium_tests_revision': 'eb4062246a81698801fbfcd4a9b68328ab2d8895',
   # Three lines of non-changing comments so that
   # the commit queue can handle CLs rolling resultdb
   # and whatever else without interference from each other.
diff --git a/core/fpdfapi/render/cpdf_renderstatus.cpp b/core/fpdfapi/render/cpdf_renderstatus.cpp
index d5574a0..4bd8248 100644
--- a/core/fpdfapi/render/cpdf_renderstatus.cpp
+++ b/core/fpdfapi/render/cpdf_renderstatus.cpp
@@ -666,9 +666,11 @@
   bitmap_render.ProcessObjectNoClip(pPageObj, new_matrix);
 #ifdef _SKIA_SUPPORT_
   if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer()) {
-    bitmap->UnPreMultiply();
+    // Safe because `CFX_SkiaDeviceDriver` always uses pre-multiplied alpha.
+    // TODO(crbug.com/pdfium/2011): Remove the need for this.
+    bitmap->ForcePreMultiply();
   }
-#endif  // _SKIA_SUPPORT_
+#endif  // _SKIA_SUPPORT
   m_bStopped = bitmap_render.m_bStopped;
   if (pSMaskDict) {
     CFX_Matrix smask_matrix =
@@ -685,10 +687,6 @@
   if (group_alpha != 1.0f && transparency.IsGroup()) {
     bitmap_device.MultiplyAlpha(group_alpha);
   }
-#if defined(_SKIA_SUPPORT_)
-  if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
-    bitmap->PreMultiply();
-#endif
   transparency = m_Transparency;
   if (pPageObj->IsForm()) {
     transparency.SetGroup();
diff --git a/core/fxge/skia/fx_skia_device.cpp b/core/fxge/skia/fx_skia_device.cpp
index 8612ff0..e7ed359 100644
--- a/core/fxge/skia/fx_skia_device.cpp
+++ b/core/fxge/skia/fx_skia_device.cpp
@@ -51,12 +51,14 @@
 #include "third_party/base/ptr_util.h"
 #include "third_party/base/span.h"
 #include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkBlendMode.h"
 #include "third_party/skia/include/core/SkCanvas.h"
 #include "third_party/skia/include/core/SkClipOp.h"
 #include "third_party/skia/include/core/SkColorFilter.h"
 #include "third_party/skia/include/core/SkColorPriv.h"
 #include "third_party/skia/include/core/SkColorType.h"
 #include "third_party/skia/include/core/SkImage.h"
+#include "third_party/skia/include/core/SkImageInfo.h"
 #include "third_party/skia/include/core/SkMaskFilter.h"
 #include "third_party/skia/include/core/SkPaint.h"
 #include "third_party/skia/include/core/SkPath.h"
@@ -1105,11 +1107,32 @@
 }
 
 bool CFX_SkiaDeviceDriver::MultiplyAlpha(float alpha) {
-  return m_pBitmap->MultiplyAlpha(static_cast<int32_t>(alpha * 255));
+  SkPaint paint;
+  paint.setAlphaf(alpha);
+  paint.setBlendMode(SkBlendMode::kDstIn);
+  m_pCanvas->drawPaint(paint);
+  return true;
 }
 
 bool CFX_SkiaDeviceDriver::MultiplyAlpha(const RetainPtr<CFX_DIBBase>& mask) {
-  return m_pBitmap->MultiplyAlpha(mask);
+  if (!mask->IsMaskFormat()) {
+    NOTREACHED();
+    return false;
+  }
+
+  // Storage vector must outlive `skia_mask`.
+  DataVector<uint32_t> dst32_storage;
+  SkBitmap skia_mask;
+  if (!Upsample(mask, dst32_storage, &skia_mask, /*forceAlpha=*/true)) {
+    return false;
+  }
+
+  SkPaint paint;
+  paint.setBlendMode(SkBlendMode::kDstIn);
+  m_pCanvas->drawImageRect(skia_mask.asImage(),
+                           SkRect::Make(m_pCanvas->imageInfo().bounds()),
+                           SkSamplingOptions(), &paint);
+  return true;
 }
 
 DeviceType CFX_SkiaDeviceDriver::GetDeviceType() const {
diff --git a/testing/resources/pixel/bug_1949_expected_skia.pdf.0.png b/testing/resources/pixel/bug_1949_expected_skia.pdf.0.png
new file mode 100644
index 0000000..6d4ea6d
--- /dev/null
+++ b/testing/resources/pixel/bug_1949_expected_skia.pdf.0.png
Binary files differ