Change FPDFImageObj_GetRenderedBitmap() to take clip path into account

If there exists a clip path for a bitmap, then only part of the bitmap
should be rendered. Change FPDFImageObj_GetRenderedBitmap() to take the
clip path into account. To do so, the clip path has to be transformed to
match the image:

1) The image may have been transformed by PDFium APIs.
2) The image has to be transformed from where it is on the page to fit
   into the output bitmap.

After which, the clip path needs to be transformed one more time to be
flipped around, which is what CPDF_RenderStatus::ProcessClipPath()
expects, similar to CPDF_ImageRenderer::Start().

Bug: 406540676
Change-Id: I28eca20d4becf799be54d0cf093af31ba7f4c4f7
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/130450
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/fpdfsdk/fpdf_editimg.cpp b/fpdfsdk/fpdf_editimg.cpp
index a149e5e..5baf512 100644
--- a/fpdfsdk/fpdf_editimg.cpp
+++ b/fpdfsdk/fpdf_editimg.cpp
@@ -324,21 +324,35 @@
   CPDF_ImageRenderer renderer(&status);
 
   // Need to first flip the image, as expected by |renderer|.
-  CFX_Matrix render_matrix(1, 0, 0, -1, 0, output_height);
+  const CFX_Matrix render_matrix(1, 0, 0, -1, 0, output_height);
 
   // Then take |image_matrix|'s offset into account.
   float min_x = image_matrix.e + std::min(image_matrix.a, image_matrix.c);
   float min_y = image_matrix.f + std::min(image_matrix.b, image_matrix.d);
-  render_matrix.Translate(-min_x, min_y);
+  CFX_Matrix image_render_matrix = render_matrix;
+  image_render_matrix.Translate(-min_x, min_y);
+
+  // Apply the clip path if there is one.
+  if (image->clip_path().HasRef()) {
+    CFX_FloatRect output_rect(0, 0, output_width, output_height);
+    CFX_FloatRect original_image_rect =
+        image->original_matrix().TransformRect(CFX_FloatRect(0, 0, 1, 1));
+    CFX_Matrix clip_render_matrix;
+    clip_render_matrix.MatchRect(output_rect, original_image_rect);
+    clip_render_matrix.Concat(render_matrix);
+    status.ProcessClipPath(image->clip_path(), clip_render_matrix);
+  }
 
   // Do the actual rendering.
-  bool should_continue = renderer.Start(image, render_matrix, /*bStdCS=*/false);
+  bool should_continue =
+      renderer.Start(image, image_render_matrix, /*bStdCS=*/false);
   while (should_continue) {
     should_continue = renderer.Continue(/*pPause=*/nullptr);
   }
 
-  if (!renderer.GetResult())
+  if (!renderer.GetResult()) {
     return nullptr;
+  }
 
   ValidateBitmapPremultiplyState(result_bitmap);