Generate clipping path when processing the graphics of page objects When reprocessing the graphics of an edited/dirty page object, the clipping path is ignored. Keep those clipping paths instead. Bug: pdfium:1558 Change-Id: Idead22cbf7796a8971e3af164464d8c80956d1e7 Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/71713 Reviewed-by: Lei Zhang <thestig@chromium.org> Commit-Queue: Daniel Hosseinian <dhoss@chromium.org>
diff --git a/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp b/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp index 573b40c..b07622a 100644 --- a/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp +++ b/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
@@ -404,6 +404,8 @@ // "rg" sets the fill color, "RG" sets the stroke color (using DefaultRGB) // "w" sets the stroke line width. // "ca" sets the fill alpha, "CA" sets the stroke alpha. +// "W" and "W*" modify the clipping path using the nonzero winding rule and +// even-odd rules, respectively. // "q" saves the graphics state, so that the settings can later be reversed void CPDF_PageContentGenerator::ProcessGraphics(std::ostringstream* buf, CPDF_PageObject* pPageObj) { @@ -428,6 +430,29 @@ if (lineJoin != CFX_GraphStateData::LineJoinMiter) *buf << static_cast<int>(lineJoin) << " j "; + const CPDF_ClipPath& clip_path = pPageObj->m_ClipPath; + if (clip_path.HasRef()) { + for (size_t i = 0; i < clip_path.GetPathCount(); ++i) { + CPDF_Path path = clip_path.GetPath(i); + ProcessPathPoints(buf, &path); + switch (clip_path.GetClipType(i)) { + case CFX_FillRenderOptions::FillType::kWinding: + *buf << " W "; + break; + case CFX_FillRenderOptions::FillType::kEvenOdd: + *buf << " W* "; + break; + case CFX_FillRenderOptions::FillType::kNoFill: + NOTREACHED(); + break; + } + + // Use a no-op path-painting operator to terminate the path without + // causing any marks to be placed on the page. + *buf << "n 0 g "; + } + } + GraphicsData graphD; graphD.fillAlpha = pPageObj->m_GeneralState.GetFillAlpha(); graphD.strokeAlpha = pPageObj->m_GeneralState.GetStrokeAlpha();
diff --git a/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp b/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp index c3fe7f0..5e145b2 100644 --- a/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp +++ b/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp
@@ -331,6 +331,18 @@ pTextObj->m_TextState.SetFontSize(15.5f); pTextObj->SetText("I am indirect"); pTextObj->SetTextRenderMode(TextRenderingMode::MODE_FILL_CLIP); + + // Add a clipping path. + auto pPath = std::make_unique<CPDF_Path>(); + pPath->AppendPoint(CFX_PointF(0, 0), FXPT_TYPE::MoveTo); + pPath->AppendPoint(CFX_PointF(5, 0), FXPT_TYPE::LineTo); + pPath->AppendPoint(CFX_PointF(5, 4), FXPT_TYPE::LineTo); + pPath->AppendPointAndClose(CFX_PointF(0, 4), FXPT_TYPE::LineTo); + pTextObj->m_ClipPath.Emplace(); + pTextObj->m_ClipPath.AppendPath(*pPath, + CFX_FillRenderOptions::FillType::kEvenOdd, + /*bAutoMerge=*/false); + TestProcessText(&generator, &buf, pTextObj.get()); } @@ -342,7 +354,7 @@ ByteString lastString = textString.Last(textString.GetLength() - firstResourceAt.value()); // q and Q must be outside the BT .. ET operations - ByteString compareString1 = "q BT 1 0 0 1 0 0 Tm /"; + ByteString compareString1 = "q 0 0 5 4 re W* n 0 g BT 1 0 0 1 0 0 Tm /"; ByteString compareString2 = " 15.5 Tf 4 Tr <4920616D20696E646972656374> Tj ET Q\n"; EXPECT_LT(compareString1.GetLength() + compareString2.GetLength(),
diff --git a/fpdfsdk/fpdf_edit_embeddertest.cpp b/fpdfsdk/fpdf_edit_embeddertest.cpp index 0cdcb9f..6371efc 100644 --- a/fpdfsdk/fpdf_edit_embeddertest.cpp +++ b/fpdfsdk/fpdf_edit_embeddertest.cpp
@@ -658,8 +658,6 @@ CloseSavedDocument(); } -// TODO(crbug.com/pdfium/1558): Clipping paths should be retained after saving -// changed text. TEST_F(FPDFEditEmbedderTest, SetTextKeepClippingPath) { // Load document with some text, with parts clipped. ASSERT_TRUE(OpenDocument("bug_1558.pdf")); @@ -718,17 +716,8 @@ ASSERT_TRUE(saved_page); { - static constexpr char kChangedChecksum[] = -#if defined(OS_WIN) - "da44e0c040ed56dbb60cf44ef033757b"; -#elif defined(OS_MACOSX) - "0bfd2dab51dd588a7f77d531582078cd"; -#else - "e63e78fcbcfba4b64f2b843fdf2cc3e8"; -#endif - // The checksum of |saved_bitmap| should be |kOriginalChecksum|. ScopedFPDFBitmap saved_bitmap = RenderSavedPage(saved_page); - CompareBitmap(saved_bitmap.get(), 200, 200, kChangedChecksum); + CompareBitmap(saved_bitmap.get(), 200, 200, kOriginalChecksum); } CloseSavedPage(saved_page);