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