xref: /aosp_15_r20/external/pdfium/fpdfsdk/fpdf_editpage_embeddertest.cpp (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
1 // Copyright 2018 The PDFium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "core/fxcrt/fx_system.h"
6 #include "core/fxge/cfx_defaultrenderdevice.h"
7 #include "public/fpdf_edit.h"
8 #include "testing/embedder_test.h"
9 #include "testing/embedder_test_constants.h"
10 
11 class FPDFEditPageEmbedderTest : public EmbedderTest {};
12 
TEST_F(FPDFEditPageEmbedderTest,Rotation)13 TEST_F(FPDFEditPageEmbedderTest, Rotation) {
14   const char* rotated_checksum = []() {
15     if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
16       return "eded83f75f3d0332c584c416c571c0df";
17     return "d599429574ff0dcad3bc898ea8b874ca";
18   }();
19 
20   {
21     ASSERT_TRUE(OpenDocument("rectangles.pdf"));
22     FPDF_PAGE page = LoadPage(0);
23     ASSERT_TRUE(page);
24 
25     {
26       // Render the page as is.
27       EXPECT_EQ(0, FPDFPage_GetRotation(page));
28       const int page_width = static_cast<int>(FPDF_GetPageWidth(page));
29       const int page_height = static_cast<int>(FPDF_GetPageHeight(page));
30       EXPECT_EQ(200, page_width);
31       EXPECT_EQ(300, page_height);
32       ScopedFPDFBitmap bitmap = RenderLoadedPage(page);
33       CompareBitmap(bitmap.get(), page_width, page_height,
34                     pdfium::RectanglesChecksum());
35     }
36 
37     FPDFPage_SetRotation(page, 1);
38 
39     {
40       // Render the page after rotation.
41       // Note that the change affects the rendering, as expected.
42       // It behaves just like the case below, rather than the case above.
43       EXPECT_EQ(1, FPDFPage_GetRotation(page));
44       const int page_width = static_cast<int>(FPDF_GetPageWidth(page));
45       const int page_height = static_cast<int>(FPDF_GetPageHeight(page));
46       EXPECT_EQ(300, page_width);
47       EXPECT_EQ(200, page_height);
48       ScopedFPDFBitmap bitmap = RenderLoadedPage(page);
49       CompareBitmap(bitmap.get(), page_width, page_height, rotated_checksum);
50     }
51 
52     UnloadPage(page);
53   }
54 
55   {
56     // Save a copy, open the copy, and render it.
57     // Note that it renders the rotation.
58     EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
59     ASSERT_TRUE(OpenSavedDocument());
60     FPDF_PAGE saved_page = LoadSavedPage(0);
61     ASSERT_TRUE(saved_page);
62 
63     EXPECT_EQ(1, FPDFPage_GetRotation(saved_page));
64     const int page_width = static_cast<int>(FPDF_GetPageWidth(saved_page));
65     const int page_height = static_cast<int>(FPDF_GetPageHeight(saved_page));
66     EXPECT_EQ(300, page_width);
67     EXPECT_EQ(200, page_height);
68     ScopedFPDFBitmap bitmap = RenderSavedPage(saved_page);
69     CompareBitmap(bitmap.get(), page_width, page_height, rotated_checksum);
70 
71     CloseSavedPage(saved_page);
72     CloseSavedDocument();
73   }
74 }
75 
TEST_F(FPDFEditPageEmbedderTest,HasTransparencyImage)76 TEST_F(FPDFEditPageEmbedderTest, HasTransparencyImage) {
77   constexpr int kExpectedObjectCount = 39;
78   ASSERT_TRUE(OpenDocument("embedded_images.pdf"));
79   FPDF_PAGE page = LoadPage(0);
80   ASSERT_TRUE(page);
81   ASSERT_EQ(kExpectedObjectCount, FPDFPage_CountObjects(page));
82 
83   for (int i = 0; i < kExpectedObjectCount; ++i) {
84     FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, i);
85     EXPECT_FALSE(FPDFPageObj_HasTransparency(obj));
86 
87     FPDFPageObj_SetFillColor(obj, 255, 0, 0, 127);
88     EXPECT_TRUE(FPDFPageObj_HasTransparency(obj));
89   }
90 
91   UnloadPage(page);
92 }
93 
TEST_F(FPDFEditPageEmbedderTest,HasTransparencyInvalid)94 TEST_F(FPDFEditPageEmbedderTest, HasTransparencyInvalid) {
95   EXPECT_FALSE(FPDFPageObj_HasTransparency(nullptr));
96 }
97 
TEST_F(FPDFEditPageEmbedderTest,HasTransparencyPath)98 TEST_F(FPDFEditPageEmbedderTest, HasTransparencyPath) {
99   constexpr int kExpectedObjectCount = 8;
100   ASSERT_TRUE(OpenDocument("rectangles.pdf"));
101   FPDF_PAGE page = LoadPage(0);
102   ASSERT_TRUE(page);
103   ASSERT_EQ(kExpectedObjectCount, FPDFPage_CountObjects(page));
104 
105   for (int i = 0; i < kExpectedObjectCount; ++i) {
106     FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, i);
107     EXPECT_FALSE(FPDFPageObj_HasTransparency(obj));
108 
109     FPDFPageObj_SetStrokeColor(obj, 63, 63, 0, 127);
110     EXPECT_TRUE(FPDFPageObj_HasTransparency(obj));
111   }
112 
113   UnloadPage(page);
114 }
115 
TEST_F(FPDFEditPageEmbedderTest,HasTransparencyText)116 TEST_F(FPDFEditPageEmbedderTest, HasTransparencyText) {
117   constexpr int kExpectedObjectCount = 2;
118   ASSERT_TRUE(OpenDocument("text_render_mode.pdf"));
119   FPDF_PAGE page = LoadPage(0);
120   ASSERT_TRUE(page);
121   ASSERT_EQ(kExpectedObjectCount, FPDFPage_CountObjects(page));
122 
123   for (int i = 0; i < kExpectedObjectCount; ++i) {
124     FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, i);
125     EXPECT_FALSE(FPDFPageObj_HasTransparency(obj));
126 
127     FPDFPageObj_SetBlendMode(obj, "Lighten");
128     EXPECT_TRUE(FPDFPageObj_HasTransparency(obj));
129   }
130 
131   UnloadPage(page);
132 }
133 
TEST_F(FPDFEditPageEmbedderTest,GetFillAndStrokeForImage)134 TEST_F(FPDFEditPageEmbedderTest, GetFillAndStrokeForImage) {
135   constexpr int kExpectedObjectCount = 39;
136   constexpr int kImageObjectsStartIndex = 33;
137   ASSERT_TRUE(OpenDocument("embedded_images.pdf"));
138   FPDF_PAGE page = LoadPage(0);
139   ASSERT_TRUE(page);
140 
141   ASSERT_EQ(kExpectedObjectCount, FPDFPage_CountObjects(page));
142 
143   for (int i = kImageObjectsStartIndex; i < kExpectedObjectCount; ++i) {
144     FPDF_PAGEOBJECT image = FPDFPage_GetObject(page, i);
145     ASSERT_TRUE(image);
146     EXPECT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(image));
147 
148     unsigned int r;
149     unsigned int g;
150     unsigned int b;
151     unsigned int a;
152     EXPECT_FALSE(FPDFPageObj_GetFillColor(image, &r, &g, &b, &a));
153     EXPECT_FALSE(FPDFPageObj_GetStrokeColor(image, &r, &g, &b, &a));
154   }
155 
156   UnloadPage(page);
157 }
158 
TEST_F(FPDFEditPageEmbedderTest,DashingArrayAndPhase)159 TEST_F(FPDFEditPageEmbedderTest, DashingArrayAndPhase) {
160   {
161     EXPECT_FALSE(FPDFPageObj_GetDashPhase(nullptr, nullptr));
162 
163     float phase = -1123.5f;
164     EXPECT_FALSE(FPDFPageObj_GetDashPhase(nullptr, &phase));
165     EXPECT_FLOAT_EQ(-1123.5f, phase);
166 
167     EXPECT_EQ(-1, FPDFPageObj_GetDashCount(nullptr));
168 
169     EXPECT_FALSE(FPDFPageObj_GetDashArray(nullptr, nullptr, 3));
170 
171     float get_array[] = {-1.0f, -1.0f, -1.0f};
172     EXPECT_FALSE(FPDFPageObj_GetDashArray(nullptr, get_array, 3));
173     for (int i = 0; i < 3; i++)
174       EXPECT_FLOAT_EQ(-1.0f, get_array[i]);
175 
176     EXPECT_FALSE(FPDFPageObj_SetDashPhase(nullptr, 5.0f));
177     EXPECT_FALSE(FPDFPageObj_SetDashArray(nullptr, nullptr, 3, 5.0f));
178 
179     float set_array[] = {1.0f, 2.0f, 3.0f};
180     EXPECT_FALSE(FPDFPageObj_SetDashArray(nullptr, set_array, 3, 5.0f));
181   }
182 
183   constexpr int kExpectedObjectCount = 3;
184   ASSERT_TRUE(OpenDocument("dashed_lines.pdf"));
185   FPDF_PAGE page = LoadPage(0);
186   ASSERT_TRUE(page);
187 
188   ASSERT_EQ(kExpectedObjectCount, FPDFPage_CountObjects(page));
189 
190   {
191     FPDF_PAGEOBJECT path = FPDFPage_GetObject(page, 0);
192     ASSERT_TRUE(path);
193     EXPECT_EQ(FPDF_PAGEOBJ_PATH, FPDFPageObj_GetType(path));
194 
195     EXPECT_FALSE(FPDFPageObj_GetDashPhase(path, nullptr));
196     EXPECT_FALSE(FPDFPageObj_GetDashArray(path, nullptr, 3));
197     EXPECT_FALSE(FPDFPageObj_SetDashArray(path, nullptr, 3, 5.0f));
198 
199     float phase = -1123.5f;
200     EXPECT_TRUE(FPDFPageObj_GetDashPhase(path, &phase));
201     EXPECT_FLOAT_EQ(0.0f, phase);
202     EXPECT_EQ(0, FPDFPageObj_GetDashCount(path));
203 
204     float get_array[] = {-1.0f, -1.0f, -1.0f};
205     EXPECT_TRUE(FPDFPageObj_GetDashArray(path, get_array, 3));
206     for (int i = 0; i < 3; i++)
207       EXPECT_FLOAT_EQ(-1.0f, get_array[i]);
208   }
209 
210   {
211     FPDF_PAGEOBJECT path = FPDFPage_GetObject(page, 1);
212     ASSERT_TRUE(path);
213     EXPECT_EQ(FPDF_PAGEOBJ_PATH, FPDFPageObj_GetType(path));
214 
215     float phase = -1123.5f;
216     EXPECT_TRUE(FPDFPageObj_GetDashPhase(path, &phase));
217     EXPECT_LT(0.0f, phase);
218     ASSERT_EQ(6, FPDFPageObj_GetDashCount(path));
219 
220     float dash_array[] = {-1.0f, -1.0f, -1.0f, -1.0f, -1.0f, -1.0f};
221     ASSERT_TRUE(FPDFPageObj_GetDashArray(path, dash_array, 6));
222 
223     for (int i = 0; i < 6; i++)
224       EXPECT_LT(0.0f, dash_array[i]);
225 
226     // the array is decreasing in value.
227     for (int i = 0; i < 5; i++)
228       EXPECT_GT(dash_array[i], dash_array[i + 1]);
229 
230     // modify phase
231     EXPECT_TRUE(FPDFPageObj_SetDashPhase(path, 1.0f));
232 
233     phase = -1123.5f;
234     EXPECT_TRUE(FPDFPageObj_GetDashPhase(path, &phase));
235     EXPECT_FLOAT_EQ(1.0f, phase);
236 
237     // clear array
238     EXPECT_TRUE(FPDFPageObj_SetDashArray(path, nullptr, 0, 0.0f));
239     EXPECT_EQ(0, FPDFPageObj_GetDashCount(path));
240 
241     phase = -1123.5f;
242     EXPECT_TRUE(FPDFPageObj_GetDashPhase(path, &phase));
243     EXPECT_FLOAT_EQ(0.0f, phase);
244   }
245 
246   {
247     FPDF_PAGEOBJECT path = FPDFPage_GetObject(page, 2);
248     ASSERT_TRUE(path);
249     EXPECT_EQ(FPDF_PAGEOBJ_PATH, FPDFPageObj_GetType(path));
250 
251     float phase = -1123.5f;
252     EXPECT_TRUE(FPDFPageObj_GetDashPhase(path, &phase));
253     EXPECT_FLOAT_EQ(0.0f, phase);
254 
255     EXPECT_EQ(0, FPDFPageObj_GetDashCount(path));
256 
257     // `get_array` should be unmodified
258     float get_array[] = {-1.0f, -1.0f, -1.0f, -1.0f};
259     EXPECT_TRUE(FPDFPageObj_GetDashArray(path, get_array, 4));
260     for (int i = 0; i < 4; i++)
261       EXPECT_FLOAT_EQ(-1.0f, get_array[i]);
262 
263     // modify dash_array and phase
264     const float set_array[] = {1.0f, 2.0f, 3.0f};
265     EXPECT_TRUE(FPDFPageObj_SetDashArray(path, set_array, 3, 5.0f));
266 
267     phase = -1123.5f;
268     EXPECT_TRUE(FPDFPageObj_GetDashPhase(path, &phase));
269     EXPECT_FLOAT_EQ(5.0f, phase);
270     ASSERT_EQ(3, FPDFPageObj_GetDashCount(path));
271 
272     // Pretend `get_array` has too few members.
273     EXPECT_FALSE(FPDFPageObj_GetDashArray(path, get_array, 2));
274     for (int i = 0; i < 4; i++)
275       EXPECT_FLOAT_EQ(-1.0f, get_array[i]);
276 
277     ASSERT_TRUE(FPDFPageObj_GetDashArray(path, get_array, 4));
278 
279     // `get_array` should be modified only up to dash_count
280     for (int i = 0; i < 3; i++)
281       EXPECT_FLOAT_EQ(static_cast<float>(i + 1), get_array[i]);
282 
283     EXPECT_FLOAT_EQ(-1.0f, get_array[3]);
284 
285     // clear array
286     EXPECT_TRUE(FPDFPageObj_SetDashArray(path, set_array, 0, 4.0f));
287     EXPECT_EQ(0, FPDFPageObj_GetDashCount(path));
288 
289     phase = -1123.5f;
290     EXPECT_TRUE(FPDFPageObj_GetDashPhase(path, &phase));
291     EXPECT_FLOAT_EQ(4.0f, phase);
292   }
293 
294   UnloadPage(page);
295 }
296 
TEST_F(FPDFEditPageEmbedderTest,GetRotatedBoundsBadParameters)297 TEST_F(FPDFEditPageEmbedderTest, GetRotatedBoundsBadParameters) {
298   ASSERT_TRUE(OpenDocument("hello_world.pdf"));
299   FPDF_PAGE page = LoadPage(0);
300   ASSERT_TRUE(page);
301 
302   FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 0);
303   ASSERT_EQ(FPDF_PAGEOBJ_TEXT, FPDFPageObj_GetType(obj));
304 
305   FS_QUADPOINTSF quad;
306   ASSERT_FALSE(FPDFPageObj_GetRotatedBounds(nullptr, nullptr));
307   ASSERT_FALSE(FPDFPageObj_GetRotatedBounds(obj, nullptr));
308   ASSERT_FALSE(FPDFPageObj_GetRotatedBounds(nullptr, &quad));
309 
310   UnloadPage(page);
311 }
312 
TEST_F(FPDFEditPageEmbedderTest,GetBoundsForNormalText)313 TEST_F(FPDFEditPageEmbedderTest, GetBoundsForNormalText) {
314   ASSERT_TRUE(OpenDocument("hello_world.pdf"));
315   FPDF_PAGE page = LoadPage(0);
316   ASSERT_TRUE(page);
317 
318   FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 0);
319   ASSERT_EQ(FPDF_PAGEOBJ_TEXT, FPDFPageObj_GetType(obj));
320 
321   constexpr float kExpectedLeft = 20.348f;
322   constexpr float kExpectedBottom = 48.164f;
323   constexpr float kExpectedRight = 83.36f;
324   constexpr float kExpectedTop = 58.328f;
325 
326   float left;
327   float bottom;
328   float right;
329   float top;
330   ASSERT_TRUE(FPDFPageObj_GetBounds(obj, &left, &bottom, &right, &top));
331   EXPECT_FLOAT_EQ(kExpectedLeft, left);
332   EXPECT_FLOAT_EQ(kExpectedBottom, bottom);
333   EXPECT_FLOAT_EQ(kExpectedRight, right);
334   EXPECT_FLOAT_EQ(kExpectedTop, top);
335 
336   FS_QUADPOINTSF quad;
337   ASSERT_TRUE(FPDFPageObj_GetRotatedBounds(obj, &quad));
338   EXPECT_FLOAT_EQ(kExpectedLeft, quad.x1);
339   EXPECT_FLOAT_EQ(kExpectedBottom, quad.y1);
340   EXPECT_FLOAT_EQ(kExpectedRight, quad.x2);
341   EXPECT_FLOAT_EQ(kExpectedBottom, quad.y2);
342   EXPECT_FLOAT_EQ(kExpectedRight, quad.x3);
343   EXPECT_FLOAT_EQ(kExpectedTop, quad.y3);
344   EXPECT_FLOAT_EQ(kExpectedLeft, quad.x4);
345   EXPECT_FLOAT_EQ(kExpectedTop, quad.y4);
346 
347   UnloadPage(page);
348 }
349 
TEST_F(FPDFEditPageEmbedderTest,GetBoundsForRotatedText)350 TEST_F(FPDFEditPageEmbedderTest, GetBoundsForRotatedText) {
351   ASSERT_TRUE(OpenDocument("rotated_text.pdf"));
352   FPDF_PAGE page = LoadPage(0);
353   ASSERT_TRUE(page);
354 
355   FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 0);
356   ASSERT_EQ(FPDF_PAGEOBJ_TEXT, FPDFPageObj_GetType(obj));
357 
358   constexpr float kExpectedLeft = 98.9478f;
359   constexpr float kExpectedBottom = 78.2607f;
360   constexpr float kExpectedRight = 126.32983f;
361   constexpr float kExpectedTop = 105.64272f;
362 
363   float left;
364   float bottom;
365   float right;
366   float top;
367   ASSERT_TRUE(FPDFPageObj_GetBounds(obj, &left, &bottom, &right, &top));
368   EXPECT_FLOAT_EQ(kExpectedLeft, left);
369   EXPECT_FLOAT_EQ(kExpectedBottom, bottom);
370   EXPECT_FLOAT_EQ(kExpectedRight, right);
371   EXPECT_FLOAT_EQ(kExpectedTop, top);
372 
373   FS_QUADPOINTSF quad;
374   ASSERT_TRUE(FPDFPageObj_GetRotatedBounds(obj, &quad));
375   EXPECT_FLOAT_EQ(kExpectedLeft, quad.x1);
376   EXPECT_FLOAT_EQ(98.4557f, quad.y1);
377   EXPECT_FLOAT_EQ(119.14279f, quad.x2);
378   EXPECT_FLOAT_EQ(kExpectedBottom, quad.y2);
379   EXPECT_FLOAT_EQ(kExpectedRight, quad.x3);
380   EXPECT_FLOAT_EQ(85.447739f, quad.y3);
381   EXPECT_FLOAT_EQ(106.13486f, quad.x4);
382   EXPECT_FLOAT_EQ(kExpectedTop, quad.y4);
383 
384   UnloadPage(page);
385 }
386 
TEST_F(FPDFEditPageEmbedderTest,GetBoundsForNormalImage)387 TEST_F(FPDFEditPageEmbedderTest, GetBoundsForNormalImage) {
388   ASSERT_TRUE(OpenDocument("matte.pdf"));
389   FPDF_PAGE page = LoadPage(0);
390   ASSERT_TRUE(page);
391 
392   FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 2);
393   ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
394 
395   constexpr float kExpectedLeft = 0.0f;
396   constexpr float kExpectedBottom = 90.0f;
397   constexpr float kExpectedRight = 40.0f;
398   constexpr float kExpectedTop = 150.0f;
399 
400   float left;
401   float bottom;
402   float right;
403   float top;
404   ASSERT_TRUE(FPDFPageObj_GetBounds(obj, &left, &bottom, &right, &top));
405   EXPECT_FLOAT_EQ(kExpectedLeft, left);
406   EXPECT_FLOAT_EQ(kExpectedBottom, bottom);
407   EXPECT_FLOAT_EQ(kExpectedRight, right);
408   EXPECT_FLOAT_EQ(kExpectedTop, top);
409 
410   FS_QUADPOINTSF quad;
411   ASSERT_TRUE(FPDFPageObj_GetRotatedBounds(obj, &quad));
412   EXPECT_FLOAT_EQ(kExpectedLeft, quad.x1);
413   EXPECT_FLOAT_EQ(kExpectedBottom, quad.y1);
414   EXPECT_FLOAT_EQ(kExpectedRight, quad.x2);
415   EXPECT_FLOAT_EQ(kExpectedBottom, quad.y2);
416   EXPECT_FLOAT_EQ(kExpectedRight, quad.x3);
417   EXPECT_FLOAT_EQ(kExpectedTop, quad.y3);
418   EXPECT_FLOAT_EQ(kExpectedLeft, quad.x4);
419   EXPECT_FLOAT_EQ(kExpectedTop, quad.y4);
420 
421   UnloadPage(page);
422 }
423 
TEST_F(FPDFEditPageEmbedderTest,GetBoundsForRotatedImage)424 TEST_F(FPDFEditPageEmbedderTest, GetBoundsForRotatedImage) {
425   ASSERT_TRUE(OpenDocument("rotated_image.pdf"));
426   FPDF_PAGE page = LoadPage(0);
427   ASSERT_TRUE(page);
428 
429   FPDF_PAGEOBJECT obj = FPDFPage_GetObject(page, 0);
430   ASSERT_EQ(FPDF_PAGEOBJ_IMAGE, FPDFPageObj_GetType(obj));
431 
432   constexpr float kExpectedLeft = 100.0f;
433   constexpr float kExpectedBottom = 70.0f;
434   constexpr float kExpectedRight = 170.0f;
435   constexpr float kExpectedTop = 140.0f;
436 
437   float left;
438   float bottom;
439   float right;
440   float top;
441   ASSERT_TRUE(FPDFPageObj_GetBounds(obj, &left, &bottom, &right, &top));
442   EXPECT_FLOAT_EQ(kExpectedLeft, left);
443   EXPECT_FLOAT_EQ(kExpectedBottom, bottom);
444   EXPECT_FLOAT_EQ(kExpectedRight, right);
445   EXPECT_FLOAT_EQ(kExpectedTop, top);
446 
447   FS_QUADPOINTSF quad;
448   ASSERT_TRUE(FPDFPageObj_GetRotatedBounds(obj, &quad));
449   EXPECT_FLOAT_EQ(kExpectedLeft, quad.x1);
450   EXPECT_FLOAT_EQ(100.0f, quad.y1);
451   EXPECT_FLOAT_EQ(130.0f, quad.x2);
452   EXPECT_FLOAT_EQ(kExpectedBottom, quad.y2);
453   EXPECT_FLOAT_EQ(kExpectedRight, quad.x3);
454   EXPECT_FLOAT_EQ(110.0f, quad.y3);
455   EXPECT_FLOAT_EQ(140.0f, quad.x4);
456   EXPECT_FLOAT_EQ(kExpectedTop, quad.y4);
457 
458   UnloadPage(page);
459 }
460 
TEST_F(FPDFEditPageEmbedderTest,VerifyDashArraySaved)461 TEST_F(FPDFEditPageEmbedderTest, VerifyDashArraySaved) {
462   constexpr float kDashArray[] = {2.5, 3.6};
463   constexpr float kDashPhase = 1.2;
464 
465   CreateEmptyDocument();
466   {
467     ScopedFPDFPage page(FPDFPage_New(document(), 0, 612, 792));
468 
469     FPDF_PAGEOBJECT path = FPDFPageObj_CreateNewPath(400, 100);
470     EXPECT_TRUE(FPDFPageObj_SetStrokeWidth(path, 2));
471     EXPECT_TRUE(FPDFPageObj_SetStrokeColor(path, 255, 0, 0, 255));
472     EXPECT_TRUE(FPDFPath_SetDrawMode(path, FPDF_FILLMODE_NONE, 1));
473     EXPECT_TRUE(FPDFPath_LineTo(path, 200, 200));
474     EXPECT_TRUE(FPDFPageObj_SetDashArray(path, kDashArray,
475                                          std::size(kDashArray), kDashPhase));
476     FPDFPage_InsertObject(page.get(), path);
477 
478     EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
479     path = FPDFPage_GetObject(page.get(), 0);
480     ASSERT_TRUE(path);
481     ASSERT_EQ(2, FPDFPageObj_GetDashCount(path));
482 
483     EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
484   }
485 
486   ASSERT_TRUE(OpenSavedDocument());
487   FPDF_PAGE page = LoadSavedPage(0);
488   ASSERT_TRUE(page);
489 
490   FPDF_PAGEOBJECT path = FPDFPage_GetObject(page, 0);
491   ASSERT_TRUE(path);
492 
493   float dash_array[] = {0, 0};
494   ASSERT_EQ(static_cast<int>(std::size(dash_array)),
495             FPDFPageObj_GetDashCount(path));
496   ASSERT_TRUE(
497       FPDFPageObj_GetDashArray(path, dash_array, std::size(dash_array)));
498   ASSERT_EQ(kDashArray[0], dash_array[0]);
499   ASSERT_EQ(kDashArray[1], dash_array[1]);
500   float dash_phase = 0;
501   ASSERT_TRUE(FPDFPageObj_GetDashPhase(path, &dash_phase));
502   ASSERT_EQ(kDashPhase, dash_phase);
503 
504   CloseSavedPage(page);
505   CloseSavedDocument();
506 }
507