Fix FPDFTextObj_SetTextRenderMode() to stick when the document is saved CPDF_PageContentGenerator::ProcessText() neglected to set the text rendering mode in the content stream. Bug: pdfium:1470 Change-Id: I507109cf65b35ce491342d59fc0f37309f9a9d21 Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/71092 Commit-Queue: Daniel Hosseinian <dhoss@chromium.org> Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp b/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp index 34dde67..580b36e 100644 --- a/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp +++ b/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
@@ -488,6 +488,7 @@ // This method adds text to the buffer, BT begins the text object, ET ends it. // Tm sets the text matrix (allows positioning and transforming text). // Tf sets the font name (from Font in Resources) and font size. +// Tr sets the text rendering mode. // Tj sets the actual text, <####...> is used when specifying charcodes. void CPDF_PageContentGenerator::ProcessText(std::ostringstream* buf, CPDF_TextObject* pTextObj) { @@ -534,6 +535,7 @@ } *buf << "/" << PDF_NameEncode(dictName) << " "; WriteFloat(*buf, pTextObj->GetFontSize()) << " Tf "; + *buf << static_cast<int>(pTextObj->GetTextRenderMode()) << " Tr "; ByteString text; for (uint32_t charcode : pTextObj->GetCharCodes()) { if (charcode != CPDF_Font::kInvalidCharCode)
diff --git a/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp b/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp index f21d449..60f5057 100644 --- a/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp +++ b/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp
@@ -15,6 +15,7 @@ #include "core/fpdfapi/page/cpdf_pagemodule.h" #include "core/fpdfapi/page/cpdf_pathobject.h" #include "core/fpdfapi/page/cpdf_textobject.h" +#include "core/fpdfapi/page/cpdf_textstate.h" #include "core/fpdfapi/parser/cpdf_dictionary.h" #include "core/fpdfapi/parser/cpdf_document.h" #include "core/fpdfapi/parser/cpdf_name.h" @@ -274,7 +275,7 @@ "q 0.501961 0.701961 0.34902 rg 1 0.901961 0 RG /"; // Color RGB values used are integers divided by 255. ByteString compareString2 = " gs BT 1 0 0 1 100 100 Tm /"; - ByteString compareString3 = " 10 Tf <48656C6C6F20576F726C64> Tj ET Q\n"; + ByteString compareString3 = " 10 Tf 0 Tr <48656C6C6F20576F726C64> Tj ET Q\n"; EXPECT_LT(compareString1.GetLength() + compareString2.GetLength() + compareString3.GetLength(), textString.GetLength()); @@ -329,6 +330,7 @@ pTextObj->m_TextState.SetFont(pLoadedFont); pTextObj->m_TextState.SetFontSize(15.5f); pTextObj->SetText("I am indirect"); + pTextObj->SetTextRenderMode(TextRenderingMode::MODE_FILL_CLIP); TestProcessText(&generator, &buf, pTextObj.get()); } @@ -341,7 +343,8 @@ 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 compareString2 = " 15.5 Tf <4920616D20696E646972656374> Tj ET Q\n"; + ByteString compareString2 = + " 15.5 Tf 4 Tr <4920616D20696E646972656374> Tj ET Q\n"; EXPECT_LT(compareString1.GetLength() + compareString2.GetLength(), textString.GetLength()); EXPECT_EQ(compareString1, textString.First(compareString1.GetLength()));
diff --git a/core/fpdfapi/page/cpdf_textobject.cpp b/core/fpdfapi/page/cpdf_textobject.cpp index 3872a2c..beb3ce9 100644 --- a/core/fpdfapi/page/cpdf_textobject.cpp +++ b/core/fpdfapi/page/cpdf_textobject.cpp
@@ -258,6 +258,7 @@ void CPDF_TextObject::SetTextRenderMode(TextRenderingMode mode) { m_TextState.SetTextMode(mode); + SetDirty(true); } CFX_PointF CPDF_TextObject::CalcPositionData(float horz_scale) {
diff --git a/fpdfsdk/fpdf_edit_embeddertest.cpp b/fpdfsdk/fpdf_edit_embeddertest.cpp index cb7c8fb..cffeb7c 100644 --- a/fpdfsdk/fpdf_edit_embeddertest.cpp +++ b/fpdfsdk/fpdf_edit_embeddertest.cpp
@@ -2122,27 +2122,27 @@ CompareBitmap(page_bitmap.get(), 612, 446, md5_stroke); } + // Save a copy. + EXPECT_TRUE(FPDFPage_GenerateContent(page)); + EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0)); + UnloadPage(page); } { - // Save a copy, open the copy, and render it. - // Note that the text render mode should be set to - // |FPDF_TEXTRENDERMODE_STROKE|, but isn't. - // TODO(crbug.com/pdfium/1470): Fix FPDFTextObj_SetTextRenderMode() to work - // on saved documents. - EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0)); + // Open the saved copy and render it. Check that the changed text render + // mode is kept in the saved copy. ASSERT_TRUE(OpenSavedDocument()); FPDF_PAGE saved_page = LoadSavedPage(0); ASSERT_TRUE(saved_page); FPDF_PAGEOBJECT page_object = FPDFPage_GetObject(saved_page, 0); EXPECT_TRUE(page_object); - EXPECT_EQ(FPDF_TEXTRENDERMODE_FILL, + EXPECT_EQ(FPDF_TEXTRENDERMODE_STROKE, FPDFTextObj_GetTextRenderMode(page_object)); ScopedFPDFBitmap bitmap = RenderSavedPage(saved_page); - CompareBitmap(bitmap.get(), 612, 446, md5); + CompareBitmap(bitmap.get(), 612, 446, md5_stroke); CloseSavedPage(saved_page); CloseSavedDocument();