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