summaryrefslogtreecommitdiff
path: root/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp')
-rw-r--r--core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp71
1 files changed, 70 insertions, 1 deletions
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 <tuple>
+#include <utility>
+
#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<CPDF_Dictionary>();
+ gsDict->SetNewFor<CPDF_Number>("ca", graphD.fillAlpha);
+ gsDict->SetNewFor<CPDF_Number>("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;
}