From 864e9fb67f42186ce24d9bf09e643c85ff89a175 Mon Sep 17 00:00:00 2001 From: wileyrya Date: Fri, 26 May 2017 11:38:14 -0500 Subject: Add public API for setting the fill color on a text object MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit BUG=pdfium:719 R=npm@chromium.org Change-Id: Ifd9330de265f8419d588b65fbd6a6187f17badd1 Reviewed-on: https://pdfium-review.googlesource.com/5950 Reviewed-by: Nicolás Peña Commit-Queue: Nicolás Peña --- AUTHORS | 3 +- core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp | 4 +- .../edit/cpdf_pagecontentgenerator_unittest.cpp | 58 ++++++++++++++++++---- fpdfsdk/fpdfeditpage.cpp | 16 ++++++ fpdfsdk/fpdfeditpath.cpp | 11 +--- fpdfsdk/fpdfedittext.cpp | 8 +++ fpdfsdk/fsdk_define.h | 5 ++ public/fpdf_edit.h | 15 ++++++ 8 files changed, 100 insertions(+), 20 deletions(-) diff --git a/AUTHORS b/AUTHORS index 7499c1094c..9b63c71c56 100644 --- a/AUTHORS +++ b/AUTHORS @@ -31,7 +31,8 @@ Miklos Vajna Nico Weber Peter Kasting Raymes Khoury -Reid Kleckner +Reid Kleckner +Ryan Wiley Robert Sesek Sam Clegg Thomas Sepez diff --git a/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp b/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp index 6643035b09..e9ea064810 100644 --- a/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp +++ b/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp @@ -289,5 +289,7 @@ void CPDF_PageContentGenerator::ProcessText(CFX_ByteTextBuf* buf, if (charcode != CPDF_Font::kInvalidCharCode) pFont->AppendChar(&text, charcode); } - *buf << PDF_EncodeString(text, true) << " Tj ET\n"; + ProcessGraphics(buf, pTextObj); + *buf << PDF_EncodeString(text, true) << " Tj ET"; + *buf << " Q\n"; } diff --git a/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp b/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp index 1f2d216ed5..8368e8de7c 100644 --- a/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp +++ b/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp @@ -167,16 +167,46 @@ TEST_F(CPDF_PageContentGeneratorTest, ProcessStandardText) { CPDF_Font* pFont = CPDF_Font::GetStockFont(pDoc.get(), "Times-Roman"); pTextObj->m_TextState.SetFont(pFont); pTextObj->m_TextState.SetFontSize(10.0f); + float rgb[3] = {0.5f, 0.7f, 0.35f}; + CPDF_ColorSpace* pCS = CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB); + pTextObj->m_ColorState.SetFillColor(pCS, rgb, 3); + + float rgb2[3] = {1, 0.9f, 0}; + pTextObj->m_ColorState.SetStrokeColor(pCS, rgb2, 3); + pTextObj->m_GeneralState.SetFillAlpha(0.5f); + pTextObj->m_GeneralState.SetStrokeAlpha(0.8f); pTextObj->Transform(CFX_Matrix(1, 0, 0, 1, 100, 100)); pTextObj->SetText("Hello World"); CFX_ByteTextBuf buf; TestProcessText(&generator, &buf, pTextObj.get()); CFX_ByteString textString = buf.MakeString(); - EXPECT_LT(61, textString.GetLength()); - EXPECT_EQ("BT 1 0 0 1 100 100 Tm /", textString.Left(23)); - EXPECT_EQ(" 10 Tf <48656C6C6F20576F726C64> Tj ET\n", textString.Right(38)); + int firstResourceAt = textString.Find('/') + 1; + int secondResourceAt = textString.ReverseFind('/') + 1; + CFX_ByteString firstString = textString.Left(firstResourceAt); + CFX_ByteString midString = + textString.Mid(firstResourceAt, secondResourceAt - firstResourceAt); + CFX_ByteString lastString = + textString.Right(textString.GetLength() - secondResourceAt); + CFX_ByteString compareString1 = "BT 1 0 0 1 100 100 Tm /"; + // Color RGB values used are integers divided by 255. + CFX_ByteString compareString2 = + " 10 Tf q 0.501961 0.701961 0.34902 rg 1 0.901961 0 RG /"; + CFX_ByteString compareString3 = " gs <48656C6C6F20576F726C64> Tj ET Q\n"; + EXPECT_LT(compareString1.GetLength() + compareString2.GetLength() + + compareString3.GetLength(), + textString.GetLength()); + EXPECT_EQ(compareString1, firstString.Left(compareString1.GetLength())); + EXPECT_EQ(compareString2, midString.Right(compareString2.GetLength())); + EXPECT_EQ(compareString3, lastString.Right(compareString3.GetLength())); + CPDF_Dictionary* externalGS = TestGetResource( + &generator, "ExtGState", + lastString.Left(lastString.GetLength() - compareString3.GetLength())); + ASSERT_TRUE(externalGS); + EXPECT_EQ(0.5f, externalGS->GetNumberFor("ca")); + EXPECT_EQ(0.8f, externalGS->GetNumberFor("CA")); CPDF_Dictionary* fontDict = TestGetResource( - &generator, "Font", textString.Mid(23, textString.GetLength() - 61)); + &generator, "Font", + midString.Left(midString.GetLength() - compareString2.GetLength())); ASSERT_TRUE(fontDict); EXPECT_EQ("Font", fontDict->GetStringFor("Type")); EXPECT_EQ("Type1", fontDict->GetStringFor("Subtype")); @@ -216,12 +246,22 @@ TEST_F(CPDF_PageContentGeneratorTest, ProcessText) { } CFX_ByteString textString = buf.MakeString(); - EXPECT_LT(63, textString.GetLength()); - EXPECT_EQ("BT 1 0 0 1 0 0 Tm /", textString.Left(19)); - EXPECT_EQ(" 15.5 Tf <4920616D20696E646972656374> Tj ET\n", - textString.Right(44)); + int firstResourceAt = textString.Find('/') + 1; + CFX_ByteString firstString = textString.Left(firstResourceAt); + CFX_ByteString lastString = + textString.Right(textString.GetLength() - firstResourceAt); + CFX_ByteString compareString1 = "BT 1 0 0 1 0 0 Tm /"; + CFX_ByteString compareString2 = + " 15.5 Tf q <4920616D20696E646972656374> Tj ET Q\n"; + EXPECT_LT(compareString1.GetLength() + compareString2.GetLength(), + textString.GetLength()); + EXPECT_EQ(compareString1, textString.Left(compareString1.GetLength())); + EXPECT_EQ(compareString2, textString.Right(compareString2.GetLength())); CPDF_Dictionary* fontDict = TestGetResource( - &generator, "Font", textString.Mid(19, textString.GetLength() - 63)); + &generator, "Font", + textString.Mid(compareString1.GetLength(), + textString.GetLength() - compareString1.GetLength() - + compareString2.GetLength())); ASSERT_TRUE(fontDict); EXPECT_TRUE(fontDict->GetObjNum()); EXPECT_EQ("Font", fontDict->GetStringFor("Type")); diff --git a/fpdfsdk/fpdfeditpage.cpp b/fpdfsdk/fpdfeditpage.cpp index 6ed375807f..2c58caf6db 100644 --- a/fpdfsdk/fpdfeditpage.cpp +++ b/fpdfsdk/fpdfeditpage.cpp @@ -304,3 +304,19 @@ DLLEXPORT void STDCALL FPDFPage_SetRotation(FPDF_PAGE page, int rotate) { rotate %= 4; pPage->m_pFormDict->SetNewFor("Rotate", rotate * 90); } + +FPDF_BOOL FPDFPageObj_SetFillColor(FPDF_PAGEOBJECT page_object, + unsigned int R, + unsigned int G, + unsigned int B, + unsigned int A) { + if (!page_object || R > 255 || G > 255 || B > 255 || A > 255) + return false; + + float rgb[3] = {R / 255.f, G / 255.f, B / 255.f}; + auto* pPageObj = static_cast(page_object); + pPageObj->m_GeneralState.SetFillAlpha(A / 255.f); + pPageObj->m_ColorState.SetFillColor( + CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB), rgb, 3); + return true; +} diff --git a/fpdfsdk/fpdfeditpath.cpp b/fpdfsdk/fpdfeditpath.cpp index 54937ef91a..ad5ca9433f 100644 --- a/fpdfsdk/fpdfeditpath.cpp +++ b/fpdfsdk/fpdfeditpath.cpp @@ -7,6 +7,7 @@ #include "core/fpdfapi/page/cpdf_path.h" #include "core/fpdfapi/page/cpdf_pathobject.h" #include "core/fxcrt/fx_system.h" +#include "fpdfsdk/fsdk_define.h" #include "third_party/base/ptr_util.h" DLLEXPORT FPDF_PAGEOBJECT STDCALL FPDFPageObj_CreateNewPath(float x, float y) { @@ -56,15 +57,7 @@ DLLEXPORT FPDF_BOOL FPDFPath_SetFillColor(FPDF_PAGEOBJECT path, unsigned int G, unsigned int B, unsigned int A) { - if (!path || R > 255 || G > 255 || B > 255 || A > 255) - return false; - - float rgb[3] = {R / 255.f, G / 255.f, B / 255.f}; - auto* pPathObj = static_cast(path); - pPathObj->m_GeneralState.SetFillAlpha(A / 255.f); - pPathObj->m_ColorState.SetFillColor( - CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB), rgb, 3); - return true; + return FPDFPageObj_SetFillColor(path, R, G, B, A); } DLLEXPORT FPDF_BOOL FPDFPath_GetFillColor(FPDF_PAGEOBJECT path, diff --git a/fpdfsdk/fpdfedittext.cpp b/fpdfsdk/fpdfedittext.cpp index 2dde2e6624..3deae7ea20 100644 --- a/fpdfsdk/fpdfedittext.cpp +++ b/fpdfsdk/fpdfedittext.cpp @@ -447,6 +447,14 @@ DLLEXPORT FPDF_FONT STDCALL FPDFText_LoadFont(FPDF_DOCUMENT document, : LoadSimpleFont(pDoc, std::move(pFont), data, size, font_type); } +DLLEXPORT FPDF_BOOL STDCALL FPDFText_SetFillColor(FPDF_PAGEOBJECT text_object, + unsigned int R, + unsigned int G, + unsigned int B, + unsigned int A) { + return FPDFPageObj_SetFillColor(text_object, R, G, B, A); +} + DLLEXPORT void STDCALL FPDFFont_Close(FPDF_FONT font) { CPDF_Font* pFont = static_cast(font); if (!pFont) diff --git a/fpdfsdk/fsdk_define.h b/fpdfsdk/fsdk_define.h index b7691bbdd9..e14cc19ea1 100644 --- a/fpdfsdk/fsdk_define.h +++ b/fpdfsdk/fsdk_define.h @@ -79,5 +79,10 @@ void FPDF_RenderPage_Retail(CPDF_PageRenderContext* pContext, void CheckUnSupportError(CPDF_Document* pDoc, uint32_t err_code); void CheckUnSupportAnnot(CPDF_Document* pDoc, const CPDF_Annot* pPDFAnnot); void ProcessParseError(CPDF_Parser::Error err); +FPDF_BOOL FPDFPageObj_SetFillColor(FPDF_PAGEOBJECT page_object, + unsigned int R, + unsigned int G, + unsigned int B, + unsigned int A); #endif // FPDFSDK_FSDK_DEFINE_H_ diff --git a/public/fpdf_edit.h b/public/fpdf_edit.h index 47a0e68f5a..904231f09f 100644 --- a/public/fpdf_edit.h +++ b/public/fpdf_edit.h @@ -469,6 +469,21 @@ DLLEXPORT FPDF_FONT STDCALL FPDFText_LoadFont(FPDF_DOCUMENT document, int font_type, FPDF_BOOL cid); +// Set the fill RGBA of a text object. Range of values: 0 - 255. +// +// text_object - handle to the text object. +// R - the red component for the path fill color. +// G - the green component for the path fill color. +// B - the blue component for the path fill color. +// A - the fill alpha for the path. +// +// Returns TRUE on success. +DLLEXPORT FPDF_BOOL STDCALL FPDFText_SetFillColor(FPDF_PAGEOBJECT text_object, + unsigned int R, + unsigned int G, + unsigned int B, + unsigned int A); + // Close a loaded PDF font. // // font - Handle to the loaded font. -- cgit v1.2.3