xref: /aosp_15_r20/external/pdfium/fpdfsdk/fpdf_transformpage_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 "public/fpdf_transformpage.h"
6 
7 #include "build/build_config.h"
8 #include "core/fxge/cfx_defaultrenderdevice.h"
9 #include "testing/embedder_test.h"
10 #include "testing/embedder_test_constants.h"
11 
12 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_FUCHSIA)
13 #include "third_party/base/test/scoped_locale.h"
14 #endif
15 
16 using pdfium::RectanglesChecksum;
17 
18 namespace {
19 
ShrunkChecksum()20 const char* ShrunkChecksum() {
21   if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
22     return "78c52d6029283090036e6db6683401e2";
23   return "f4136cc9209207ab60eb8381a3df2e69";
24 }
25 
26 }  // namespace
27 
28 class FPDFTransformEmbedderTest : public EmbedderTest {};
29 
TEST_F(FPDFTransformEmbedderTest,GetBoundingBoxes)30 TEST_F(FPDFTransformEmbedderTest, GetBoundingBoxes) {
31   ASSERT_TRUE(OpenDocument("cropped_text.pdf"));
32   ASSERT_EQ(4, FPDF_GetPageCount(document()));
33 
34   {
35     FPDF_PAGE page = LoadPage(1);
36     ASSERT_TRUE(page);
37 
38     FS_RECTF mediabox;
39     EXPECT_TRUE(FPDFPage_GetMediaBox(page, &mediabox.left, &mediabox.bottom,
40                                      &mediabox.right, &mediabox.top));
41     EXPECT_EQ(-50, mediabox.left);
42     EXPECT_EQ(-50, mediabox.bottom);
43     EXPECT_EQ(200, mediabox.right);
44     EXPECT_EQ(200, mediabox.top);
45 
46     FS_RECTF cropbox;
47     EXPECT_TRUE(FPDFPage_GetCropBox(page, &cropbox.left, &cropbox.bottom,
48                                     &cropbox.right, &cropbox.top));
49     EXPECT_EQ(50, cropbox.left);
50     EXPECT_EQ(50, cropbox.bottom);
51     EXPECT_EQ(150, cropbox.right);
52     EXPECT_EQ(150, cropbox.top);
53 
54     FS_RECTF bleedbox;
55     EXPECT_TRUE(FPDFPage_GetBleedBox(page, &bleedbox.left, &bleedbox.bottom,
56                                      &bleedbox.right, &bleedbox.top));
57     EXPECT_EQ(0, bleedbox.left);
58     EXPECT_EQ(10, bleedbox.bottom);
59     EXPECT_EQ(150, bleedbox.right);
60     EXPECT_EQ(145, bleedbox.top);
61 
62     FS_RECTF trimbox;
63     EXPECT_TRUE(FPDFPage_GetTrimBox(page, &trimbox.left, &trimbox.bottom,
64                                     &trimbox.right, &trimbox.top));
65     EXPECT_EQ(25, trimbox.left);
66     EXPECT_EQ(30, trimbox.bottom);
67     EXPECT_EQ(140, trimbox.right);
68     EXPECT_EQ(145, trimbox.top);
69 
70     FS_RECTF artbox;
71     EXPECT_TRUE(FPDFPage_GetArtBox(page, &artbox.left, &artbox.bottom,
72                                    &artbox.right, &artbox.top));
73     EXPECT_EQ(50, artbox.left);
74     EXPECT_EQ(60, artbox.bottom);
75     EXPECT_EQ(135, artbox.right);
76     EXPECT_EQ(140, artbox.top);
77 
78     UnloadPage(page);
79   }
80 
81   {
82     FPDF_PAGE page = LoadPage(3);
83     ASSERT_TRUE(page);
84 
85     FS_RECTF mediabox;
86     EXPECT_TRUE(FPDFPage_GetMediaBox(page, &mediabox.left, &mediabox.bottom,
87                                      &mediabox.right, &mediabox.top));
88     EXPECT_EQ(0, mediabox.left);
89     EXPECT_EQ(0, mediabox.bottom);
90     EXPECT_EQ(200, mediabox.right);
91     EXPECT_EQ(200, mediabox.top);
92 
93     FS_RECTF cropbox;
94     EXPECT_TRUE(FPDFPage_GetCropBox(page, &cropbox.left, &cropbox.bottom,
95                                     &cropbox.right, &cropbox.top));
96     EXPECT_EQ(150, cropbox.left);
97     EXPECT_EQ(150, cropbox.bottom);
98     EXPECT_EQ(60, cropbox.right);
99     EXPECT_EQ(60, cropbox.top);
100 
101     EXPECT_FALSE(FPDFPage_GetCropBox(page, nullptr, &cropbox.bottom,
102                                      &cropbox.right, &cropbox.top));
103     EXPECT_FALSE(FPDFPage_GetCropBox(page, &cropbox.left, nullptr,
104                                      &cropbox.right, &cropbox.top));
105     EXPECT_FALSE(FPDFPage_GetCropBox(page, &cropbox.left, &cropbox.bottom,
106                                      nullptr, &cropbox.top));
107     EXPECT_FALSE(FPDFPage_GetCropBox(page, &cropbox.left, &cropbox.bottom,
108                                      &cropbox.right, nullptr));
109     EXPECT_FALSE(FPDFPage_GetCropBox(page, nullptr, nullptr, nullptr, nullptr));
110 
111     FS_RECTF bleedbox;
112     EXPECT_TRUE(FPDFPage_GetBleedBox(page, &bleedbox.left, &bleedbox.bottom,
113                                      &bleedbox.right, &bleedbox.top));
114     EXPECT_EQ(160, bleedbox.left);
115     EXPECT_EQ(165, bleedbox.bottom);
116     EXPECT_EQ(0, bleedbox.right);
117     EXPECT_EQ(10, bleedbox.top);
118 
119     FS_RECTF trimbox;
120     EXPECT_TRUE(FPDFPage_GetTrimBox(page, &trimbox.left, &trimbox.bottom,
121                                     &trimbox.right, &trimbox.top));
122     EXPECT_EQ(155, trimbox.left);
123     EXPECT_EQ(165, trimbox.bottom);
124     EXPECT_EQ(25, trimbox.right);
125     EXPECT_EQ(30, trimbox.top);
126 
127     FS_RECTF artbox;
128     EXPECT_TRUE(FPDFPage_GetArtBox(page, &artbox.left, &artbox.bottom,
129                                    &artbox.right, &artbox.top));
130     EXPECT_EQ(140, artbox.left);
131     EXPECT_EQ(145, artbox.bottom);
132     EXPECT_EQ(65, artbox.right);
133     EXPECT_EQ(70, artbox.top);
134 
135     UnloadPage(page);
136   }
137 }
138 
TEST_F(FPDFTransformEmbedderTest,NoCropBox)139 TEST_F(FPDFTransformEmbedderTest, NoCropBox) {
140   ASSERT_TRUE(OpenDocument("hello_world.pdf"));
141   ASSERT_EQ(1, FPDF_GetPageCount(document()));
142 
143   FPDF_PAGE page = LoadPage(0);
144   ASSERT_TRUE(page);
145 
146   FS_RECTF cropbox = {-1.0f, 0.0f, 3.0f, -2.0f};
147   EXPECT_FALSE(FPDFPage_GetCropBox(page, &cropbox.left, &cropbox.bottom,
148                                    &cropbox.right, &cropbox.top));
149   EXPECT_EQ(-1.0f, cropbox.left);
150   EXPECT_EQ(-2.0f, cropbox.bottom);
151   EXPECT_EQ(3.0f, cropbox.right);
152   EXPECT_EQ(0.0f, cropbox.top);
153 
154   UnloadPage(page);
155 }
156 
TEST_F(FPDFTransformEmbedderTest,NoBleedBox)157 TEST_F(FPDFTransformEmbedderTest, NoBleedBox) {
158   ASSERT_TRUE(OpenDocument("hello_world.pdf"));
159   ASSERT_EQ(1, FPDF_GetPageCount(document()));
160 
161   FPDF_PAGE page = LoadPage(0);
162   ASSERT_TRUE(page);
163 
164   FS_RECTF bleedbox = {-1.0f, 10.f, 3.0f, -1.0f};
165   EXPECT_FALSE(FPDFPage_GetBleedBox(page, &bleedbox.left, &bleedbox.bottom,
166                                     &bleedbox.right, &bleedbox.top));
167   EXPECT_EQ(-1.0f, bleedbox.left);
168   EXPECT_EQ(-1.0f, bleedbox.bottom);
169   EXPECT_EQ(3.0f, bleedbox.right);
170   EXPECT_EQ(10.0f, bleedbox.top);
171 
172   UnloadPage(page);
173 }
174 
TEST_F(FPDFTransformEmbedderTest,NoTrimBox)175 TEST_F(FPDFTransformEmbedderTest, NoTrimBox) {
176   ASSERT_TRUE(OpenDocument("hello_world.pdf"));
177   ASSERT_EQ(1, FPDF_GetPageCount(document()));
178 
179   FPDF_PAGE page = LoadPage(0);
180   ASSERT_TRUE(page);
181 
182   FS_RECTF trimbox = {-11.0f, 0.0f, 3.0f, -10.0f};
183   EXPECT_FALSE(FPDFPage_GetTrimBox(page, &trimbox.left, &trimbox.bottom,
184                                    &trimbox.right, &trimbox.top));
185   EXPECT_EQ(-11.0f, trimbox.left);
186   EXPECT_EQ(-10.0f, trimbox.bottom);
187   EXPECT_EQ(3.0f, trimbox.right);
188   EXPECT_EQ(0.0f, trimbox.top);
189 
190   UnloadPage(page);
191 }
192 
TEST_F(FPDFTransformEmbedderTest,NoArtBox)193 TEST_F(FPDFTransformEmbedderTest, NoArtBox) {
194   ASSERT_TRUE(OpenDocument("hello_world.pdf"));
195   ASSERT_EQ(1, FPDF_GetPageCount(document()));
196 
197   FPDF_PAGE page = LoadPage(0);
198   ASSERT_TRUE(page);
199 
200   FS_RECTF artbox = {-1.0f, 0.0f, 3.0f, -1.0f};
201   EXPECT_FALSE(FPDFPage_GetArtBox(page, &artbox.left, &artbox.bottom,
202                                   &artbox.right, &artbox.top));
203   EXPECT_EQ(-1.0f, artbox.left);
204   EXPECT_EQ(-1.0f, artbox.bottom);
205   EXPECT_EQ(3.0f, artbox.right);
206   EXPECT_EQ(0.0f, artbox.top);
207 
208   UnloadPage(page);
209 }
210 
TEST_F(FPDFTransformEmbedderTest,SetCropBox)211 TEST_F(FPDFTransformEmbedderTest, SetCropBox) {
212   const char* cropped_checksum = []() {
213     if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
214       return "4b9d2d2246be61c583f454245fe3172f";
215     return "9937883715d5144c079fb8f7e3d4f395";
216   }();
217   {
218     ASSERT_TRUE(OpenDocument("rectangles.pdf"));
219     FPDF_PAGE page = LoadPage(0);
220     ASSERT_TRUE(page);
221 
222     {
223       // Render the page as is.
224       FS_RECTF cropbox;
225       EXPECT_FALSE(FPDFPage_GetCropBox(page, &cropbox.left, &cropbox.bottom,
226                                        &cropbox.right, &cropbox.top));
227       const int page_width = static_cast<int>(FPDF_GetPageWidth(page));
228       const int page_height = static_cast<int>(FPDF_GetPageHeight(page));
229       EXPECT_EQ(200, page_width);
230       EXPECT_EQ(300, page_height);
231       ScopedFPDFBitmap bitmap = RenderLoadedPage(page);
232       CompareBitmap(bitmap.get(), page_width, page_height,
233                     RectanglesChecksum());
234     }
235 
236     FPDFPage_SetCropBox(page, 10, 20, 100, 150);
237 
238     {
239       // Render the page after setting the CropBox.
240       // Note that the change affects the rendering, as expected.
241       // It behaves just like the case below, rather than the case above.
242       FS_RECTF cropbox;
243       EXPECT_TRUE(FPDFPage_GetCropBox(page, &cropbox.left, &cropbox.bottom,
244                                       &cropbox.right, &cropbox.top));
245       EXPECT_EQ(10, cropbox.left);
246       EXPECT_EQ(20, cropbox.bottom);
247       EXPECT_EQ(100, cropbox.right);
248       EXPECT_EQ(150, cropbox.top);
249       const int page_width = static_cast<int>(FPDF_GetPageWidth(page));
250       const int page_height = static_cast<int>(FPDF_GetPageHeight(page));
251       EXPECT_EQ(90, page_width);
252       EXPECT_EQ(130, page_height);
253       ScopedFPDFBitmap bitmap = RenderLoadedPage(page);
254       CompareBitmap(bitmap.get(), page_width, page_height, cropped_checksum);
255     }
256 
257     UnloadPage(page);
258   }
259 
260   {
261     // Save a copy, open the copy, and render it.
262     // Note that it renders the rotation.
263     EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
264     ASSERT_TRUE(OpenSavedDocument());
265     FPDF_PAGE saved_page = LoadSavedPage(0);
266     ASSERT_TRUE(saved_page);
267 
268     FS_RECTF cropbox;
269     EXPECT_TRUE(FPDFPage_GetCropBox(saved_page, &cropbox.left, &cropbox.bottom,
270                                     &cropbox.right, &cropbox.top));
271     EXPECT_EQ(10, cropbox.left);
272     EXPECT_EQ(20, cropbox.bottom);
273     EXPECT_EQ(100, cropbox.right);
274     EXPECT_EQ(150, cropbox.top);
275     const int page_width = static_cast<int>(FPDF_GetPageWidth(saved_page));
276     const int page_height = static_cast<int>(FPDF_GetPageHeight(saved_page));
277     EXPECT_EQ(90, page_width);
278     EXPECT_EQ(130, page_height);
279     ScopedFPDFBitmap bitmap = RenderSavedPage(saved_page);
280     CompareBitmap(bitmap.get(), page_width, page_height, cropped_checksum);
281 
282     CloseSavedPage(saved_page);
283     CloseSavedDocument();
284   }
285 }
286 
TEST_F(FPDFTransformEmbedderTest,SetMediaBox)287 TEST_F(FPDFTransformEmbedderTest, SetMediaBox) {
288   const char* shrunk_checksum_set_media_box = []() {
289     if (CFX_DefaultRenderDevice::SkiaIsDefaultRenderer())
290       return "9f28f0610a7f789c24cfd5f9bd5dc3de";
291     return "eab5958f62f7ce65d7c32de98389fee1";
292   }();
293 
294   {
295     ASSERT_TRUE(OpenDocument("rectangles.pdf"));
296     FPDF_PAGE page = LoadPage(0);
297     ASSERT_TRUE(page);
298 
299     {
300       // Render the page as is.
301       FS_RECTF mediabox;
302       EXPECT_FALSE(FPDFPage_GetMediaBox(page, &mediabox.left, &mediabox.bottom,
303                                         &mediabox.right, &mediabox.top));
304       const int page_width = static_cast<int>(FPDF_GetPageWidth(page));
305       const int page_height = static_cast<int>(FPDF_GetPageHeight(page));
306       EXPECT_EQ(200, page_width);
307       EXPECT_EQ(300, page_height);
308       ScopedFPDFBitmap bitmap = RenderLoadedPage(page);
309       CompareBitmap(bitmap.get(), page_width, page_height,
310                     RectanglesChecksum());
311     }
312 
313     FPDFPage_SetMediaBox(page, 20, 30, 100, 150);
314 
315     {
316       // Render the page after setting the MediaBox.
317       // Note that the change affects the rendering, as expected.
318       // It behaves just like the case below, rather than the case above.
319       FS_RECTF mediabox;
320       EXPECT_TRUE(FPDFPage_GetMediaBox(page, &mediabox.left, &mediabox.bottom,
321                                        &mediabox.right, &mediabox.top));
322       EXPECT_EQ(20, mediabox.left);
323       EXPECT_EQ(30, mediabox.bottom);
324       EXPECT_EQ(100, mediabox.right);
325       EXPECT_EQ(150, mediabox.top);
326       const int page_width = static_cast<int>(FPDF_GetPageWidth(page));
327       const int page_height = static_cast<int>(FPDF_GetPageHeight(page));
328       EXPECT_EQ(80, page_width);
329       EXPECT_EQ(120, page_height);
330       ScopedFPDFBitmap bitmap = RenderLoadedPage(page);
331       CompareBitmap(bitmap.get(), page_width, page_height,
332                     shrunk_checksum_set_media_box);
333     }
334 
335     UnloadPage(page);
336   }
337 
338   {
339     // Save a copy, open the copy, and render it.
340     // Note that it renders the rotation.
341     EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
342     ASSERT_TRUE(OpenSavedDocument());
343     FPDF_PAGE saved_page = LoadSavedPage(0);
344     ASSERT_TRUE(saved_page);
345 
346     FS_RECTF mediabox;
347     EXPECT_TRUE(FPDFPage_GetMediaBox(saved_page, &mediabox.left,
348                                      &mediabox.bottom, &mediabox.right,
349                                      &mediabox.top));
350     EXPECT_EQ(20, mediabox.left);
351     EXPECT_EQ(30, mediabox.bottom);
352     EXPECT_EQ(100, mediabox.right);
353     EXPECT_EQ(150, mediabox.top);
354     const int page_width = static_cast<int>(FPDF_GetPageWidth(saved_page));
355     const int page_height = static_cast<int>(FPDF_GetPageHeight(saved_page));
356     EXPECT_EQ(80, page_width);
357     EXPECT_EQ(120, page_height);
358     ScopedFPDFBitmap bitmap = RenderSavedPage(saved_page);
359     CompareBitmap(bitmap.get(), page_width, page_height,
360                   shrunk_checksum_set_media_box);
361 
362     CloseSavedPage(saved_page);
363     CloseSavedDocument();
364   }
365 }
366 
TEST_F(FPDFTransformEmbedderTest,ClipPath)367 TEST_F(FPDFTransformEmbedderTest, ClipPath) {
368   ASSERT_TRUE(OpenDocument("hello_world.pdf"));
369 
370   FPDF_PAGE page = LoadPage(0);
371   ASSERT_TRUE(page);
372 
373   {
374     ScopedFPDFClipPath clip(FPDF_CreateClipPath(10.0f, 10.0f, 90.0f, 90.0f));
375     EXPECT_TRUE(clip);
376 
377     // NULL arg call is a no-op.
378     FPDFPage_InsertClipPath(nullptr, clip.get());
379 
380     // Do actual work.
381     FPDFPage_InsertClipPath(page, clip.get());
382 
383     // TODO(tsepez): test how inserting path affects page rendering.
384   }
385 
386   UnloadPage(page);
387 }
388 
TEST_F(FPDFTransformEmbedderTest,TransFormWithClip)389 TEST_F(FPDFTransformEmbedderTest, TransFormWithClip) {
390   const FS_MATRIX half_matrix{0.5, 0, 0, 0.5, 0, 0};
391   const FS_RECTF clip_rect = {0.0f, 0.0f, 20.0f, 10.0f};
392 
393   ASSERT_TRUE(OpenDocument("hello_world.pdf"));
394 
395   FPDF_PAGE page = LoadPage(0);
396   ASSERT_TRUE(page);
397 
398   EXPECT_FALSE(FPDFPage_TransFormWithClip(nullptr, nullptr, nullptr));
399   EXPECT_FALSE(FPDFPage_TransFormWithClip(nullptr, &half_matrix, nullptr));
400   EXPECT_FALSE(FPDFPage_TransFormWithClip(nullptr, nullptr, &clip_rect));
401   EXPECT_FALSE(FPDFPage_TransFormWithClip(nullptr, &half_matrix, &clip_rect));
402   EXPECT_FALSE(FPDFPage_TransFormWithClip(page, nullptr, nullptr));
403   EXPECT_TRUE(FPDFPage_TransFormWithClip(page, &half_matrix, nullptr));
404   EXPECT_TRUE(FPDFPage_TransFormWithClip(page, nullptr, &clip_rect));
405   EXPECT_TRUE(FPDFPage_TransFormWithClip(page, &half_matrix, &clip_rect));
406 
407   UnloadPage(page);
408 }
409 
TEST_F(FPDFTransformEmbedderTest,TransFormWithClipWithPatterns)410 TEST_F(FPDFTransformEmbedderTest, TransFormWithClipWithPatterns) {
411   const FS_MATRIX half_matrix{0.5, 0, 0, 0.5, 0, 0};
412   const FS_RECTF clip_rect = {0.0f, 0.0f, 20.0f, 10.0f};
413 
414   ASSERT_TRUE(OpenDocument("bug_547706.pdf"));
415 
416   FPDF_PAGE page = LoadPage(0);
417   ASSERT_TRUE(page);
418 
419   EXPECT_TRUE(FPDFPage_TransFormWithClip(page, &half_matrix, nullptr));
420   EXPECT_TRUE(FPDFPage_TransFormWithClip(page, nullptr, &clip_rect));
421   EXPECT_TRUE(FPDFPage_TransFormWithClip(page, &half_matrix, &clip_rect));
422 
423   UnloadPage(page);
424 }
425 
TEST_F(FPDFTransformEmbedderTest,TransFormWithClipAndSave)426 TEST_F(FPDFTransformEmbedderTest, TransFormWithClipAndSave) {
427   {
428     ASSERT_TRUE(OpenDocument("rectangles.pdf"));
429     FPDF_PAGE page = LoadPage(0);
430     ASSERT_TRUE(page);
431 
432     {
433       // Render the page as is.
434       const int page_width = static_cast<int>(FPDF_GetPageWidth(page));
435       const int page_height = static_cast<int>(FPDF_GetPageHeight(page));
436       EXPECT_EQ(200, page_width);
437       EXPECT_EQ(300, page_height);
438       ScopedFPDFBitmap bitmap = RenderLoadedPage(page);
439       CompareBitmap(bitmap.get(), page_width, page_height,
440                     RectanglesChecksum());
441     }
442 
443     {
444       // Render the page after transforming.
445       // Note that the change should affect the rendering, but does not.
446       // It should behaves just like the case below, rather than the case above.
447       // TODO(crbug.com/pdfium/1328): The checksum after invoking
448       // `FPDFPage_TransFormWithClip()` below should match `ShrunkChecksum()`.
449       const FS_MATRIX half_matrix{0.5, 0, 0, 0.5, 0, 0};
450       EXPECT_TRUE(FPDFPage_TransFormWithClip(page, &half_matrix, nullptr));
451       const int page_width = static_cast<int>(FPDF_GetPageWidth(page));
452       const int page_height = static_cast<int>(FPDF_GetPageHeight(page));
453       EXPECT_EQ(200, page_width);
454       EXPECT_EQ(300, page_height);
455       ScopedFPDFBitmap bitmap = RenderLoadedPage(page);
456       CompareBitmap(bitmap.get(), page_width, page_height,
457                     RectanglesChecksum());
458     }
459 
460     UnloadPage(page);
461   }
462 
463   {
464     // Save a copy, open the copy, and render it.
465     // Note that it renders the transform.
466     EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
467     ASSERT_TRUE(OpenSavedDocument());
468     FPDF_PAGE saved_page = LoadSavedPage(0);
469     ASSERT_TRUE(saved_page);
470 
471     const int page_width = static_cast<int>(FPDF_GetPageWidth(saved_page));
472     const int page_height = static_cast<int>(FPDF_GetPageHeight(saved_page));
473     EXPECT_EQ(200, page_width);
474     EXPECT_EQ(300, page_height);
475     ScopedFPDFBitmap bitmap = RenderSavedPage(saved_page);
476     CompareBitmap(bitmap.get(), page_width, page_height, ShrunkChecksum());
477 
478     CloseSavedPage(saved_page);
479     CloseSavedDocument();
480   }
481 }
482 
483 #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_FUCHSIA)
TEST_F(FPDFTransformEmbedderTest,TransFormWithClipAndSaveWithLocale)484 TEST_F(FPDFTransformEmbedderTest, TransFormWithClipAndSaveWithLocale) {
485   pdfium::base::ScopedLocale scoped_locale("da_DK.UTF-8");
486 
487   {
488     ASSERT_TRUE(OpenDocument("rectangles.pdf"));
489     FPDF_PAGE page = LoadPage(0);
490     ASSERT_TRUE(page);
491 
492     {
493       // Render the page as is.
494       const int page_width = static_cast<int>(FPDF_GetPageWidth(page));
495       const int page_height = static_cast<int>(FPDF_GetPageHeight(page));
496       EXPECT_EQ(200, page_width);
497       EXPECT_EQ(300, page_height);
498       ScopedFPDFBitmap bitmap = RenderLoadedPage(page);
499       CompareBitmap(bitmap.get(), page_width, page_height,
500                     RectanglesChecksum());
501     }
502 
503     {
504       // Render the page after transforming.
505       // Note that the change should affect the rendering, but does not.
506       // It should behaves just like the case below, rather than the case above.
507       // TODO(crbug.com/pdfium/1328): The checksum after invoking
508       // `FPDFPage_TransFormWithClip()` below should match `ShrunkChecksum()`.
509       const FS_MATRIX half_matrix{0.5, 0, 0, 0.5, 0, 0};
510       EXPECT_TRUE(FPDFPage_TransFormWithClip(page, &half_matrix, nullptr));
511       const int page_width = static_cast<int>(FPDF_GetPageWidth(page));
512       const int page_height = static_cast<int>(FPDF_GetPageHeight(page));
513       EXPECT_EQ(200, page_width);
514       EXPECT_EQ(300, page_height);
515       ScopedFPDFBitmap bitmap = RenderLoadedPage(page);
516       CompareBitmap(bitmap.get(), page_width, page_height,
517                     RectanglesChecksum());
518     }
519 
520     UnloadPage(page);
521   }
522 
523   {
524     // Save a copy, open the copy, and render it.
525     // Note that it renders the transform.
526     EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
527     ASSERT_TRUE(OpenSavedDocument());
528     FPDF_PAGE saved_page = LoadSavedPage(0);
529     ASSERT_TRUE(saved_page);
530 
531     const int page_width = static_cast<int>(FPDF_GetPageWidth(saved_page));
532     const int page_height = static_cast<int>(FPDF_GetPageHeight(saved_page));
533     EXPECT_EQ(200, page_width);
534     EXPECT_EQ(300, page_height);
535     ScopedFPDFBitmap bitmap = RenderSavedPage(saved_page);
536     CompareBitmap(bitmap.get(), page_width, page_height, ShrunkChecksum());
537 
538     CloseSavedPage(saved_page);
539     CloseSavedDocument();
540   }
541 }
542 #endif  // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) ||
543         // BUILDFLAG(IS_FUCHSIA)
544