From 4bd0d99c11102514fb43328b67b7674165888619 Mon Sep 17 00:00:00 2001 From: Nicolas Pena Date: Thu, 2 Feb 2017 14:32:21 -0500 Subject: Add CPDF_PageContentGenerator::ProcessPath supporting path construction MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit See Table 4.9 for path construction operators. Ignoring v, y, because those can be replaced with the more powerful c operator. The code added will be called by public methods that do not exist yet. BUG=pdfium:661 Change-Id: I9a1ad3fd0a601e4e3a292b55f3e5708fe0c9c8fb Reviewed-on: https://pdfium-review.googlesource.com/2495 Commit-Queue: Nicolás Peña Reviewed-by: dsinclair --- core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp | 63 ++++++++++++++++++++++++- 1 file changed, 61 insertions(+), 2 deletions(-) (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 a65d564141..e2354e1b50 100644 --- a/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp +++ b/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp @@ -10,6 +10,8 @@ #include "core/fpdfapi/page/cpdf_image.h" #include "core/fpdfapi/page/cpdf_imageobject.h" #include "core/fpdfapi/page/cpdf_page.h" +#include "core/fpdfapi/page/cpdf_path.h" +#include "core/fpdfapi/page/cpdf_pathobject.h" #include "core/fpdfapi/parser/cpdf_dictionary.h" #include "core/fpdfapi/parser/cpdf_document.h" #include "core/fpdfapi/parser/cpdf_name.h" @@ -40,9 +42,10 @@ CPDF_PageContentGenerator::~CPDF_PageContentGenerator() {} void CPDF_PageContentGenerator::GenerateContent() { CFX_ByteTextBuf buf; for (CPDF_PageObject* pPageObj : m_pageObjects) { - CPDF_ImageObject* pImageObject = pPageObj->AsImage(); - if (pImageObject) + if (CPDF_ImageObject* pImageObject = pPageObj->AsImage()) ProcessImage(&buf, pImageObject); + else if (CPDF_PathObject* pPathObj = pPageObj->AsPath()) + ProcessPath(&buf, pPathObj); } CPDF_Dictionary* pPageDict = m_pPage->m_pFormDict; CPDF_Object* pContent = @@ -109,3 +112,59 @@ void CPDF_PageContentGenerator::ProcessImage(CFX_ByteTextBuf* buf, *buf << "/" << PDF_NameEncode(name) << " Do Q\n"; } + +// Processing path with operators from Tables 4.9 and 4.10 of PDF spec 1.7: +// "re" appends a rectangle (here, used only if the whole path is a rectangle) +// "m" moves current point to the given coordinates +// "l" creates a line from current point to the new point +// "c" adds a Bezier curve from current to last point, using the two other +// points as the Bezier control points +// Note: "l", "c" change the current point +// "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. +void CPDF_PageContentGenerator::ProcessPath(CFX_ByteTextBuf* buf, + CPDF_PathObject* pPathObj) { + const FX_PATHPOINT* pPoints = pPathObj->m_Path.GetPoints(); + if (pPathObj->m_Path.IsRect()) { + *buf << pPoints[0].m_PointX << " " << pPoints[0].m_PointY << " " + << (pPoints[2].m_PointX - pPoints[0].m_PointX) << " " + << (pPoints[2].m_PointY - pPoints[0].m_PointY) << " re"; + } else { + int numPoints = pPathObj->m_Path.GetPointCount(); + for (int i = 0; i < numPoints; i++) { + if (i > 0) + *buf << " "; + *buf << pPoints[i].m_PointX << " " << pPoints[i].m_PointY; + int pointFlag = pPoints[i].m_Flag; + if (pointFlag == FXPT_MOVETO) { + *buf << " m"; + } else if (pointFlag & FXPT_LINETO) { + *buf << " l"; + } else if (pointFlag & FXPT_BEZIERTO) { + if (i + 2 >= numPoints || pPoints[i].m_Flag != FXPT_BEZIERTO || + pPoints[i + 1].m_Flag != FXPT_BEZIERTO || + (pPoints[i + 2].m_Flag & FXPT_BEZIERTO) == 0) { + // If format is not supported, close the path and paint + *buf << " h"; + break; + } + *buf << " " << pPoints[i + 1].m_PointX << " " << pPoints[i + 1].m_PointY + << " " << pPoints[i + 2].m_PointX << " " << pPoints[i + 2].m_PointY + << " c"; + if (pPoints[i + 2].m_Flag & FXPT_CLOSEFIGURE) + *buf << " h"; + i += 2; + } + if (pointFlag & FXPT_CLOSEFIGURE) + *buf << " h"; + } + } + if (pPathObj->m_FillType == 0) + *buf << (pPathObj->m_bStroke ? " S" : " n"); + else if (pPathObj->m_FillType == FXFILL_WINDING) + *buf << (pPathObj->m_bStroke ? " B" : " f"); + else if (pPathObj->m_FillType == FXFILL_ALTERNATE) + *buf << (pPathObj->m_bStroke ? " B*" : " f*"); + *buf << "\n"; +} -- cgit v1.2.3