From 603a31d0c509c7ce3c2709dcb5377a78e6ce4815 Mon Sep 17 00:00:00 2001 From: Nicolas Pena Date: Wed, 14 Jun 2017 11:41:18 -0400 Subject: Add blend to GraphicsData MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CL [1] added the ability to set the blend mode for a page object. This CL adds the corresponding component to GraphicsData since the blend mode is part of ExtGSState. In addition, a test using the SetBlendMode method is added. [1] https://pdfium-review.googlesource.com/c/5953/ Bug: pdfium:720 Change-Id: I49120284345185c200a45cc3b37ec59f0658e2dc Reviewed-on: https://pdfium-review.googlesource.com/6510 Commit-Queue: Nicolás Peña Reviewed-by: dsinclair --- core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp | 10 ++--- core/fpdfapi/page/cpdf_page.cpp | 4 +- core/fpdfapi/page/cpdf_page.h | 1 + fpdfsdk/fpdfedit_embeddertest.cpp | 55 +++++++++++++++++++++++++ public/fpdf_edit.h | 53 ++++++++++++------------ 5 files changed, 91 insertions(+), 32 deletions(-) diff --git a/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp b/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp index e06c28d7ae..8b39a7a136 100644 --- a/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp +++ b/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp @@ -269,10 +269,10 @@ void CPDF_PageContentGenerator::ProcessGraphics(std::ostringstream* buf, GraphicsData graphD; graphD.fillAlpha = pPageObj->m_GeneralState.GetFillAlpha(); graphD.strokeAlpha = pPageObj->m_GeneralState.GetStrokeAlpha(); - int blend_type = pPageObj->m_GeneralState.GetBlendType(); + graphD.blendType = pPageObj->m_GeneralState.GetBlendType(); if (graphD.fillAlpha == 1.0f && graphD.strokeAlpha == 1.0f && - (blend_type == FXDIB_BLEND_UNSUPPORTED || - blend_type == FXDIB_BLEND_NORMAL)) { + (graphD.blendType == FXDIB_BLEND_UNSUPPORTED || + graphD.blendType == FXDIB_BLEND_NORMAL)) { return; } @@ -288,8 +288,8 @@ void CPDF_PageContentGenerator::ProcessGraphics(std::ostringstream* buf, if (graphD.strokeAlpha != 1.0f) gsDict->SetNewFor("CA", graphD.strokeAlpha); - if (blend_type != FXDIB_BLEND_UNSUPPORTED && - blend_type != FXDIB_BLEND_NORMAL) { + if (graphD.blendType != FXDIB_BLEND_UNSUPPORTED && + graphD.blendType != FXDIB_BLEND_NORMAL) { gsDict->SetNewFor("BM", pPageObj->m_GeneralState.GetBlendMode()); } diff --git a/core/fpdfapi/page/cpdf_page.cpp b/core/fpdfapi/page/cpdf_page.cpp index 092a1cad41..075aa9023d 100644 --- a/core/fpdfapi/page/cpdf_page.cpp +++ b/core/fpdfapi/page/cpdf_page.cpp @@ -183,7 +183,9 @@ int CPDF_Page::GetPageRotation() const { bool GraphicsData::operator<(const GraphicsData& other) const { if (fillAlpha != other.fillAlpha) return fillAlpha < other.fillAlpha; - return strokeAlpha < other.strokeAlpha; + if (strokeAlpha != other.strokeAlpha) + return strokeAlpha < other.strokeAlpha; + return blendType < other.blendType; } bool FontData::operator<(const FontData& other) const { diff --git a/core/fpdfapi/page/cpdf_page.h b/core/fpdfapi/page/cpdf_page.h index 77cc793d81..0a080a58ae 100644 --- a/core/fpdfapi/page/cpdf_page.h +++ b/core/fpdfapi/page/cpdf_page.h @@ -26,6 +26,7 @@ class CPDF_PageRenderContext; struct GraphicsData { float fillAlpha; float strokeAlpha; + int blendType; bool operator<(const GraphicsData& other) const; }; diff --git a/fpdfsdk/fpdfedit_embeddertest.cpp b/fpdfsdk/fpdfedit_embeddertest.cpp index 40081e6d75..1146a8c546 100644 --- a/fpdfsdk/fpdfedit_embeddertest.cpp +++ b/fpdfsdk/fpdfedit_embeddertest.cpp @@ -556,6 +556,61 @@ TEST_F(FPDFEditEmbeddertest, AddStandardFontText) { FPDF_ClosePage(page); } +TEST_F(FPDFEditEmbeddertest, GraphicsData) { + // New page + std::unique_ptr page( + FPDFPage_New(CreateNewDocument(), 0, 612, 792)); + + // Create a rect with nontrivial graphics + FPDF_PAGEOBJECT rect1 = FPDFPageObj_CreateNewRect(10, 10, 100, 100); + FPDFPageObj_SetBlendMode(rect1, "Color"); + FPDFPage_InsertObject(page.get(), rect1); + EXPECT_TRUE(FPDFPage_GenerateContent(page.get())); + + // Check that the ExtGState was created + CPDF_Page* the_page = CPDFPageFromFPDFPage(page.get()); + CPDF_Dictionary* graphics_dict = + the_page->m_pResources->GetDictFor("ExtGState"); + ASSERT_TRUE(graphics_dict); + EXPECT_EQ(1, static_cast(graphics_dict->GetCount())); + + // Add a text object causing no change to the graphics dictionary + FPDF_PAGEOBJECT text1 = FPDFPageObj_NewTextObj(document(), "Arial", 12.0f); + // Only alpha, the last component, matters for the graphics dictionary. And + // the default value is 255. + EXPECT_TRUE(FPDFText_SetFillColor(text1, 100, 100, 100, 255)); + FPDFPage_InsertObject(page.get(), text1); + EXPECT_TRUE(FPDFPage_GenerateContent(page.get())); + EXPECT_EQ(1, static_cast(graphics_dict->GetCount())); + + // Add a text object increasing the size of the graphics dictionary + FPDF_PAGEOBJECT text2 = + FPDFPageObj_NewTextObj(document(), "Times-Roman", 12.0f); + FPDFPage_InsertObject(page.get(), text2); + FPDFPageObj_SetBlendMode(text2, "Darken"); + EXPECT_TRUE(FPDFText_SetFillColor(text2, 0, 0, 255, 150)); + EXPECT_TRUE(FPDFPage_GenerateContent(page.get())); + EXPECT_EQ(2, static_cast(graphics_dict->GetCount())); + + // Add a path that should reuse graphics + // TODO(npm): This causes a crash on Windows. + /*FPDF_PAGEOBJECT path = FPDFPageObj_CreateNewPath(400, 100); + FPDFPageObj_SetBlendMode(path, "Darken"); + EXPECT_TRUE(FPDFPath_SetFillColor(path, 200, 200, 100, 150)); + FPDFPage_InsertObject(page.get(), path); + EXPECT_TRUE(FPDFPage_GenerateContent(page.get())); + EXPECT_EQ(2, static_cast(graphics_dict->GetCount()));*/ + + // Add a rect increasing the size of the graphics dictionary + FPDF_PAGEOBJECT rect2 = FPDFPageObj_CreateNewRect(10, 10, 100, 100); + FPDFPageObj_SetBlendMode(rect2, "Darken"); + EXPECT_TRUE(FPDFPath_SetFillColor(rect2, 0, 0, 255, 150)); + EXPECT_TRUE(FPDFPath_SetStrokeColor(rect2, 0, 0, 0, 200)); + FPDFPage_InsertObject(page.get(), rect2); + EXPECT_TRUE(FPDFPage_GenerateContent(page.get())); + EXPECT_EQ(3, static_cast(graphics_dict->GetCount())); +} + TEST_F(FPDFEditEmbeddertest, DoubleGenerating) { // Start with a blank page FPDF_PAGE page = FPDFPage_New(CreateNewDocument(), 0, 612, 792); diff --git a/public/fpdf_edit.h b/public/fpdf_edit.h index aceca351cd..022832fe78 100644 --- a/public/fpdf_edit.h +++ b/public/fpdf_edit.h @@ -136,23 +136,23 @@ DLLEXPORT FPDF_BOOL STDCALL FPDFPage_HasTransparency(FPDF_PAGE page); // |FPDFPage_GenerateContent| or any changes to |page| will be lost. DLLEXPORT FPDF_BOOL STDCALL FPDFPage_GenerateContent(FPDF_PAGE page); -// Checks if |pageObject| contains transparency. +// Checks if |page_object| contains transparency. // -// pageObject - handle to a page object. +// page_object - handle to a page object. // // Returns TRUE if |pageObject| contains transparency. DLLEXPORT FPDF_BOOL STDCALL -FPDFPageObj_HasTransparency(FPDF_PAGEOBJECT pageObject); +FPDFPageObj_HasTransparency(FPDF_PAGEOBJECT page_object); -// Get type of |pageObject|. +// Get type of |page_object|. // -// pageObject - handle to a page object. +// page_object - handle to a page object. // // Returns one of the FPDF_PAGEOBJ_* values on success, FPDF_PAGEOBJ_UNKNOWN on // error. -DLLEXPORT int STDCALL FPDFPageObj_GetType(FPDF_PAGEOBJECT pageObject); +DLLEXPORT int STDCALL FPDFPageObj_GetType(FPDF_PAGEOBJECT page_object); -// Transform |pageObject| by the given matrix. +// Transform |page_object| by the given matrix. // // page_object - handle to a page object. // a - matrix value. @@ -304,30 +304,30 @@ DLLEXPORT FPDF_PAGEOBJECT STDCALL FPDFPageObj_CreateNewRect(float x, float w, float h); -// Get the bounding box of |pageObject|. +// Get the bounding box of |page_object|. // -// pageObject - handle to a page object. -// left - pointer where the left coordinate will be stored -// bottom - pointer where the bottom coordinate will be stored -// right - pointer where the right coordinate will be stored -// top - pointer where the top coordinate will be stored +// page_object - handle to a page object. +// left - pointer where the left coordinate will be stored +// bottom - pointer where the bottom coordinate will be stored +// right - pointer where the right coordinate will be stored +// top - pointer where the top coordinate will be stored // // Returns TRUE on success. -DLLEXPORT FPDF_BOOL STDCALL FPDFPageObj_GetBounds(FPDF_PAGEOBJECT pageObject, +DLLEXPORT FPDF_BOOL STDCALL FPDFPageObj_GetBounds(FPDF_PAGEOBJECT page_object, float* left, float* bottom, float* right, float* top); -// Set the blend mode of |pageObject|. +// Set the blend mode of |page_object|. // -// pageObject - handle to a page object. -// blend_mode - string containing the blend mode. +// page_object - handle to a page object. +// blend_mode - string containing the blend mode. // // Blend mode can be one of following: Color, ColorBurn, ColorDodge, Darken, // Difference, Exclusion, HardLight, Hue, Lighten, Luminosity, Multiply, Normal, // Overlay, Saturation, Screen, SoftLight -DLLEXPORT void STDCALL FPDFPageObj_SetBlendMode(FPDF_PAGEOBJECT page, +DLLEXPORT void STDCALL FPDFPageObj_SetBlendMode(FPDF_PAGEOBJECT page_object, FPDF_BYTESTRING blend_mode); // Set the stroke RGBA of a path. Range of values: 0 - 255. @@ -353,24 +353,25 @@ DLLEXPORT FPDF_BOOL FPDFPath_SetStrokeColor(FPDF_PAGEOBJECT path, // Returns TRUE on success DLLEXPORT FPDF_BOOL FPDFPath_SetStrokeWidth(FPDF_PAGEOBJECT path, float width); -// Set the line join of |pageObject|. +// Set the line join of |page_object|. // -// pageObject - handle to a page object. -// line_join - line join +// page_object - handle to a page object. +// line_join - line join // // Line join can be one of following: FPDF_LINEJOIN_MITER, FPDF_LINEJOIN_ROUND, // FPDF_LINEJOIN_BEVEL -DLLEXPORT void STDCALL FPDFPath_SetLineJoin(FPDF_PAGEOBJECT page, +DLLEXPORT void STDCALL FPDFPath_SetLineJoin(FPDF_PAGEOBJECT page_object, int line_join); -// Set the line cap of |pageObject|. +// Set the line cap of |page_object|. // -// pageObject - handle to a page object. -// line_cap - line cap +// page_object - handle to a page object. +// line_cap - line cap // // Line cap can be one of following: FPDF_LINECAP_BUTT, FPDF_LINECAP_ROUND, // FPDF_LINECAP_PROJECTING_SQUARE -DLLEXPORT void STDCALL FPDFPath_SetLineCap(FPDF_PAGEOBJECT page, int line_cap); +DLLEXPORT void STDCALL FPDFPath_SetLineCap(FPDF_PAGEOBJECT page_object, + int line_cap); // Set the fill RGBA of a path. Range of values: 0 - 255. // -- cgit v1.2.3