Split path construction and painting in content generation

Path construction will be used to create clipping paths when processing
the graphics of a page object. Split the path construction into a
separate function to reuse the code.

Bug: pdfium:1558
Change-Id: I91f42e61712786c3b559a509bcd4d89547d2e377
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/71730
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Daniel Hosseinian <dhoss@chromium.org>
diff --git a/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp b/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
index 580b36e..573b40c 100644
--- a/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
+++ b/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
@@ -331,7 +331,7 @@
   *buf << "/" << PDF_NameEncode(name) << " Do Q\n";
 }
 
-// Processing path with operators from Tables 4.9 and 4.10 of PDF spec 1.7:
+// Processing path construction with operators from Table 4.9 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
@@ -339,6 +339,45 @@
 // 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)
+void CPDF_PageContentGenerator::ProcessPathPoints(std::ostringstream* buf,
+                                                  CPDF_Path* pPath) {
+  pdfium::span<const FX_PATHPOINT> points = pPath->GetPoints();
+  if (pPath->IsRect()) {
+    CFX_PointF diff = points[2].m_Point - points[0].m_Point;
+    *buf << points[0].m_Point << " " << diff << " re";
+    return;
+  }
+  for (size_t i = 0; i < points.size(); ++i) {
+    if (i > 0)
+      *buf << " ";
+
+    *buf << points[i].m_Point;
+
+    FXPT_TYPE point_type = points[i].m_Type;
+    if (point_type == FXPT_TYPE::MoveTo) {
+      *buf << " m";
+    } else if (point_type == FXPT_TYPE::LineTo) {
+      *buf << " l";
+    } else if (point_type == FXPT_TYPE::BezierTo) {
+      if (i + 2 >= points.size() ||
+          !points[i].IsTypeAndOpen(FXPT_TYPE::BezierTo) ||
+          !points[i + 1].IsTypeAndOpen(FXPT_TYPE::BezierTo) ||
+          points[i + 2].m_Type != FXPT_TYPE::BezierTo) {
+        // If format is not supported, close the path and paint
+        *buf << " h";
+        break;
+      }
+      *buf << " ";
+      *buf << points[i + 1].m_Point << " ";
+      *buf << points[i + 2].m_Point << " c";
+      i += 2;
+    }
+    if (points[i].m_CloseFigure)
+      *buf << " h";
+  }
+}
+
+// Processing path painting with operators from Table 4.10 of PDF spec 1.7:
 // 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.
@@ -347,41 +386,8 @@
   ProcessGraphics(buf, pPathObj);
 
   *buf << pPathObj->matrix() << " cm ";
+  ProcessPathPoints(buf, &pPathObj->path());
 
-  pdfium::span<const FX_PATHPOINT> points = pPathObj->path().GetPoints();
-  if (pPathObj->path().IsRect()) {
-    CFX_PointF diff = points[2].m_Point - points[0].m_Point;
-    *buf << points[0].m_Point << " " << diff << " re";
-  } else {
-    for (size_t i = 0; i < points.size(); ++i) {
-      if (i > 0)
-        *buf << " ";
-
-      *buf << points[i].m_Point;
-
-      FXPT_TYPE point_type = points[i].m_Type;
-      if (point_type == FXPT_TYPE::MoveTo) {
-        *buf << " m";
-      } else if (point_type == FXPT_TYPE::LineTo) {
-        *buf << " l";
-      } else if (point_type == FXPT_TYPE::BezierTo) {
-        if (i + 2 >= points.size() ||
-            !points[i].IsTypeAndOpen(FXPT_TYPE::BezierTo) ||
-            !points[i + 1].IsTypeAndOpen(FXPT_TYPE::BezierTo) ||
-            points[i + 2].m_Type != FXPT_TYPE::BezierTo) {
-          // If format is not supported, close the path and paint
-          *buf << " h";
-          break;
-        }
-        *buf << " ";
-        *buf << points[i + 1].m_Point << " ";
-        *buf << points[i + 2].m_Point << " c";
-        i += 2;
-      }
-      if (points[i].m_CloseFigure)
-        *buf << " h";
-    }
-  }
   if (pPathObj->has_no_filltype())
     *buf << (pPathObj->stroke() ? " S" : " n");
   else if (pPathObj->has_winding_filltype())
diff --git a/core/fpdfapi/edit/cpdf_pagecontentgenerator.h b/core/fpdfapi/edit/cpdf_pagecontentgenerator.h
index 40d19ae..f1126f2 100644
--- a/core/fpdfapi/edit/cpdf_pagecontentgenerator.h
+++ b/core/fpdfapi/edit/cpdf_pagecontentgenerator.h
@@ -22,6 +22,7 @@
 class CPDF_Object;
 class CPDF_PageObject;
 class CPDF_PageObjectHolder;
+class CPDF_Path;
 class CPDF_PathObject;
 class CPDF_TextObject;
 
@@ -37,6 +38,7 @@
   friend class CPDF_PageContentGeneratorTest;
 
   void ProcessPageObject(std::ostringstream* buf, CPDF_PageObject* pPageObj);
+  void ProcessPathPoints(std::ostringstream* buf, CPDF_Path* pPath);
   void ProcessPath(std::ostringstream* buf, CPDF_PathObject* pPathObj);
   void ProcessImage(std::ostringstream* buf, CPDF_ImageObject* pImageObj);
   void ProcessGraphics(std::ostringstream* buf, CPDF_PageObject* pPageObj);