M126: 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> (cherry picked from commit 3d82f31bff680789d1e428c70875b1490ab8530b) Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/121551 Reviewed-by: Tom Sepez <tsepez@google.com>
diff --git a/core/fxge/agg/fx_agg_driver.cpp b/core/fxge/agg/fx_agg_driver.cpp index ecdaae2..8f52d19 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 1046cf4..c4582f4 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