From f9baca8709472f71fe0e5bcae95717b7f712b4a5 Mon Sep 17 00:00:00 2001 From: Nicolas Pena Date: Mon, 6 Feb 2017 12:01:21 -0500 Subject: Add support for fill and stroke RGBA in CPDF_PageContentGenerator MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit CPDF_PageObject is a CPDF_GraphicStates, which allows us to add graphics information to the object itself. The RGB can be added easily in the stream. The alpha parameter needs to be in a dictionary contained in the ExtGState, which should be part of the page's resources. BUG=pdfium:661 Change-Id: Id99b2ece7aa201e3550c765ac2b5eeff4b43fc48 Reviewed-on: https://pdfium-review.googlesource.com/2530 Reviewed-by: dsinclair Reviewed-by: Tom Sepez Commit-Queue: Nicolás Peña --- core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp | 71 ++++++++++++++++++++++++- 1 file changed, 70 insertions(+), 1 deletion(-) (limited to 'core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp') diff --git a/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp b/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp index e2354e1b50..9dba6e0ceb 100644 --- a/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp +++ b/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp @@ -6,6 +6,9 @@ #include "core/fpdfapi/edit/cpdf_pagecontentgenerator.h" +#include +#include + #include "core/fpdfapi/page/cpdf_docpagedata.h" #include "core/fpdfapi/page/cpdf_image.h" #include "core/fpdfapi/page/cpdf_imageobject.h" @@ -15,6 +18,7 @@ #include "core/fpdfapi/parser/cpdf_dictionary.h" #include "core/fpdfapi/parser/cpdf_document.h" #include "core/fpdfapi/parser/cpdf_name.h" +#include "core/fpdfapi/parser/cpdf_number.h" #include "core/fpdfapi/parser/cpdf_reference.h" #include "core/fpdfapi/parser/cpdf_stream.h" #include "core/fpdfapi/parser/fpdf_parser_decode.h" @@ -27,6 +31,19 @@ CFX_ByteTextBuf& operator<<(CFX_ByteTextBuf& ar, const CFX_Matrix& matrix) { return ar; } +bool GetColor(const CPDF_Color* pColor, FX_FLOAT* rgb) { + int intRGB[3]; + if (!pColor || + pColor->GetColorSpace() != CPDF_ColorSpace::GetStockCS(PDFCS_DEVICERGB) || + !pColor->GetRGB(intRGB[0], intRGB[1], intRGB[2])) { + return false; + } + rgb[0] = intRGB[0] / 255.0f; + rgb[1] = intRGB[1] / 255.0f; + rgb[2] = intRGB[2] / 255.0f; + return true; +} + } // namespace CPDF_PageContentGenerator::CPDF_PageContentGenerator(CPDF_Page* pPage) @@ -123,8 +140,10 @@ void CPDF_PageContentGenerator::ProcessImage(CFX_ByteTextBuf* buf, // "h" closes the subpath (appends a line from current to starting point) // Path painting operators: "S", "n", "B", "f", "B*", "f*", depending on // the filling mode and whether we want stroking the path or not. +// "Q" restores the graphics state imposed by the ProcessGraphics method. void CPDF_PageContentGenerator::ProcessPath(CFX_ByteTextBuf* buf, CPDF_PathObject* pPathObj) { + ProcessGraphics(buf, pPathObj); const FX_PATHPOINT* pPoints = pPathObj->m_Path.GetPoints(); if (pPathObj->m_Path.IsRect()) { *buf << pPoints[0].m_PointX << " " << pPoints[0].m_PointY << " " @@ -166,5 +185,55 @@ void CPDF_PageContentGenerator::ProcessPath(CFX_ByteTextBuf* buf, *buf << (pPathObj->m_bStroke ? " B" : " f"); else if (pPathObj->m_FillType == FXFILL_ALTERNATE) *buf << (pPathObj->m_bStroke ? " B*" : " f*"); - *buf << "\n"; + *buf << " Q\n"; +} + +// This method supports color operators rg and RGB from Table 4.24 of PDF spec +// 1.7. A color will not be set if the colorspace is not DefaultRGB or the RGB +// values cannot be obtained. The method also adds an external graphics +// dictionary, as described in Section 4.3.4. +// "rg" sets the fill color, "RG" sets the stroke color (using DefaultRGB) +// "ca" sets the fill alpha, "CA" sets the stroke alpha. +// "q" saves the graphics state, so that the settings can later be reversed +void CPDF_PageContentGenerator::ProcessGraphics(CFX_ByteTextBuf* buf, + CPDF_PageObject* pPageObj) { + *buf << "q "; + FX_FLOAT fillColor[3]; + if (GetColor(pPageObj->m_ColorState.GetFillColor(), fillColor)) { + *buf << fillColor[0] << " " << fillColor[1] << " " << fillColor[2] + << " rg "; + } + FX_FLOAT strokeColor[3]; + if (GetColor(pPageObj->m_ColorState.GetStrokeColor(), strokeColor)) { + *buf << strokeColor[0] << " " << strokeColor[1] << " " << strokeColor[2] + << " RG "; + } + + GraphicsData graphD; + graphD.fillAlpha = pPageObj->m_GeneralState.GetFillAlpha(); + graphD.strokeAlpha = pPageObj->m_GeneralState.GetStrokeAlpha(); + if (graphD.fillAlpha == 1.0f && graphD.strokeAlpha == 1.0f) + return; + + CFX_ByteString name; + auto it = m_GraphicsMap.find(graphD); + if (it != m_GraphicsMap.end()) { + name = it->second; + } else { + auto gsDict = pdfium::MakeUnique(); + gsDict->SetNewFor("ca", graphD.fillAlpha); + gsDict->SetNewFor("CA", graphD.strokeAlpha); + CPDF_Object* pDict = m_pDocument->AddIndirectObject(std::move(gsDict)); + uint32_t dwObjNum = pDict->GetObjNum(); + name = RealizeResource(dwObjNum, "ExtGState"); + m_GraphicsMap[graphD] = name; + } + *buf << "/" << PDF_NameEncode(name) << " gs "; +} + +bool CPDF_PageContentGenerator::GraphicsData::operator<( + const GraphicsData& other) const { + if (fillAlpha != other.fillAlpha) + return fillAlpha < other.fillAlpha; + return strokeAlpha < other.strokeAlpha; } -- cgit v1.2.3