Fix regression in CFX_AggDeviceDriver::SetClipMask()

In https://pdfium-review.googlesource.com/115412, SetClipMask()
accidentally returned early and failed to do clipping when the clip box
is empty. Adjust the code to restore the original behavior, so
CFX_ClipRgn::IntersectMaskF() still gets called. Then change
IntersectMaskF() to tolerate empty bitmaps.

Add yet another rectangles.in variant as a pixel test to exercise this
case. With a 0x0 clip box, the PDF should render blank.

Bug: 341357062
Change-Id: I05d1b096d9652668aa338ca95ab20de91ccfeace
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/119430
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/fxge/agg/fx_agg_driver.cpp b/core/fxge/agg/fx_agg_driver.cpp
index f036674..76d8ea1 100644
--- a/core/fxge/agg/fx_agg_driver.cpp
+++ b/core/fxge/agg/fx_agg_driver.cpp
@@ -1060,23 +1060,22 @@
   FX_RECT path_rect(rasterizer.min_x(), rasterizer.min_y(),
                     rasterizer.max_x() + 1, rasterizer.max_y() + 1);
   path_rect.Intersect(m_pClipRgn->GetBox());
-  if (path_rect.IsEmpty()) {
-    return;
-  }
   auto pThisLayer = pdfium::MakeRetain<CFX_DIBitmap>();
-  CHECK(pThisLayer->Create(path_rect.Width(), path_rect.Height(),
-                           FXDIB_Format::k8bppMask));
-  agg::rendering_buffer raw_buf(pThisLayer->GetWritableBuffer().data(),
-                                pThisLayer->GetWidth(), pThisLayer->GetHeight(),
-                                pThisLayer->GetPitch());
-  agg::pixfmt_gray8 pixel_buf(raw_buf);
-  agg::renderer_base<agg::pixfmt_gray8> base_buf(pixel_buf);
-  RendererScanLineAaOffset<agg::renderer_base<agg::pixfmt_gray8>> final_render(
-      base_buf, path_rect.left, path_rect.top);
-  final_render.color(agg::gray8(255));
-  agg::scanline_u8 scanline;
-  agg::render_scanlines(rasterizer, scanline, final_render,
-                        m_FillOptions.aliased_path);
+  if (!path_rect.IsEmpty()) {
+    CHECK(pThisLayer->Create(path_rect.Width(), path_rect.Height(),
+                             FXDIB_Format::k8bppMask));
+    agg::rendering_buffer raw_buf(
+        pThisLayer->GetWritableBuffer().data(), pThisLayer->GetWidth(),
+        pThisLayer->GetHeight(), pThisLayer->GetPitch());
+    agg::pixfmt_gray8 pixel_buf(raw_buf);
+    agg::renderer_base<agg::pixfmt_gray8> base_buf(pixel_buf);
+    RendererScanLineAaOffset<agg::renderer_base<agg::pixfmt_gray8>>
+        final_render(base_buf, path_rect.left, path_rect.top);
+    final_render.color(agg::gray8(255));
+    agg::scanline_u8 scanline;
+    agg::render_scanlines(rasterizer, scanline, final_render,
+                          m_FillOptions.aliased_path);
+  }
   m_pClipRgn->IntersectMaskF(path_rect.left, path_rect.top,
                              std::move(pThisLayer));
 }
diff --git a/core/fxge/cfx_cliprgn.cpp b/core/fxge/cfx_cliprgn.cpp
index e4e0884..a78fcf9 100644
--- a/core/fxge/cfx_cliprgn.cpp
+++ b/core/fxge/cfx_cliprgn.cpp
@@ -63,9 +63,13 @@
 void CFX_ClipRgn::IntersectMaskF(int left,
                                  int top,
                                  RetainPtr<CFX_DIBitmap> pMask) {
-  DCHECK_EQ(pMask->GetFormat(), FXDIB_Format::k8bppMask);
   FX_RECT mask_box(left, top, left + pMask->GetWidth(),
                    top + pMask->GetHeight());
+  if (!mask_box.IsEmpty()) {
+    // Make sure non-empty masks have the right format. If the mask is empty,
+    // then the format does not matter as it will not get used.
+    CHECK_EQ(pMask->GetFormat(), FXDIB_Format::k8bppMask);
+  }
   if (m_Type == kRectI) {
     IntersectMaskRect(m_Box, mask_box, std::move(pMask));
     return;
diff --git a/testing/resources/pixel/rectangles_clipped.in b/testing/resources/pixel/rectangles_clipped.in
new file mode 100644
index 0000000..4dd738a
--- /dev/null
+++ b/testing/resources/pixel/rectangles_clipped.in
@@ -0,0 +1,46 @@
+{{header}}
+{{object 1 0}} <<
+  /Type /Catalog
+  /Pages 2 0 R
+>>
+endobj
+{{object 2 0}} <<
+  /Type /Pages
+  /MediaBox [0 0 200 300]
+  /Count 1
+  /Kids [3 0 R]
+>>
+endobj
+{{object 3 0}} <<
+  /Type /Page
+  /Parent 2 0 R
+  /Contents 4 0 R
+>>
+endobj
+{{object 4 0}} <<
+  {{streamlen}}
+>>
+stream
+q
+0 0 0 0 re
+W
+n
+0 0 0 rg
+0 290 10 10 re B*
+10 150 50 30 re B*
+0 0 1 rg
+190 290 10 10 re B*
+70 232 50 30 re B*
+0 1 0 rg
+190 0 10 10 re B*
+130 150 50 30 re B*
+1 0 0 rg
+0 0 10 10 re B*
+70 67 50 30 re B*
+Q
+endstream
+endobj
+{{xref}}
+{{trailer}}
+{{startxref}}
+%%EOF
diff --git a/testing/resources/pixel/rectangles_clipped_expected.pdf.0.png b/testing/resources/pixel/rectangles_clipped_expected.pdf.0.png
new file mode 100644
index 0000000..e57c3e8
--- /dev/null
+++ b/testing/resources/pixel/rectangles_clipped_expected.pdf.0.png
Binary files differ