Save dash array and phase of GraphState in CPDF_PageContentGenerator

Previously the dash array was not saved and thus it was not possible
to generate and save a PDF with dashed lines.

Bug: pdfium:2036
Change-Id: I587f72cd6c7d39864a46b829e0bc2ce77f748810
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/107170
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/AUTHORS b/AUTHORS
index f8e3ed9..0623324 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -17,6 +17,7 @@
 Chery Cherian <cherycherian@gmail.com>
 Claudio DeSouza <claudiomdsjr@gmail.com>
 Dan Ilan <danilan@gmail.com>
+Dorian Rudolph <dorianrudo97@gmail.com>
 Felix Kauselmann <licorn@gmail.com>
 GiWan Go <gogil@stealien.com>
 Huy Ngo <huyna89@gmail.com>
diff --git a/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp b/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
index 8717028..c79de4c 100644
--- a/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
+++ b/core/fpdfapi/edit/cpdf_pagecontentgenerator.cpp
@@ -548,6 +548,18 @@
   CFX_GraphStateData::LineJoin lineJoin = pPageObj->m_GraphState.GetLineJoin();
   if (lineJoin != CFX_GraphStateData::LineJoin::kMiter)
     *buf << static_cast<int>(lineJoin) << " j ";
+  std::vector<float> dash_array = pPageObj->m_GraphState.GetLineDashArray();
+  if (dash_array.size()) {
+    *buf << "[";
+    for (size_t i = 0; i < dash_array.size(); ++i) {
+      if (i > 0) {
+        *buf << " ";
+      }
+      WriteFloat(*buf, dash_array[i]);
+    }
+    *buf << "] ";
+    WriteFloat(*buf, pPageObj->m_GraphState.GetLineDashPhase()) << " d ";
+  }
 
   const CPDF_ClipPath& clip_path = pPageObj->m_ClipPath;
   if (clip_path.HasRef()) {
diff --git a/fpdfsdk/fpdf_editpage_embeddertest.cpp b/fpdfsdk/fpdf_editpage_embeddertest.cpp
index c74d6dc..e6eba89 100644
--- a/fpdfsdk/fpdf_editpage_embeddertest.cpp
+++ b/fpdfsdk/fpdf_editpage_embeddertest.cpp
@@ -457,3 +457,50 @@
 
   UnloadPage(page);
 }
+
+TEST_F(FPDFEditPageEmbedderTest, VerifyDashArraySaved) {
+  constexpr float kDashArray[] = {2.5, 3.6};
+  constexpr float kDashPhase = 1.2;
+
+  CreateEmptyDocument();
+  {
+    ScopedFPDFPage page(FPDFPage_New(document(), 0, 612, 792));
+
+    FPDF_PAGEOBJECT path = FPDFPageObj_CreateNewPath(400, 100);
+    EXPECT_TRUE(FPDFPageObj_SetStrokeWidth(path, 2));
+    EXPECT_TRUE(FPDFPageObj_SetStrokeColor(path, 255, 0, 0, 255));
+    EXPECT_TRUE(FPDFPath_SetDrawMode(path, FPDF_FILLMODE_NONE, 1));
+    EXPECT_TRUE(FPDFPath_LineTo(path, 200, 200));
+    EXPECT_TRUE(FPDFPageObj_SetDashArray(path, kDashArray,
+                                         std::size(kDashArray), kDashPhase));
+    FPDFPage_InsertObject(page.get(), path);
+
+    EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
+    path = FPDFPage_GetObject(page.get(), 0);
+    ASSERT_TRUE(path);
+    ASSERT_EQ(2, FPDFPageObj_GetDashCount(path));
+
+    EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
+  }
+
+  ASSERT_TRUE(OpenSavedDocument());
+  FPDF_PAGE page = LoadSavedPage(0);
+  ASSERT_TRUE(page);
+
+  FPDF_PAGEOBJECT path = FPDFPage_GetObject(page, 0);
+  ASSERT_TRUE(path);
+
+  float dash_array[] = {0, 0};
+  ASSERT_EQ(static_cast<int>(std::size(dash_array)),
+            FPDFPageObj_GetDashCount(path));
+  ASSERT_TRUE(
+      FPDFPageObj_GetDashArray(path, dash_array, std::size(dash_array)));
+  ASSERT_EQ(kDashArray[0], dash_array[0]);
+  ASSERT_EQ(kDashArray[1], dash_array[1]);
+  float dash_phase = 0;
+  ASSERT_TRUE(FPDFPageObj_GetDashPhase(path, &dash_phase));
+  ASSERT_EQ(kDashPhase, dash_phase);
+
+  CloseSavedPage(page);
+  CloseSavedDocument();
+}