Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
fpdf_view_embeddertest.cpp
Go to the documentation of this file.
1// Copyright 2015 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 <math.h>
6
7#include <algorithm>
8#include <limits>
9#include <memory>
10#include <string>
11#include <utility>
12#include <vector>
13
14#include "build/build_config.h"
15#include "core/fpdfapi/parser/cpdf_document.h"
16#include "core/fxge/cfx_defaultrenderdevice.h"
17#include "fpdfsdk/cpdfsdk_helpers.h"
18#include "fpdfsdk/fpdf_view_c_api_test.h"
19#include "public/cpp/fpdf_scopers.h"
20#include "public/fpdfview.h"
21#include "testing/embedder_test.h"
22#include "testing/embedder_test_constants.h"
23#include "testing/embedder_test_environment.h"
24#include "testing/fx_string_testhelpers.h"
25#include "testing/gtest/include/gtest/gtest.h"
26#include "testing/utils/file_util.h"
27#include "testing/utils/hash.h"
28#include "testing/utils/path_service.h"
29
30#if defined(PDF_USE_SKIA)
31#include "third_party/skia/include/core/SkCanvas.h" // nogncheck
32#include "third_party/skia/include/core/SkColor.h" // nogncheck
33#include "third_party/skia/include/core/SkColorType.h" // nogncheck
34#include "third_party/skia/include/core/SkImage.h" // nogncheck
35#include "third_party/skia/include/core/SkImageInfo.h" // nogncheck
36#include "third_party/skia/include/core/SkPicture.h" // nogncheck
37#include "third_party/skia/include/core/SkPictureRecorder.h" // nogncheck
38#include "third_party/skia/include/core/SkRefCnt.h" // nogncheck
39#include "third_party/skia/include/core/SkSize.h" // nogncheck
40#include "third_party/skia/include/core/SkSurface.h" // nogncheck
41#endif // defined(PDF_USE_SKIA)
42
43using pdfium::ManyRectanglesChecksum;
44
45namespace {
46
47constexpr char kFirstAlternate[] = "FirstAlternate";
48constexpr char kLastAlternate[] = "LastAlternate";
49
50#if BUILDFLAG(IS_WIN)
51const char kExpectedRectanglePostScript[] = R"(
52save
53/im/initmatrix load def
54/n/newpath load def/m/moveto load def/l/lineto load def/c/curveto load def/h/closepath load def
55/f/fill load def/F/eofill load def/s/stroke load def/W/clip load def/W*/eoclip load def
56/rg/setrgbcolor load def/k/setcmykcolor load def
57/J/setlinecap load def/j/setlinejoin load def/w/setlinewidth load def/M/setmiterlimit load def/d/setdash load def
58/q/gsave load def/Q/grestore load def/iM/imagemask load def
59/Tj/show load def/Ff/findfont load def/Fs/scalefont load def/Sf/setfont load def
60/cm/concat load def/Cm/currentmatrix load def/mx/matrix load def/sm/setmatrix load def
610 300 m 0 0 l 200 0 l 200 300 l 0 300 l h W n
62q
630 300 m 0 0 l 200 0 l 200 300 l 0 300 l h W n
64q
650 J
66[]0 d
670 j
681 w
6910 M
70mx Cm [1 0 0 -1 0 300]cm 0 290 m 10 290 l 10 300 l 0 300 l 0 290 l h 0 0 0 rg
71q F Q s sm
72mx Cm [1 0 0 -1 0 300]cm 10 150 m 60 150 l 60 180 l 10 180 l 10 150 l h q F Q s sm
73mx Cm [1 0 0 -1 0 300]cm 190 290 m 200 290 l 200 300 l 190 300 l 190 290 l h 0 0 1 rg
74q F Q 0 0 0 rg
75s sm
76mx Cm [1 0 0 -1 0 300]cm 70 232 m 120 232 l 120 262 l 70 262 l 70 232 l h 0 0 1 rg
77q F Q 0 0 0 rg
78s sm
79mx Cm [1 0 0 -1 0 300]cm 190 0 m 200 0 l 200 10 l 190 10 l 190 0 l h 0 1 0 rg
80q F Q 0 0 0 rg
81s sm
82mx Cm [1 0 0 -1 0 300]cm 130 150 m 180 150 l 180 180 l 130 180 l 130 150 l h 0 1 0 rg
83q F Q 0 0 0 rg
84s sm
85mx Cm [1 0 0 -1 0 300]cm 0 0 m 10 0 l 10 10 l 0 10 l 0 0 l h 1 0 0 rg
86q F Q 0 0 0 rg
87s sm
88mx Cm [1 0 0 -1 0 300]cm 70 67 m 120 67 l 120 97 l 70 97 l 70 67 l h 1 0 0 rg
89q F Q 0 0 0 rg
90s sm
91Q
92Q
93Q
94
95restore
96)";
97#endif // BUILDFLAG(IS_WIN)
98
99class MockDownloadHints final : public FX_DOWNLOADHINTS {
100 public:
101 static void SAddSegment(FX_DOWNLOADHINTS* pThis, size_t offset, size_t size) {
102 }
103
104 MockDownloadHints() {
105 FX_DOWNLOADHINTS::version = 1;
106 FX_DOWNLOADHINTS::AddSegment = SAddSegment;
107 }
108
109 ~MockDownloadHints() = default;
110};
111
112#if defined(PDF_USE_SKIA)
113ScopedFPDFBitmap SkImageToPdfiumBitmap(const SkImage& image) {
114 ScopedFPDFBitmap bitmap(
115 FPDFBitmap_Create(image.width(), image.height(), /*alpha=*/1));
116 if (!bitmap) {
117 ADD_FAILURE() << "Could not create FPDF_BITMAP";
118 return nullptr;
119 }
120
121 if (!image.readPixels(/*context=*/nullptr,
122 image.imageInfo().makeColorType(kBGRA_8888_SkColorType),
123 FPDFBitmap_GetBuffer(bitmap.get()),
124 FPDFBitmap_GetStride(bitmap.get()),
125 /*srcX=*/0, /*srcY=*/0)) {
126 ADD_FAILURE() << "Could not read pixels from SkImage";
127 return nullptr;
128 }
129
130 return bitmap;
131}
132
133ScopedFPDFBitmap SkPictureToPdfiumBitmap(sk_sp<SkPicture> picture,
134 const SkISize& size) {
135 sk_sp<SkSurface> surface =
136 SkSurfaces::Raster(SkImageInfo::MakeN32Premul(size));
137 if (!surface) {
138 ADD_FAILURE() << "Could not create SkSurface";
139 return nullptr;
140 }
141
142 surface->getCanvas()->clear(SK_ColorWHITE);
143 surface->getCanvas()->drawPicture(picture);
144 sk_sp<SkImage> image = surface->makeImageSnapshot();
145 if (!image) {
146 ADD_FAILURE() << "Could not snapshot SkSurface";
147 return nullptr;
148 }
149
150 return SkImageToPdfiumBitmap(*image);
151}
152#endif // defined(PDF_USE_SKIA)
153
154} // namespace
155
157 EXPECT_TRUE(CheckPDFiumCApi());
158}
159
161 protected:
163 int bitmap_width,
164 int bitmap_height,
165 const FS_MATRIX& matrix,
166 const FS_RECTF& rect,
167 const char* expected_checksum) {
168 ScopedFPDFBitmap bitmap(FPDFBitmap_Create(bitmap_width, bitmap_height, 0));
169 ASSERT_TRUE(FPDFBitmap_FillRect(bitmap.get(), 0, 0, bitmap_width,
170 bitmap_height, 0xFFFFFFFF));
171 FPDF_RenderPageBitmapWithMatrix(bitmap.get(), page, &matrix, &rect, 0);
172 CompareBitmap(bitmap.get(), bitmap_width, bitmap_height, expected_checksum);
173 }
174
175 void TestRenderPageBitmapWithFlags(FPDF_PAGE page,
176 int flags,
177 const char* expected_checksum) {
178 int bitmap_width = static_cast<int>(FPDF_GetPageWidth(page));
179 int bitmap_height = static_cast<int>(FPDF_GetPageHeight(page));
180 ScopedFPDFBitmap bitmap(FPDFBitmap_Create(bitmap_width, bitmap_height, 0));
181 ASSERT_TRUE(FPDFBitmap_FillRect(bitmap.get(), 0, 0, bitmap_width,
182 bitmap_height, 0xFFFFFFFF));
183 FPDF_RenderPageBitmap(bitmap.get(), page, 0, 0, bitmap_width, bitmap_height,
184 0, flags);
185 CompareBitmap(bitmap.get(), bitmap_width, bitmap_height, expected_checksum);
186 }
187
189 int format,
190 const char* expected_checksum) {
192 page, format, /*bitmap_stride=*/0, expected_checksum);
193 }
194
196 FPDF_PAGE page,
197 int format,
198 int bitmap_stride,
199 const char* expected_checksum) {
200 int bitmap_width = static_cast<int>(FPDF_GetPageWidth(page));
201 int bitmap_height = static_cast<int>(FPDF_GetPageHeight(page));
202 int bytes_per_pixel = BytesPerPixelForFormat(format);
203 ASSERT_NE(0, bytes_per_pixel);
204
205 ScopedFPDFBitmap bitmap(FPDFBitmap_CreateEx(
206 bitmap_width, bitmap_height, format, nullptr, bitmap_stride));
207 RenderPageToBitmapAndCheck(page, bitmap.get(), expected_checksum);
208 }
209
211 int format,
212 const char* expected_checksum) {
213 int bitmap_width = static_cast<int>(FPDF_GetPageWidth(page));
214 int bytes_per_pixel = BytesPerPixelForFormat(format);
215 ASSERT_NE(0, bytes_per_pixel);
216
217 int bitmap_stride = bytes_per_pixel * bitmap_width;
218 return TestRenderPageBitmapWithExternalMemoryImpl(
219 page, format, bitmap_stride, expected_checksum);
220 }
221
223 FPDF_PAGE page,
224 int format,
225 const char* expected_checksum) {
226 return TestRenderPageBitmapWithExternalMemoryImpl(
227 page, format, /*bitmap_stride=*/0, expected_checksum);
228 }
229
230#if defined(PDF_USE_SKIA)
232 int width = static_cast<int>(FPDF_GetPageWidth(page));
233 int height = static_cast<int>(FPDF_GetPageHeight(page));
234
236 {
239
242 width, height);
245 }
246
250 }
251#endif // defined(PDF_USE_SKIA)
252
253 private:
254 void TestRenderPageBitmapWithExternalMemoryImpl(
255 FPDF_PAGE page,
256 int format,
257 int bitmap_stride,
258 const char* expected_checksum) {
259 int bitmap_width = static_cast<int>(FPDF_GetPageWidth(page));
260 int bitmap_height = static_cast<int>(FPDF_GetPageHeight(page));
261
262 std::vector<uint8_t> external_memory(bitmap_stride * bitmap_height);
263 ScopedFPDFBitmap bitmap(FPDFBitmap_CreateEx(bitmap_width, bitmap_height,
264 format, external_memory.data(),
265 bitmap_stride));
266 RenderPageToBitmapAndCheck(page, bitmap.get(), expected_checksum);
267 }
268
269 void RenderPageToBitmapAndCheck(FPDF_PAGE page,
270 FPDF_BITMAP bitmap,
271 const char* expected_checksum) {
272 int bitmap_width = FPDFBitmap_GetWidth(bitmap);
273 int bitmap_height = FPDFBitmap_GetHeight(bitmap);
274 EXPECT_EQ(bitmap_width, static_cast<int>(FPDF_GetPageWidth(page)));
275 EXPECT_EQ(bitmap_height, static_cast<int>(FPDF_GetPageHeight(page)));
276 ASSERT_TRUE(FPDFBitmap_FillRect(bitmap, 0, 0, bitmap_width, bitmap_height,
277 0xFFFFFFFF));
278 FPDF_RenderPageBitmap(bitmap, page, 0, 0, bitmap_width, bitmap_height, 0,
280 CompareBitmap(bitmap, bitmap_width, bitmap_height, expected_checksum);
281 }
282};
283
284// Test for conversion of a point in device coordinates to page coordinates
286 ASSERT_TRUE(OpenDocument("about_blank.pdf"));
287 ScopedEmbedderTestPage page = LoadScopedPage(0);
288 EXPECT_TRUE(page);
289
290 // Error tolerance for floating point comparison
291 const double kTolerance = 0.0001;
292
293 // Display bounds in device coordinates
294 int start_x = 0;
295 int start_y = 0;
296 int size_x = 640;
297 int size_y = 480;
298
299 // Page Orientation normal
300 int rotate = 0;
301
302 // Device coordinate to be converted
303 int device_x = 10;
304 int device_y = 10;
305
306 double page_x = 0.0;
307 double page_y = 0.0;
308 EXPECT_TRUE(FPDF_DeviceToPage(page.get(), start_x, start_y, size_x, size_y,
309 rotate, device_x, device_y, &page_x, &page_y));
310 EXPECT_NEAR(9.5625, page_x, kTolerance);
311 EXPECT_NEAR(775.5, page_y, kTolerance);
312
313 // Rotate 90 degrees clockwise
314 rotate = 1;
315 EXPECT_TRUE(FPDF_DeviceToPage(page.get(), start_x, start_y, size_x, size_y,
316 rotate, device_x, device_y, &page_x, &page_y));
317 EXPECT_NEAR(12.75, page_x, kTolerance);
318 EXPECT_NEAR(12.375, page_y, kTolerance);
319
320 // Rotate 180 degrees
321 rotate = 2;
322 EXPECT_TRUE(FPDF_DeviceToPage(page.get(), start_x, start_y, size_x, size_y,
323 rotate, device_x, device_y, &page_x, &page_y));
324 EXPECT_NEAR(602.4374, page_x, kTolerance);
325 EXPECT_NEAR(16.5, page_y, kTolerance);
326
327 // Rotate 90 degrees counter-clockwise
328 rotate = 3;
329 EXPECT_TRUE(FPDF_DeviceToPage(page.get(), start_x, start_y, size_x, size_y,
330 rotate, device_x, device_y, &page_x, &page_y));
331 EXPECT_NEAR(599.25, page_x, kTolerance);
332 EXPECT_NEAR(779.625, page_y, kTolerance);
333
334 // FPDF_DeviceToPage() converts |rotate| into legal rotation by taking
335 // modulo by 4. A value of 4 is expected to be converted into 0 (normal
336 // rotation)
337 rotate = 4;
338 EXPECT_TRUE(FPDF_DeviceToPage(page.get(), start_x, start_y, size_x, size_y,
339 rotate, device_x, device_y, &page_x, &page_y));
340 EXPECT_NEAR(9.5625, page_x, kTolerance);
341 EXPECT_NEAR(775.5, page_y, kTolerance);
342
343 // FPDF_DeviceToPage returns untransformed coordinates if |rotate| % 4 is
344 // negative.
345 rotate = -1;
346 EXPECT_TRUE(FPDF_DeviceToPage(page.get(), start_x, start_y, size_x, size_y,
347 rotate, device_x, device_y, &page_x, &page_y));
348 EXPECT_NEAR(device_x, page_x, kTolerance);
349 EXPECT_NEAR(device_y, page_y, kTolerance);
350
351 // Negative case - invalid page
352 page_x = 1234.0;
353 page_y = 5678.0;
354 EXPECT_FALSE(FPDF_DeviceToPage(nullptr, start_x, start_y, size_x, size_y,
355 rotate, device_x, device_y, &page_x, &page_y));
356 // Out parameters are expected to remain unchanged
357 EXPECT_NEAR(1234.0, page_x, kTolerance);
358 EXPECT_NEAR(5678.0, page_y, kTolerance);
359
360 // Negative case - invalid output parameters
361 EXPECT_FALSE(FPDF_DeviceToPage(page.get(), start_x, start_y, size_x, size_y,
362 rotate, device_x, device_y, nullptr, nullptr));
363}
364
365// Test for conversion of a point in page coordinates to device coordinates.
367 ASSERT_TRUE(OpenDocument("about_blank.pdf"));
368 FPDF_PAGE page = LoadPage(0);
369 EXPECT_TRUE(page);
370
371 // Display bounds in device coordinates
372 int start_x = 0;
373 int start_y = 0;
374 int size_x = 640;
375 int size_y = 480;
376
377 // Page Orientation normal
378 int rotate = 0;
379
380 // Page coordinate to be converted
381 double page_x = 9.0;
382 double page_y = 775.0;
383
384 int device_x = 0;
385 int device_y = 0;
386 EXPECT_TRUE(FPDF_PageToDevice(page, start_x, start_y, size_x, size_y, rotate,
387 page_x, page_y, &device_x, &device_y));
388
389 EXPECT_EQ(9, device_x);
390 EXPECT_EQ(10, device_y);
391
392 // Rotate 90 degrees clockwise
393 rotate = 1;
394 EXPECT_TRUE(FPDF_PageToDevice(page, start_x, start_y, size_x, size_y, rotate,
395 page_x, page_y, &device_x, &device_y));
396 EXPECT_EQ(626, device_x);
397 EXPECT_EQ(7, device_y);
398
399 // Rotate 180 degrees
400 rotate = 2;
401 EXPECT_TRUE(FPDF_PageToDevice(page, start_x, start_y, size_x, size_y, rotate,
402 page_x, page_y, &device_x, &device_y));
403 EXPECT_EQ(631, device_x);
404 EXPECT_EQ(470, device_y);
405
406 // Rotate 90 degrees counter-clockwise
407 rotate = 3;
408 EXPECT_TRUE(FPDF_PageToDevice(page, start_x, start_y, size_x, size_y, rotate,
409 page_x, page_y, &device_x, &device_y));
410 EXPECT_EQ(14, device_x);
411 EXPECT_EQ(473, device_y);
412
413 // FPDF_PageToDevice() converts |rotate| into legal rotation by taking
414 // modulo by 4. A value of 4 is expected to be converted into 0 (normal
415 // rotation)
416 rotate = 4;
417 EXPECT_TRUE(FPDF_PageToDevice(page, start_x, start_y, size_x, size_y, rotate,
418 page_x, page_y, &device_x, &device_y));
419 EXPECT_EQ(9, device_x);
420 EXPECT_EQ(10, device_y);
421
422 // FPDF_PageToDevice() returns untransformed coordinates if |rotate| % 4 is
423 // negative.
424 rotate = -1;
425 EXPECT_TRUE(FPDF_PageToDevice(page, start_x, start_y, size_x, size_y, rotate,
426 page_x, page_y, &device_x, &device_y));
427 EXPECT_EQ(start_x, device_x);
428 EXPECT_EQ(start_y, device_y);
429
430 // Negative case - invalid page
431 device_x = 1234;
432 device_y = 5678;
433 EXPECT_FALSE(FPDF_PageToDevice(nullptr, start_x, start_y, size_x, size_y,
434 rotate, page_x, page_y, &device_x, &device_y));
435 // Out parameters are expected to remain unchanged
436 EXPECT_EQ(1234, device_x);
437 EXPECT_EQ(5678, device_y);
438
439 // Negative case - invalid output parameters
440 EXPECT_FALSE(FPDF_PageToDevice(page, start_x, start_y, size_x, size_y, rotate,
441 page_x, page_y, nullptr, nullptr));
442
443 UnloadPage(page);
444}
445
447 FPDF_InitLibrary(); // Redundant given SetUp() in environment, but safe.
448 FPDF_InitLibrary(); // Doubly-redundant even, but safe.
449
450 ASSERT_TRUE(OpenDocument("about_blank.pdf"));
451 CloseDocument();
452 CloseDocument(); // Redundant given above, but safe.
453 CloseDocument(); // Doubly-redundant even, but safe.
454
455 FPDF_DestroyLibrary(); // Doubly-Redundant even, but safe.
456 FPDF_DestroyLibrary(); // Redundant given call to TearDown(), but safe.
457
460}
461
463 for (int i = 0; i < 3; ++i) {
464 if (!OpenDocument("about_blank.pdf"))
465 ADD_FAILURE();
466 CloseDocument();
467
470 }
471
472 // Puts the test environment back the way it was.
475}
476
478 ASSERT_TRUE(OpenDocument("about_blank.pdf"));
479 EXPECT_EQ(1, GetPageCount());
480 EXPECT_EQ(0, GetFirstPageNum());
481
482 int version;
483 EXPECT_TRUE(FPDF_GetFileVersion(document(), &version));
484 EXPECT_EQ(14, version);
485
486 // 0xFFFFFFFF because no security handler present
487 EXPECT_EQ(0xFFFFFFFF, FPDF_GetDocPermissions(document()));
488 EXPECT_EQ(0xFFFFFFFF, FPDF_GetDocUserPermissions(document()));
489 EXPECT_EQ(-1, FPDF_GetSecurityHandlerRevision(document()));
490 CloseDocument();
491
492 // Safe to open again and do the same things all over again.
493 ASSERT_TRUE(OpenDocument("about_blank.pdf"));
494 EXPECT_EQ(1, GetPageCount());
495 EXPECT_EQ(0, GetFirstPageNum());
496
497 version = 42;
498 EXPECT_TRUE(FPDF_GetFileVersion(document(), &version));
499 EXPECT_EQ(14, version);
500
501 // 0xFFFFFFFF because no security handler present
502 EXPECT_EQ(0xFFFFFFFF, FPDF_GetDocPermissions(document()));
503 EXPECT_EQ(0xFFFFFFFF, FPDF_GetDocUserPermissions(document()));
504 EXPECT_EQ(-1, FPDF_GetSecurityHandlerRevision(document()));
505 // CloseDocument() called by TearDown().
506}
507
509 std::string file_path = PathService::GetTestFilePath("about_blank.pdf");
510 ASSERT_FALSE(file_path.empty());
511
512 std::vector<uint8_t> file_contents = GetFileContents(file_path.c_str());
513 ASSERT_FALSE(file_contents.empty());
514 ScopedFPDFDocument doc(FPDF_LoadMemDocument64(file_contents.data(),
515 file_contents.size(), nullptr));
516 ASSERT_TRUE(doc);
517
518 int version;
519 EXPECT_TRUE(FPDF_GetFileVersion(doc.get(), &version));
520 EXPECT_EQ(14, version);
521}
522
524 FPDF_DOCUMENT doc = FPDF_LoadDocument("nonexistent_document.pdf", "");
525 ASSERT_FALSE(doc);
526 EXPECT_EQ(static_cast<int>(FPDF_GetLastError()), FPDF_ERR_FILE);
527}
528
530 ASSERT_TRUE(OpenDocument("no_page_count.pdf"));
531 ASSERT_EQ(6, FPDF_GetPageCount(document()));
532}
533
535 ASSERT_TRUE(OpenDocument("page_tree_empty_node.pdf"));
536 ASSERT_EQ(2, FPDF_GetPageCount(document()));
537}
538
539// See https://crbug.com/pdfium/465
541 CreateEmptyDocument();
542 {
543 int version = 42;
544 EXPECT_FALSE(FPDF_GetFileVersion(document(), &version));
545 EXPECT_EQ(0, version);
546 }
547 EXPECT_EQ(0U, FPDF_GetDocPermissions(document()));
548 EXPECT_EQ(-1, FPDF_GetSecurityHandlerRevision(document()));
549 EXPECT_EQ(0, FPDF_GetPageCount(document()));
550 EXPECT_TRUE(FPDF_VIEWERREF_GetPrintScaling(document()));
551 EXPECT_EQ(1, FPDF_VIEWERREF_GetNumCopies(document()));
552 EXPECT_EQ(DuplexUndefined, FPDF_VIEWERREF_GetDuplex(document()));
553
554 char buf[100];
555 EXPECT_EQ(0U, FPDF_VIEWERREF_GetName(document(), "foo", nullptr, 0));
556 EXPECT_EQ(0U, FPDF_VIEWERREF_GetName(document(), "foo", buf, sizeof(buf)));
557 EXPECT_EQ(0u, FPDF_CountNamedDests(document()));
558}
559
561 uint16_t buf[200];
562 unsigned long len;
563
564 CreateEmptyDocument();
565 len = FPDF_GetMetaText(document(), "CreationDate", buf, sizeof(buf));
566 EXPECT_GT(len, 2u); // Not just "double NUL" end-of-string indicator.
567 EXPECT_NE(0u, buf[0]);
568 CloseDocument();
569
571 CreateEmptyDocument();
572 len = FPDF_GetMetaText(document(), "CreationDate", buf, sizeof(buf));
573 EXPECT_EQ(2u, len); // Only a "double NUL" end-of-string indicator.
574 EXPECT_EQ(0u, buf[0]);
575 CloseDocument();
576
577 constexpr unsigned long kNoSuchPolicy = 102;
578 FPDF_SetSandBoxPolicy(kNoSuchPolicy, true);
579 CreateEmptyDocument();
580 len = FPDF_GetMetaText(document(), "CreationDate", buf, sizeof(buf));
581 EXPECT_EQ(2u, len); // Only a "double NUL" end-of-string indicator.
582 EXPECT_EQ(0u, buf[0]);
583 CloseDocument();
584
586 CreateEmptyDocument();
587 len = FPDF_GetMetaText(document(), "CreationDate", buf, sizeof(buf));
588 EXPECT_GT(len, 2u); // Not just "double NUL" end-of-string indicator.
589 EXPECT_NE(0u, buf[0]);
590 CloseDocument();
591}
592
594 ASSERT_TRUE(OpenDocumentLinearized("feature_linearized_loading.pdf"));
595 int version;
596 EXPECT_TRUE(FPDF_GetFileVersion(document(), &version));
597 EXPECT_EQ(16, version);
598}
599
603
604// See https://crbug.com/pdfium/1261
606 std::string file_contents_string; // Must outlive |doc|.
607 ScopedFPDFDocument doc;
608 {
609 // Read a PDF, and copy it into |file_contents_string|.
610 std::string pdf_path = PathService::GetTestFilePath("rectangles.pdf");
611 ASSERT_FALSE(pdf_path.empty());
612 std::vector<uint8_t> file_contents = GetFileContents(pdf_path.c_str());
613 ASSERT_FALSE(file_contents.empty());
614 std::copy(file_contents.begin(), file_contents.end(),
615 std::back_inserter(file_contents_string));
616
617 // Define a FPDF_FILEACCESS object that will go out of scope, while the
618 // loaded document in |doc| remains valid.
619 FPDF_FILEACCESS file_access = {};
620 file_access.m_FileLen = file_contents_string.size();
621 file_access.m_GetBlock = GetBlockFromString;
622 file_access.m_Param = &file_contents_string;
623 doc.reset(FPDF_LoadCustomDocument(&file_access, nullptr));
624 ASSERT_TRUE(doc);
625 }
626
627 // Now try to access |doc| and make sure it still works.
628 ScopedFPDFPage page(FPDF_LoadPage(doc.get(), 0));
629 ASSERT_TRUE(page);
630 EXPECT_FLOAT_EQ(200.0f, FPDF_GetPageWidthF(page.get()));
631 EXPECT_FLOAT_EQ(300.0f, FPDF_GetPageHeightF(page.get()));
632}
633
635 ASSERT_TRUE(OpenDocument("about_blank.pdf"));
636 FPDF_PAGE page = LoadPage(0);
637 EXPECT_TRUE(page);
638
639 EXPECT_FLOAT_EQ(612.0f, FPDF_GetPageWidthF(page));
640 EXPECT_FLOAT_EQ(792.0f, FPDF_GetPageHeightF(page));
641
642 FS_RECTF rect;
643 EXPECT_TRUE(FPDF_GetPageBoundingBox(page, &rect));
644 EXPECT_EQ(0.0, rect.left);
645 EXPECT_EQ(0.0, rect.bottom);
646 EXPECT_EQ(612.0, rect.right);
647 EXPECT_EQ(792.0, rect.top);
648
649 // Null arguments return errors rather than crashing,
650 EXPECT_EQ(0.0, FPDF_GetPageWidth(nullptr));
651 EXPECT_EQ(0.0, FPDF_GetPageHeight(nullptr));
652 EXPECT_FALSE(FPDF_GetPageBoundingBox(nullptr, &rect));
653 EXPECT_FALSE(FPDF_GetPageBoundingBox(page, nullptr));
654
655 UnloadPage(page);
656 EXPECT_FALSE(LoadPage(1));
657}
658
660 ASSERT_TRUE(OpenDocument("about_blank.pdf"));
661 EXPECT_TRUE(FPDF_VIEWERREF_GetPrintScaling(document()));
662 EXPECT_EQ(1, FPDF_VIEWERREF_GetNumCopies(document()));
663 EXPECT_EQ(DuplexUndefined, FPDF_VIEWERREF_GetDuplex(document()));
664
665 char buf[100];
666 EXPECT_EQ(0U, FPDF_VIEWERREF_GetName(document(), "foo", nullptr, 0));
667 EXPECT_EQ(0U, FPDF_VIEWERREF_GetName(document(), "foo", buf, sizeof(buf)));
668
669 FPDF_PAGERANGE page_range = FPDF_VIEWERREF_GetPrintPageRange(document());
670 EXPECT_FALSE(page_range);
671 EXPECT_EQ(0U, FPDF_VIEWERREF_GetPrintPageRangeCount(page_range));
672 EXPECT_EQ(-1, FPDF_VIEWERREF_GetPrintPageRangeElement(page_range, 0));
673 EXPECT_EQ(-1, FPDF_VIEWERREF_GetPrintPageRangeElement(page_range, 1));
674}
675
677 ASSERT_TRUE(OpenDocument("viewer_ref.pdf"));
678 EXPECT_TRUE(FPDF_VIEWERREF_GetPrintScaling(document()));
679 EXPECT_EQ(5, FPDF_VIEWERREF_GetNumCopies(document()));
680 EXPECT_EQ(DuplexUndefined, FPDF_VIEWERREF_GetDuplex(document()));
681
682 // Test some corner cases.
683 char buf[100];
684 EXPECT_EQ(0U, FPDF_VIEWERREF_GetName(document(), "", buf, sizeof(buf)));
685 EXPECT_EQ(0U, FPDF_VIEWERREF_GetName(document(), "foo", nullptr, 0));
686 EXPECT_EQ(0U, FPDF_VIEWERREF_GetName(document(), "foo", buf, sizeof(buf)));
687
688 // Make sure |buf| does not get written into when it appears to be too small.
689 // NOLINTNEXTLINE(runtime/printf)
690 strcpy(buf, "ABCD");
691 EXPECT_EQ(4U, FPDF_VIEWERREF_GetName(document(), "Foo", buf, 1));
692 EXPECT_STREQ("ABCD", buf);
693
694 // Note "Foo" is a different key from "foo".
695 EXPECT_EQ(4U, FPDF_VIEWERREF_GetName(document(), "Foo", nullptr, 0));
696 ASSERT_EQ(4U, FPDF_VIEWERREF_GetName(document(), "Foo", buf, sizeof(buf)));
697 EXPECT_STREQ("foo", buf);
698
699 // Try to retrieve a boolean and an integer.
700 EXPECT_EQ(
701 0U, FPDF_VIEWERREF_GetName(document(), "HideToolbar", buf, sizeof(buf)));
702 EXPECT_EQ(0U,
703 FPDF_VIEWERREF_GetName(document(), "NumCopies", buf, sizeof(buf)));
704
705 // Try more valid cases.
706 ASSERT_EQ(4U,
707 FPDF_VIEWERREF_GetName(document(), "Direction", buf, sizeof(buf)));
708 EXPECT_STREQ("R2L", buf);
709 ASSERT_EQ(8U,
710 FPDF_VIEWERREF_GetName(document(), "ViewArea", buf, sizeof(buf)));
711 EXPECT_STREQ("CropBox", buf);
712
713 FPDF_PAGERANGE page_range = FPDF_VIEWERREF_GetPrintPageRange(document());
714 EXPECT_TRUE(page_range);
715 EXPECT_EQ(4U, FPDF_VIEWERREF_GetPrintPageRangeCount(page_range));
716 EXPECT_EQ(0, FPDF_VIEWERREF_GetPrintPageRangeElement(page_range, 0));
717 EXPECT_EQ(2, FPDF_VIEWERREF_GetPrintPageRangeElement(page_range, 1));
718 EXPECT_EQ(4, FPDF_VIEWERREF_GetPrintPageRangeElement(page_range, 2));
719 EXPECT_EQ(4, FPDF_VIEWERREF_GetPrintPageRangeElement(page_range, 3));
720 EXPECT_EQ(-1, FPDF_VIEWERREF_GetPrintPageRangeElement(page_range, 4));
721}
722
724 ASSERT_TRUE(OpenDocument("named_dests.pdf"));
725 EXPECT_EQ(6u, FPDF_CountNamedDests(document()));
726
727 long buffer_size;
728 char fixed_buffer[512];
729 FPDF_DEST dest;
730
731 // Query the size of the first item.
732 buffer_size = 2000000; // Absurdly large, check not used for this case.
733 dest = FPDF_GetNamedDest(document(), 0, nullptr, &buffer_size);
734 EXPECT_TRUE(dest);
735 EXPECT_EQ(12, buffer_size);
736
737 // Try to retrieve the first item with too small a buffer.
738 buffer_size = 10;
739 dest = FPDF_GetNamedDest(document(), 0, fixed_buffer, &buffer_size);
740 EXPECT_TRUE(dest);
741 EXPECT_EQ(-1, buffer_size);
742
743 // Try to retrieve the first item with correctly sized buffer. Item is
744 // taken from Dests NameTree in named_dests.pdf.
745 buffer_size = 12;
746 dest = FPDF_GetNamedDest(document(), 0, fixed_buffer, &buffer_size);
747 EXPECT_TRUE(dest);
748 EXPECT_EQ(12, buffer_size);
749 EXPECT_EQ("First",
750 GetPlatformString(reinterpret_cast<FPDF_WIDESTRING>(fixed_buffer)));
751
752 // Try to retrieve the second item with ample buffer. Item is taken
753 // from Dests NameTree but has a sub-dictionary in named_dests.pdf.
754 buffer_size = sizeof(fixed_buffer);
755 dest = FPDF_GetNamedDest(document(), 1, fixed_buffer, &buffer_size);
756 EXPECT_TRUE(dest);
757 EXPECT_EQ(10, buffer_size);
758 EXPECT_EQ("Next",
759 GetPlatformString(reinterpret_cast<FPDF_WIDESTRING>(fixed_buffer)));
760
761 // Try to retrieve third item with ample buffer. Item is taken
762 // from Dests NameTree but has a bad sub-dictionary in named_dests.pdf.
763 // in named_dests.pdf).
764 buffer_size = sizeof(fixed_buffer);
765 dest = FPDF_GetNamedDest(document(), 2, fixed_buffer, &buffer_size);
766 EXPECT_FALSE(dest);
767 EXPECT_EQ(sizeof(fixed_buffer),
768 static_cast<size_t>(buffer_size)); // unmodified.
769
770 // Try to retrieve the forth item with ample buffer. Item is taken
771 // from Dests NameTree but has a vale of the wrong type in named_dests.pdf.
772 buffer_size = sizeof(fixed_buffer);
773 dest = FPDF_GetNamedDest(document(), 3, fixed_buffer, &buffer_size);
774 EXPECT_FALSE(dest);
775 EXPECT_EQ(sizeof(fixed_buffer),
776 static_cast<size_t>(buffer_size)); // unmodified.
777
778 // Try to retrieve fifth item with ample buffer. Item taken from the
779 // old-style Dests dictionary object in named_dests.pdf.
780 buffer_size = sizeof(fixed_buffer);
781 dest = FPDF_GetNamedDest(document(), 4, fixed_buffer, &buffer_size);
782 EXPECT_TRUE(dest);
783 EXPECT_EQ(30, buffer_size);
784 EXPECT_EQ(kFirstAlternate,
785 GetPlatformString(reinterpret_cast<FPDF_WIDESTRING>(fixed_buffer)));
786
787 // Try to retrieve sixth item with ample buffer. Item istaken from the
788 // old-style Dests dictionary object but has a sub-dictionary in
789 // named_dests.pdf.
790 buffer_size = sizeof(fixed_buffer);
791 dest = FPDF_GetNamedDest(document(), 5, fixed_buffer, &buffer_size);
792 EXPECT_TRUE(dest);
793 EXPECT_EQ(28, buffer_size);
794 EXPECT_EQ(kLastAlternate,
795 GetPlatformString(reinterpret_cast<FPDF_WIDESTRING>(fixed_buffer)));
796
797 // Try to retrieve non-existent item with ample buffer.
798 buffer_size = sizeof(fixed_buffer);
799 dest = FPDF_GetNamedDest(document(), 6, fixed_buffer, &buffer_size);
800 EXPECT_FALSE(dest);
801 EXPECT_EQ(sizeof(fixed_buffer),
802 static_cast<size_t>(buffer_size)); // unmodified.
803
804 // Try to underflow/overflow the integer index.
805 buffer_size = sizeof(fixed_buffer);
806 dest = FPDF_GetNamedDest(document(), std::numeric_limits<int>::max(),
807 fixed_buffer, &buffer_size);
808 EXPECT_FALSE(dest);
809 EXPECT_EQ(sizeof(fixed_buffer),
810 static_cast<size_t>(buffer_size)); // unmodified.
811
812 buffer_size = sizeof(fixed_buffer);
813 dest = FPDF_GetNamedDest(document(), std::numeric_limits<int>::min(),
814 fixed_buffer, &buffer_size);
815 EXPECT_FALSE(dest);
816 EXPECT_EQ(sizeof(fixed_buffer),
817 static_cast<size_t>(buffer_size)); // unmodified.
818
819 buffer_size = sizeof(fixed_buffer);
820 dest = FPDF_GetNamedDest(document(), -1, fixed_buffer, &buffer_size);
821 EXPECT_FALSE(dest);
822 EXPECT_EQ(sizeof(fixed_buffer),
823 static_cast<size_t>(buffer_size)); // unmodified.
824}
825
827 ASSERT_TRUE(OpenDocument("named_dests.pdf"));
828
829 // Null pointer returns nullptr.
830 FPDF_DEST dest = FPDF_GetNamedDestByName(document(), nullptr);
831 EXPECT_FALSE(dest);
832
833 // Empty string returns nullptr.
834 dest = FPDF_GetNamedDestByName(document(), "");
835 EXPECT_FALSE(dest);
836
837 // Item from Dests NameTree.
838 dest = FPDF_GetNamedDestByName(document(), "First");
839 EXPECT_TRUE(dest);
840
841 long ignore_len = 0;
842 FPDF_DEST dest_by_index =
843 FPDF_GetNamedDest(document(), 0, nullptr, &ignore_len);
844 EXPECT_EQ(dest_by_index, dest);
845
846 // Item from Dests dictionary.
847 dest = FPDF_GetNamedDestByName(document(), kFirstAlternate);
848 EXPECT_TRUE(dest);
849
850 ignore_len = 0;
851 dest_by_index = FPDF_GetNamedDest(document(), 4, nullptr, &ignore_len);
852 EXPECT_EQ(dest_by_index, dest);
853
854 // Bad value type for item from Dests NameTree array.
855 dest = FPDF_GetNamedDestByName(document(), "WrongType");
856 EXPECT_FALSE(dest);
857
858 // No such destination in either Dest NameTree or dictionary.
859 dest = FPDF_GetNamedDestByName(document(), "Bogus");
860 EXPECT_FALSE(dest);
861}
862
864 ASSERT_TRUE(OpenDocument("named_dests_old_style.pdf"));
865 EXPECT_EQ(2u, FPDF_CountNamedDests(document()));
866
867 // Test bad parameters.
868 EXPECT_FALSE(FPDF_GetNamedDestByName(document(), nullptr));
869 EXPECT_FALSE(FPDF_GetNamedDestByName(document(), ""));
870 EXPECT_FALSE(FPDF_GetNamedDestByName(document(), "NoSuchName"));
871
872 // These should return a valid destination.
873 EXPECT_TRUE(FPDF_GetNamedDestByName(document(), kFirstAlternate));
874 EXPECT_TRUE(FPDF_GetNamedDestByName(document(), kLastAlternate));
875
876 char buffer[512];
877 constexpr long kBufferSize = sizeof(buffer);
878 long size = kBufferSize;
879
880 // Test bad indices.
881 EXPECT_FALSE(FPDF_GetNamedDest(document(), -1, buffer, &size));
882 EXPECT_EQ(kBufferSize, size);
883 size = kBufferSize;
884 EXPECT_FALSE(FPDF_GetNamedDest(document(), 2, buffer, &size));
885 EXPECT_EQ(kBufferSize, size);
886
887 // These should return a valid destination.
888 size = kBufferSize;
889 ASSERT_TRUE(FPDF_GetNamedDest(document(), 0, buffer, &size));
890 ASSERT_EQ(static_cast<int>(sizeof(kFirstAlternate) * 2), size);
891 EXPECT_EQ(kFirstAlternate,
892 GetPlatformString(reinterpret_cast<FPDF_WIDESTRING>(buffer)));
893 size = kBufferSize;
894 ASSERT_TRUE(FPDF_GetNamedDest(document(), 1, buffer, &size));
895 ASSERT_EQ(static_cast<int>(sizeof(kLastAlternate) * 2), size);
896 EXPECT_EQ(kLastAlternate,
897 GetPlatformString(reinterpret_cast<FPDF_WIDESTRING>(buffer)));
898}
899
900// The following tests pass if the document opens without crashing.
902 ASSERT_TRUE(OpenDocument("bug_113.pdf"));
903}
904
906 // Document is damaged and can't be opened.
907 EXPECT_FALSE(OpenDocument("bug_451830.pdf"));
908}
909
911 ASSERT_TRUE(OpenDocument("bug_452455.pdf"));
912 ScopedEmbedderTestPage page = LoadScopedPage(0);
913 EXPECT_TRUE(page);
914}
915
917 // Document is damaged and can't be opened.
918 EXPECT_FALSE(OpenDocument("bug_454695.pdf"));
919}
920
922 ASSERT_TRUE(OpenDocument("bug_572871.pdf"));
923}
924
925// It tests that document can still be loaded even the trailer has no 'Size'
926// field if other information is right.
928 ASSERT_TRUE(OpenDocument("bug_213.pdf"));
929}
930
931// The following tests pass if the document opens without infinite looping.
933 EXPECT_FALSE(OpenDocument("bug_298.pdf"));
934}
935
937 ASSERT_TRUE(OpenDocument("bug_773229.pdf"));
938}
939
940// Test if the document opens without infinite looping.
941// Previously this test will hang in a loop inside LoadAllCrossRefV4. After
942// the fix, LoadAllCrossRefV4 will return false after detecting a cross
943// reference loop. Cross references will be rebuilt successfully.
945 ASSERT_TRUE(OpenDocument("bug_xrefv4_loop.pdf"));
946 MockDownloadHints hints;
947
948 // Make sure calling FPDFAvail_IsDocAvail() on this file does not infinite
949 // loop either. See bug 875.
950 int ret = PDF_DATA_NOTAVAIL;
951 while (ret == PDF_DATA_NOTAVAIL)
952 ret = FPDFAvail_IsDocAvail(avail(), &hints);
953 EXPECT_EQ(PDF_DATA_AVAIL, ret);
954}
955
956// The test should pass when circular references to ParseIndirectObject will not
957// cause infinite loop.
959 EXPECT_FALSE(OpenDocument("bug_343.pdf"));
960}
961
962// The test should pass when the absence of 'Contents' field in a signature
963// dictionary will not cause an infinite loop in CPDF_SyntaxParser::GetObject().
965 EXPECT_FALSE(OpenDocument("bug_344.pdf"));
966}
967
968// The test should pass when there is no infinite recursion in
969// CPDF_SyntaxParser::GetString().
971 EXPECT_FALSE(OpenDocument("bug_355.pdf"));
972}
973// The test should pass even when the file has circular references to pages.
975 EXPECT_FALSE(OpenDocument("bug_360.pdf"));
976}
977
978// Deliberately damaged version of linearized.pdf with bad data in the shared
979// object hint table.
981 ASSERT_TRUE(OpenDocumentLinearized("linearized_bug_1055.pdf"));
982 int version;
983 EXPECT_TRUE(FPDF_GetFileVersion(document(), &version));
984 EXPECT_EQ(16, version);
985}
986
988 const char* clipped_checksum = []() {
989 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
990 return "d2929fae285593cd1c1d446750d47d60";
991 }
992 return "a84cab93c102b9b9290fba3047ba702c";
993 }();
994 const char* top_left_quarter_checksum = []() {
995 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
996 return "31d24d8c6a2bac380b2f5c393e77ecc9";
997 }
998 return "f11a11137c8834389e31cf555a4a6979";
999 }();
1000 const char* rotated_90_clockwise_checksum = []() {
1001 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
1002 return "b4baa001d201baed576cd6d5d0d5a160";
1003 }
1004 return "d8da2c7bf77521550d0f2752b9cf3482";
1005 }();
1006 const char* rotated_180_clockwise_checksum = []() {
1007 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
1008 return "51819227d0863222aed366d5d7c5d9c8";
1009 }
1010 return "0113386bb0bd45125bacc6dee78bfe78";
1011 }();
1012 const char* rotated_270_clockwise_checksum = []() {
1013 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
1014 return "f2b046e46c2751cebc777a9725ae2f3e";
1015 }
1016 return "a287e0f74ce203699cda89f9cc97a240";
1017 }();
1018 const char* mirror_hori_checksum = []() {
1019 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
1020 return "c7fbec322b4fc6bcf46ec1eb89661c41";
1021 }
1022 return "6e8d7a6fde39d8e720fb9e620102918c";
1023 }();
1024 const char* mirror_vert_checksum = []() {
1025 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
1026 return "a8b00bc40677a73c15a08b9769d1b576";
1027 }
1028 return "8f3a555ef9c0d5031831ae3715273707";
1029 }();
1030 const char* larger_top_left_quarter_checksum = []() {
1031 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
1032 return "35deb5ed4b73675ce33f68328a33c687";
1033 }
1034 return "172a2f4adafbadbe98017b1c025b9e27";
1035 }();
1036 const char* larger_rotated_diagonal_checksum = []() {
1037 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
1038 return "a7179bc24e329341a1a1f6d6be20a1e9";
1039 }
1040 return "3d62417468bdaff0eb14391a0c30a3b1";
1041 }();
1042 const char* tile_checksum = []() {
1043 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
1044 return "387be3a84774f39aaa955314d2fe7106";
1045 }
1046 return "0a190003c97220bf8877684c8d7e89cf";
1047 }();
1048 const char kHoriStretchedChecksum[] = "48ef9205941ed19691ccfa00d717187e";
1049 const char kLargerChecksum[] = "c806145641c3e6fc4e022c7065343749";
1050 const char kLargerClippedChecksum[] = "091d3b1c7933c8f6945eb2cb41e588e9";
1051 const char kLargerRotatedChecksum[] = "115f13353ebfc82ddb392d1f0059eb12";
1052 const char kLargerRotatedLandscapeChecksum[] =
1053 "c901239d17d84ac84cb6f2124da71b0d";
1054
1055 ASSERT_TRUE(OpenDocument("rectangles.pdf"));
1056 FPDF_PAGE page = LoadPage(0);
1057 ASSERT_TRUE(page);
1058 const float page_width = FPDF_GetPageWidthF(page);
1059 const float page_height = FPDF_GetPageHeightF(page);
1060 EXPECT_FLOAT_EQ(200, page_width);
1061 EXPECT_FLOAT_EQ(300, page_height);
1062
1063 using pdfium::RectanglesChecksum;
1064 ScopedFPDFBitmap bitmap = RenderLoadedPage(page);
1065 CompareBitmap(bitmap.get(), page_width, page_height, RectanglesChecksum());
1066
1067 FS_RECTF page_rect{0, 0, page_width, page_height};
1068
1069 // Try rendering with an identity matrix. The output should be the same as
1070 // the RenderLoadedPage() output.
1071 FS_MATRIX identity_matrix{1, 0, 0, 1, 0, 0};
1072 TestRenderPageBitmapWithMatrix(page, page_width, page_height, identity_matrix,
1073 page_rect, RectanglesChecksum());
1074
1075 // Again render with an identity matrix but with a smaller clipping rect.
1076 FS_RECTF middle_of_page_rect{page_width / 4, page_height / 4,
1077 page_width * 3 / 4, page_height * 3 / 4};
1078 TestRenderPageBitmapWithMatrix(page, page_width, page_height, identity_matrix,
1079 middle_of_page_rect, clipped_checksum);
1080
1081 // Now render again with the image scaled smaller.
1082 FS_MATRIX half_scale_matrix{0.5, 0, 0, 0.5, 0, 0};
1083 TestRenderPageBitmapWithMatrix(page, page_width, page_height,
1084 half_scale_matrix, page_rect,
1085 top_left_quarter_checksum);
1086
1087 // Now render again with the image scaled larger horizontally (the right half
1088 // will be clipped).
1089 FS_MATRIX stretch_x_matrix{2, 0, 0, 1, 0, 0};
1090 TestRenderPageBitmapWithMatrix(page, page_width, page_height,
1091 stretch_x_matrix, page_rect,
1092 kHoriStretchedChecksum);
1093
1094 // Try a 90 degree rotation clockwise but with the same bitmap size, so part
1095 // will be clipped.
1096 FS_MATRIX rotate_90_matrix{0, 1, -1, 0, page_width, 0};
1097 TestRenderPageBitmapWithMatrix(page, page_width, page_height,
1098 rotate_90_matrix, page_rect,
1099 rotated_90_clockwise_checksum);
1100
1101 // 180 degree rotation clockwise.
1102 FS_MATRIX rotate_180_matrix{-1, 0, 0, -1, page_width, page_height};
1103 TestRenderPageBitmapWithMatrix(page, page_width, page_height,
1104 rotate_180_matrix, page_rect,
1105 rotated_180_clockwise_checksum);
1106
1107 // 270 degree rotation clockwise.
1108 FS_MATRIX rotate_270_matrix{0, -1, 1, 0, 0, page_width};
1109 TestRenderPageBitmapWithMatrix(page, page_width, page_height,
1110 rotate_270_matrix, page_rect,
1111 rotated_270_clockwise_checksum);
1112
1113 // Mirror horizontally.
1114 FS_MATRIX mirror_hori_matrix{-1, 0, 0, 1, page_width, 0};
1115 TestRenderPageBitmapWithMatrix(page, page_width, page_height,
1116 mirror_hori_matrix, page_rect,
1117 mirror_hori_checksum);
1118
1119 // Mirror vertically.
1120 FS_MATRIX mirror_vert_matrix{1, 0, 0, -1, 0, page_height};
1121 TestRenderPageBitmapWithMatrix(page, page_width, page_height,
1122 mirror_vert_matrix, page_rect,
1123 mirror_vert_checksum);
1124
1125 // Tests rendering to a larger bitmap
1126 const float bitmap_width = page_width * 2;
1127 const float bitmap_height = page_height * 2;
1128
1129 // Render using an identity matrix and the whole bitmap area as clipping rect.
1130 FS_RECTF bitmap_rect{0, 0, bitmap_width, bitmap_height};
1131 TestRenderPageBitmapWithMatrix(page, bitmap_width, bitmap_height,
1132 identity_matrix, bitmap_rect,
1133 larger_top_left_quarter_checksum);
1134
1135 // Render using a scaling matrix to fill the larger bitmap.
1136 FS_MATRIX double_scale_matrix{2, 0, 0, 2, 0, 0};
1137 TestRenderPageBitmapWithMatrix(page, bitmap_width, bitmap_height,
1138 double_scale_matrix, bitmap_rect,
1139 kLargerChecksum);
1140
1141 // Render the larger image again but with clipping.
1142 FS_RECTF middle_of_bitmap_rect{bitmap_width / 4, bitmap_height / 4,
1143 bitmap_width * 3 / 4, bitmap_height * 3 / 4};
1144 TestRenderPageBitmapWithMatrix(page, bitmap_width, bitmap_height,
1145 double_scale_matrix, middle_of_bitmap_rect,
1146 kLargerClippedChecksum);
1147
1148 // On the larger bitmap, try a 90 degree rotation but with the same bitmap
1149 // size, so part will be clipped.
1150 FS_MATRIX rotate_90_scale_2_matrix{0, 2, -2, 0, bitmap_width, 0};
1151 TestRenderPageBitmapWithMatrix(page, bitmap_width, bitmap_height,
1152 rotate_90_scale_2_matrix, bitmap_rect,
1153 kLargerRotatedChecksum);
1154
1155 // On the larger bitmap, apply 90 degree rotation to a bitmap with the
1156 // appropriate dimensions.
1157 const float landscape_bitmap_width = bitmap_height;
1158 const float landscape_bitmap_height = bitmap_width;
1159 FS_RECTF landscape_bitmap_rect{0, 0, landscape_bitmap_width,
1160 landscape_bitmap_height};
1161 FS_MATRIX landscape_rotate_90_scale_2_matrix{
1162 0, 2, -2, 0, landscape_bitmap_width, 0};
1163 TestRenderPageBitmapWithMatrix(
1164 page, landscape_bitmap_width, landscape_bitmap_height,
1165 landscape_rotate_90_scale_2_matrix, landscape_bitmap_rect,
1166 kLargerRotatedLandscapeChecksum);
1167
1168 // On the larger bitmap, apply 45 degree rotation to a bitmap with the
1169 // appropriate dimensions.
1170 const float sqrt2 = 1.41421356f;
1171 const float diagonal_bitmap_size =
1172 ceil((bitmap_width + bitmap_height) / sqrt2);
1173 FS_RECTF diagonal_bitmap_rect{0, 0, diagonal_bitmap_size,
1174 diagonal_bitmap_size};
1175 FS_MATRIX rotate_45_scale_2_matrix{
1176 sqrt2, sqrt2, -sqrt2, sqrt2, bitmap_height / sqrt2, 0};
1177 TestRenderPageBitmapWithMatrix(page, diagonal_bitmap_size,
1178 diagonal_bitmap_size, rotate_45_scale_2_matrix,
1179 diagonal_bitmap_rect,
1180 larger_rotated_diagonal_checksum);
1181
1182 // Render the (2, 1) tile of the page (third column, second row) when the page
1183 // is divided in 50x50 pixel tiles. The tile is scaled by a factor of 7.
1184 const float scale = 7.0;
1185 const int tile_size = 50;
1186 const int tile_x = 2;
1187 const int tile_y = 1;
1188 float tile_bitmap_size = scale * tile_size;
1189 FS_RECTF tile_bitmap_rect{0, 0, tile_bitmap_size, tile_bitmap_size};
1190 FS_MATRIX tile_2_1_matrix{scale,
1191 0,
1192 0,
1193 scale,
1194 -tile_x * tile_bitmap_size,
1195 -tile_y * tile_bitmap_size};
1196 TestRenderPageBitmapWithMatrix(page, tile_bitmap_size, tile_bitmap_size,
1197 tile_2_1_matrix, tile_bitmap_rect,
1198 tile_checksum);
1199
1200 UnloadPage(page);
1201}
1202
1204 ASSERT_TRUE(OpenDocument("rectangles.pdf"));
1205
1206 FS_SIZEF size;
1207 EXPECT_FALSE(FPDF_GetPageSizeByIndexF(nullptr, 0, &size));
1208 EXPECT_FALSE(FPDF_GetPageSizeByIndexF(document(), 0, nullptr));
1209
1210 // Page -1 doesn't exist.
1211 EXPECT_FALSE(FPDF_GetPageSizeByIndexF(document(), -1, &size));
1212
1213 // Page 1 doesn't exist.
1214 EXPECT_FALSE(FPDF_GetPageSizeByIndexF(document(), 1, &size));
1215
1216 // Page 0 exists.
1217 EXPECT_TRUE(FPDF_GetPageSizeByIndexF(document(), 0, &size));
1218 EXPECT_FLOAT_EQ(200.0f, size.width);
1219 EXPECT_FLOAT_EQ(300.0f, size.height);
1220
1221 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document());
1222#ifdef PDF_ENABLE_XFA
1223 // TODO(tsepez): XFA must obtain this size without parsing.
1224 EXPECT_EQ(1u, pDoc->GetParsedPageCountForTesting());
1225#else // PDF_ENABLE_XFA
1226 EXPECT_EQ(0u, pDoc->GetParsedPageCountForTesting());
1227#endif // PDF_ENABLE_XFA
1228
1229 // Double-check against values from when page is actually parsed.
1230 FPDF_PAGE page = LoadPage(0);
1231 ASSERT_TRUE(page);
1232 EXPECT_FLOAT_EQ(size.width, FPDF_GetPageWidthF(page));
1233 EXPECT_FLOAT_EQ(size.height, FPDF_GetPageHeightF(page));
1234 EXPECT_EQ(1u, pDoc->GetParsedPageCountForTesting());
1235 UnloadPage(page);
1236}
1237
1239 ASSERT_TRUE(OpenDocument("rectangles.pdf"));
1240
1241 double width = 0;
1242 double height = 0;
1243
1244 EXPECT_FALSE(FPDF_GetPageSizeByIndex(nullptr, 0, &width, &height));
1245 EXPECT_FALSE(FPDF_GetPageSizeByIndex(document(), 0, nullptr, &height));
1246 EXPECT_FALSE(FPDF_GetPageSizeByIndex(document(), 0, &width, nullptr));
1247
1248 // Page -1 doesn't exist.
1249 EXPECT_FALSE(FPDF_GetPageSizeByIndex(document(), -1, &width, &height));
1250
1251 // Page 1 doesn't exist.
1252 EXPECT_FALSE(FPDF_GetPageSizeByIndex(document(), 1, &width, &height));
1253
1254 // Page 0 exists.
1255 EXPECT_TRUE(FPDF_GetPageSizeByIndex(document(), 0, &width, &height));
1256 EXPECT_EQ(200.0, width);
1257 EXPECT_EQ(300.0, height);
1258
1259 CPDF_Document* pDoc = CPDFDocumentFromFPDFDocument(document());
1260#ifdef PDF_ENABLE_XFA
1261 // TODO(tsepez): XFA must obtain this size without parsing.
1262 EXPECT_EQ(1u, pDoc->GetParsedPageCountForTesting());
1263#else // PDF_ENABLE_XFA
1264 EXPECT_EQ(0u, pDoc->GetParsedPageCountForTesting());
1265#endif // PDF_ENABLE_XFA
1266
1267 // Double-check against values from when page is actually parsed.
1268 FPDF_PAGE page = LoadPage(0);
1269 ASSERT_TRUE(page);
1270 EXPECT_EQ(width, FPDF_GetPageWidth(page));
1271 EXPECT_EQ(height, FPDF_GetPageHeight(page));
1272 EXPECT_EQ(1u, pDoc->GetParsedPageCountForTesting());
1273 UnloadPage(page);
1274}
1275
1277 static constexpr struct {
1278 int index;
1279 const char* name;
1280 size_t content_length;
1281 const char* content_checksum;
1282 } kTestCases[]{
1283 {0, "preamble", 124u, "71be364e53292596412242bfcdb46eab"},
1284 {1, "config", 642u, "bcd1ca1d420ee31a561273a54a06435f"},
1285 {2, "template", 541u, "0f48cb2fa1bb9cbf9eee802d66e81bf4"},
1286 {3, "localeSet", 3455u, "bb1f253d3e5c719ac0da87d055bc164e"},
1287 {4, "postamble", 11u, "6b79e25da35d86634ea27c38f64cf243"},
1288 };
1289
1290 ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
1291 ASSERT_EQ(static_cast<int>(std::size(kTestCases)),
1292 FPDF_GetXFAPacketCount(document()));
1293
1294 for (const auto& testcase : kTestCases) {
1295 char name_buffer[20] = {};
1296 ASSERT_EQ(strlen(testcase.name) + 1,
1297 FPDF_GetXFAPacketName(document(), testcase.index, nullptr, 0));
1298 EXPECT_EQ(strlen(testcase.name) + 1,
1299 FPDF_GetXFAPacketName(document(), testcase.index, name_buffer,
1300 sizeof(name_buffer)));
1301 EXPECT_STREQ(testcase.name, name_buffer);
1302
1303 unsigned long buflen;
1304 ASSERT_TRUE(FPDF_GetXFAPacketContent(document(), testcase.index, nullptr, 0,
1305 &buflen));
1306 ASSERT_EQ(testcase.content_length, buflen);
1307 std::vector<uint8_t> data_buffer(buflen);
1308 EXPECT_TRUE(FPDF_GetXFAPacketContent(document(), testcase.index,
1309 data_buffer.data(), data_buffer.size(),
1310 &buflen));
1311 EXPECT_EQ(testcase.content_length, buflen);
1312 EXPECT_EQ(testcase.content_checksum, GenerateMD5Base16(data_buffer));
1313 }
1314
1315 // Test bad parameters.
1316 EXPECT_EQ(-1, FPDF_GetXFAPacketCount(nullptr));
1317
1318 EXPECT_EQ(0u, FPDF_GetXFAPacketName(nullptr, 0, nullptr, 0));
1319 EXPECT_EQ(0u, FPDF_GetXFAPacketName(document(), -1, nullptr, 0));
1320 EXPECT_EQ(
1321 0u, FPDF_GetXFAPacketName(document(), std::size(kTestCases), nullptr, 0));
1322
1323 unsigned long buflen = 123;
1324 EXPECT_FALSE(FPDF_GetXFAPacketContent(nullptr, 0, nullptr, 0, &buflen));
1325 EXPECT_EQ(123u, buflen);
1326 EXPECT_FALSE(FPDF_GetXFAPacketContent(document(), -1, nullptr, 0, &buflen));
1327 EXPECT_EQ(123u, buflen);
1328 EXPECT_FALSE(FPDF_GetXFAPacketContent(document(), std::size(kTestCases),
1329 nullptr, 0, &buflen));
1330 EXPECT_EQ(123u, buflen);
1331 EXPECT_FALSE(FPDF_GetXFAPacketContent(document(), 0, nullptr, 0, nullptr));
1332}
1333
1335 ASSERT_TRUE(OpenDocument("bug_1265.pdf"));
1336
1337 ASSERT_EQ(1, FPDF_GetXFAPacketCount(document()));
1338
1339 char name_buffer[20] = {};
1340 ASSERT_EQ(1u, FPDF_GetXFAPacketName(document(), 0, nullptr, 0));
1341 EXPECT_EQ(1u, FPDF_GetXFAPacketName(document(), 0, name_buffer,
1342 sizeof(name_buffer)));
1343 EXPECT_STREQ("", name_buffer);
1344
1345 unsigned long buflen;
1346 ASSERT_TRUE(FPDF_GetXFAPacketContent(document(), 0, nullptr, 0, &buflen));
1347 ASSERT_EQ(121u, buflen);
1348 std::vector<uint8_t> data_buffer(buflen);
1349 EXPECT_TRUE(FPDF_GetXFAPacketContent(document(), 0, data_buffer.data(),
1350 data_buffer.size(), &buflen));
1351 EXPECT_EQ(121u, buflen);
1352 EXPECT_EQ("8f912eaa1e66c9341cb3032ede71e147", GenerateMD5Base16(data_buffer));
1353}
1354
1356 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
1357
1358 EXPECT_EQ(0, FPDF_GetXFAPacketCount(document()));
1359}
1360
1362 ASSERT_TRUE(OpenDocument("text_form.pdf"));
1363
1364 EXPECT_EQ(0, FPDF_GetXFAPacketCount(document()));
1365}
1366
1367class RecordUnsupportedErrorDelegate final : public EmbedderTest::Delegate {
1368 public:
1370 ~RecordUnsupportedErrorDelegate() override = default;
1371
1372 void UnsupportedHandler(int type) override { type_ = type; }
1373
1374 int type_ = -1;
1375};
1376
1378 RecordUnsupportedErrorDelegate delegate;
1379 SetDelegate(&delegate);
1380 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
1381 EXPECT_EQ(delegate.type_, -1);
1382 SetDelegate(nullptr);
1383}
1384
1386 RecordUnsupportedErrorDelegate delegate;
1387 SetDelegate(&delegate);
1388 ASSERT_TRUE(OpenDocument("unsupported_feature.pdf"));
1389 EXPECT_EQ(FPDF_UNSP_DOC_PORTABLECOLLECTION, delegate.type_);
1390 SetDelegate(nullptr);
1391}
1392
1394 std::string file_path =
1395 PathService::GetTestFilePath("unsupported_feature.pdf");
1396 ASSERT_FALSE(file_path.empty());
1397
1398 RecordUnsupportedErrorDelegate delegate;
1399 SetDelegate(&delegate);
1400 {
1401 ScopedFPDFDocument doc(FPDF_LoadDocument(file_path.c_str(), ""));
1402 EXPECT_TRUE(doc);
1403 EXPECT_EQ(FPDF_UNSP_DOC_PORTABLECOLLECTION, delegate.type_);
1404 }
1405 SetDelegate(nullptr);
1406}
1407
1409 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
1410 EXPECT_TRUE(FPDF_DocumentHasValidCrossReferenceTable(document()));
1411}
1412
1414 EXPECT_FALSE(FPDF_DocumentHasValidCrossReferenceTable(nullptr));
1415
1416 ASSERT_TRUE(OpenDocument("bug_664284.pdf"));
1417 EXPECT_FALSE(FPDF_DocumentHasValidCrossReferenceTable(document()));
1418}
1419
1420// Related to https://crbug.com/pdfium/1197
1422 ASSERT_TRUE(OpenDocument("empty_xref.pdf"));
1423 EXPECT_TRUE(FPDF_DocumentHasValidCrossReferenceTable(document()));
1424
1425 std::string file_path = PathService::GetTestFilePath("empty_xref.pdf");
1426 ASSERT_FALSE(file_path.empty());
1427 {
1428 ScopedFPDFDocument doc(FPDF_LoadDocument(file_path.c_str(), ""));
1429 ASSERT_TRUE(doc);
1430 EXPECT_TRUE(FPDF_DocumentHasValidCrossReferenceTable(doc.get()));
1431 }
1432 {
1433 std::vector<uint8_t> file_contents = GetFileContents(file_path.c_str());
1434 ASSERT_FALSE(file_contents.empty());
1435 ScopedFPDFDocument doc(
1436 FPDF_LoadMemDocument(file_contents.data(), file_contents.size(), ""));
1437 ASSERT_TRUE(doc);
1438 EXPECT_TRUE(FPDF_DocumentHasValidCrossReferenceTable(doc.get()));
1439 }
1440}
1441
1443 // For Skia, since the font used in bug_664284.pdf is not a CID font,
1444 // ShouldDrawDeviceText() will always return true. Therefore
1445 // FPDF_NO_NATIVETEXT and the font widths defined in the PDF determines
1446 // whether to go through the rendering path in
1447 // CFX_SkiaDeviceDriver::DrawDeviceText(). In this case, it returns false and
1448 // affects the rendering results across all platforms.
1449
1450 // For AGG, since CFX_AggDeviceDriver::DrawDeviceText() always returns false,
1451 // FPDF_NO_NATIVETEXT won't affect device-specific rendering path and it will
1452 // only disable native text support on macOS. Therefore Windows and Linux
1453 // rendering results remain the same as rendering with no flags, while the
1454 // macOS rendering result doesn't.
1455
1456 const char* original_checksum = []() {
1457 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
1458#if BUILDFLAG(IS_WIN)
1459 return "1c5d8217aca4f6fa86a8ed192f34b210";
1460#elif BUILDFLAG(IS_APPLE)
1461 return "b7ac2ca2b934f4e213ab4ba36c5f8ffd";
1462#else
1463 return "29cb8045c21cfa2c920fdf43de70efd8";
1464#endif
1465 }
1466#if BUILDFLAG(IS_APPLE)
1467 return "0e339d606aafb63077f49e238dc27cb0";
1468#else
1469 return "288502887ffc63291f35a0573b944375";
1470#endif
1471 }();
1472 static const char kNoNativeTextChecksum[] =
1473 "288502887ffc63291f35a0573b944375";
1474 ASSERT_TRUE(OpenDocument("bug_664284.pdf"));
1475 FPDF_PAGE page = LoadPage(0);
1476 ASSERT_TRUE(page);
1477
1478 TestRenderPageBitmapWithFlags(page, 0, original_checksum);
1479 TestRenderPageBitmapWithFlags(page, FPDF_NO_NATIVETEXT,
1480 kNoNativeTextChecksum);
1481
1482 UnloadPage(page);
1483}
1484
1486 const char* annotation_checksum = []() {
1487 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
1488 return "eaece6b8041c0cb9b33398e5b6d5ddda";
1489 }
1490 return "c108ba6e0a9743652f12e4bc223f9b32";
1491 }();
1492 static const char kPrintingChecksum[] = "3e235b9f88f652f2b97b1fc393924849";
1493 ASSERT_TRUE(OpenDocument("bug_1658.pdf"));
1494 FPDF_PAGE page = LoadPage(0);
1495 ASSERT_TRUE(page);
1496
1497 // A yellow highlight is rendered with `FPDF_ANNOT` flag.
1498 TestRenderPageBitmapWithFlags(page, FPDF_ANNOT, annotation_checksum);
1499
1500 // After adding `FPDF_PRINTING` flag, the yellow highlight is not rendered.
1501 TestRenderPageBitmapWithFlags(page, FPDF_PRINTING | FPDF_ANNOT,
1502 kPrintingChecksum);
1503 UnloadPage(page);
1504}
1505
1506// TODO(crbug.com/pdfium/1955): Remove this test once pixel tests can pass with
1507// `reverse-byte-order` option.
1509 // When rendering with `FPDF_REVERSE_BYTE_ORDER` flag, the blue and red
1510 // channels should be reversed.
1511 ASSERT_TRUE(OpenDocument("bug_1396264.pdf"));
1512 ScopedFPDFPage page(FPDF_LoadPage(document(), 0));
1513 ASSERT_TRUE(page);
1514
1515 TestRenderPageBitmapWithFlags(page.get(), 0,
1516 "81e7f4498090977c848a21b5c6510d3a");
1517 TestRenderPageBitmapWithFlags(page.get(), FPDF_REVERSE_BYTE_ORDER,
1518 "505ba6d1c7f4044c11c91873452a8bde");
1519}
1520
1522 static const char kNormalChecksum[] = "4bcd56cae1ca2622403e8af07242e71a";
1523 static const char kGrayscaleChecksum[] = "fe45ad56efe868ba82285fa5ffedc0cb";
1524
1525 ASSERT_TRUE(OpenDocument("jpx_lzw.pdf"));
1526 FPDF_PAGE page = LoadPage(0);
1527 ASSERT_TRUE(page);
1528
1529 TestRenderPageBitmapWithFlags(page, 0, kNormalChecksum);
1530 TestRenderPageBitmapWithFlags(page, FPDF_ANNOT, kNormalChecksum);
1531 TestRenderPageBitmapWithFlags(page, FPDF_LCD_TEXT, kNormalChecksum);
1532 TestRenderPageBitmapWithFlags(page, FPDF_NO_NATIVETEXT, kNormalChecksum);
1533 TestRenderPageBitmapWithFlags(page, FPDF_GRAYSCALE, kGrayscaleChecksum);
1534 TestRenderPageBitmapWithFlags(page, FPDF_RENDER_LIMITEDIMAGECACHE,
1535 kNormalChecksum);
1536 TestRenderPageBitmapWithFlags(page, FPDF_RENDER_FORCEHALFTONE,
1537 kNormalChecksum);
1538 TestRenderPageBitmapWithFlags(page, FPDF_PRINTING, kNormalChecksum);
1539 TestRenderPageBitmapWithFlags(page, FPDF_RENDER_NO_SMOOTHTEXT,
1540 kNormalChecksum);
1541 TestRenderPageBitmapWithFlags(page, FPDF_RENDER_NO_SMOOTHIMAGE,
1542 kNormalChecksum);
1543 TestRenderPageBitmapWithFlags(page, FPDF_RENDER_NO_SMOOTHPATH,
1544 kNormalChecksum);
1545
1546 UnloadPage(page);
1547}
1548
1550 const char* grayscale_checksum = []() {
1551 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
1552 return "b596ac8bbe64e7bff31888ab05e4dcf4";
1553 }
1554 return "7b553f1052069a9c61237a05db0955d6";
1555 }();
1556 const char* no_smoothpath_checksum = []() {
1557 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
1558 return "4d71ed53d9f6e6a761876ebb4ff23e19";
1559 }
1560 return "ff6e5c509d1f6984bcdfd18b26a4203a";
1561 }();
1562
1563 ASSERT_TRUE(OpenDocument("many_rectangles.pdf"));
1564 FPDF_PAGE page = LoadPage(0);
1565 ASSERT_TRUE(page);
1566
1567 TestRenderPageBitmapWithFlags(page, 0, ManyRectanglesChecksum());
1568 TestRenderPageBitmapWithFlags(page, FPDF_ANNOT, ManyRectanglesChecksum());
1569 TestRenderPageBitmapWithFlags(page, FPDF_LCD_TEXT, ManyRectanglesChecksum());
1570 TestRenderPageBitmapWithFlags(page, FPDF_NO_NATIVETEXT,
1572 TestRenderPageBitmapWithFlags(page, FPDF_GRAYSCALE, grayscale_checksum);
1573 TestRenderPageBitmapWithFlags(page, FPDF_RENDER_LIMITEDIMAGECACHE,
1575 TestRenderPageBitmapWithFlags(page, FPDF_RENDER_FORCEHALFTONE,
1577 TestRenderPageBitmapWithFlags(page, FPDF_PRINTING, ManyRectanglesChecksum());
1578 TestRenderPageBitmapWithFlags(page, FPDF_RENDER_NO_SMOOTHTEXT,
1580 TestRenderPageBitmapWithFlags(page, FPDF_RENDER_NO_SMOOTHIMAGE,
1582 TestRenderPageBitmapWithFlags(page, FPDF_RENDER_NO_SMOOTHPATH,
1583 no_smoothpath_checksum);
1584
1585 UnloadPage(page);
1586}
1587
1589 ASSERT_TRUE(OpenDocument("many_rectangles.pdf"));
1590 FPDF_PAGE page = LoadPage(0);
1591 ASSERT_TRUE(page);
1592
1593 const char* bgr_checksum = []() {
1594 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
1595 return "4d52e5cc1d4a8067bf918b85b232fff0";
1596 }
1597 return "ab6312e04c0d3f4e46fb302a45173d05";
1598 }();
1599 static constexpr int kBgrStride = 600; // Width of 200 * 24 bits per pixel.
1600 TestRenderPageBitmapWithInternalMemory(page, FPDFBitmap_BGR, bgr_checksum);
1601 TestRenderPageBitmapWithInternalMemoryAndStride(page, FPDFBitmap_BGR,
1602 kBgrStride, bgr_checksum);
1603 TestRenderPageBitmapWithExternalMemory(page, FPDFBitmap_BGR, bgr_checksum);
1604 TestRenderPageBitmapWithExternalMemoryAndNoStride(page, FPDFBitmap_BGR,
1605 bgr_checksum);
1606
1607 const char* gray_checksum = []() {
1608 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
1609 return "3dfe1fc3889123d68e1748fefac65e72";
1610 }
1611 return "b561c11edc44dc3972125a9b8744fa2f";
1612 }();
1613
1614 TestRenderPageBitmapWithInternalMemory(page, FPDFBitmap_Gray, gray_checksum);
1615 static constexpr int kGrayStride = 200; // Width of 200 * 8 bits per pixel.
1616 TestRenderPageBitmapWithInternalMemoryAndStride(page, FPDFBitmap_Gray,
1617 kGrayStride, gray_checksum);
1618 TestRenderPageBitmapWithExternalMemory(page, FPDFBitmap_Gray, gray_checksum);
1619 TestRenderPageBitmapWithExternalMemoryAndNoStride(page, FPDFBitmap_Gray,
1620 gray_checksum);
1621
1622 static constexpr int kBgrxStride = 800; // Width of 200 * 32 bits per pixel.
1623 TestRenderPageBitmapWithInternalMemory(page, FPDFBitmap_BGRx,
1625 TestRenderPageBitmapWithInternalMemoryAndStride(
1626 page, FPDFBitmap_BGRx, kBgrxStride, ManyRectanglesChecksum());
1627 TestRenderPageBitmapWithExternalMemory(page, FPDFBitmap_BGRx,
1629 TestRenderPageBitmapWithExternalMemoryAndNoStride(page, FPDFBitmap_BGRx,
1631
1632 TestRenderPageBitmapWithInternalMemory(page, FPDFBitmap_BGRA,
1634 TestRenderPageBitmapWithInternalMemoryAndStride(
1635 page, FPDFBitmap_BGRA, kBgrxStride, ManyRectanglesChecksum());
1636 TestRenderPageBitmapWithExternalMemory(page, FPDFBitmap_BGRA,
1638 TestRenderPageBitmapWithExternalMemoryAndNoStride(page, FPDFBitmap_BGRA,
1640
1641 UnloadPage(page);
1642}
1643
1645 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
1646 FPDF_PAGE page = LoadPage(0);
1647 ASSERT_TRUE(page);
1648
1649 using pdfium::HelloWorldChecksum;
1650 TestRenderPageBitmapWithFlags(page, 0, HelloWorldChecksum());
1651 TestRenderPageBitmapWithFlags(page, FPDF_ANNOT, HelloWorldChecksum());
1652 TestRenderPageBitmapWithFlags(page, FPDF_GRAYSCALE, HelloWorldChecksum());
1653 TestRenderPageBitmapWithFlags(page, FPDF_RENDER_LIMITEDIMAGECACHE,
1655 TestRenderPageBitmapWithFlags(page, FPDF_RENDER_FORCEHALFTONE,
1657 TestRenderPageBitmapWithFlags(page, FPDF_PRINTING, HelloWorldChecksum());
1658 TestRenderPageBitmapWithFlags(page, FPDF_RENDER_NO_SMOOTHIMAGE,
1660 TestRenderPageBitmapWithFlags(page, FPDF_RENDER_NO_SMOOTHPATH,
1662
1663 const char* lcd_text_checksum = []() {
1664 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
1665#if BUILDFLAG(IS_WIN)
1666 return "496d1f907349b153c5ecdc87c8073c7b";
1667#elif BUILDFLAG(IS_APPLE)
1668 return "b110924c4af6e87232249ea2a564f0e4";
1669#else
1670 return "d1decde2de1c07b5274cc8cb44f92427";
1671#endif
1672 }
1673#if BUILDFLAG(IS_APPLE)
1674 return "6eef7237f7591f07616e238422086737";
1675#else
1676 return "09152e25e51fa8ca31fc28d0937bf477";
1677#endif // BUILDFLAG(IS_APPLE)
1678 }();
1679 const char* no_smoothtext_checksum = []() {
1680 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
1681#if BUILDFLAG(IS_WIN)
1682 return "04dcf7d221437081034ca1152c717a8a";
1683#elif BUILDFLAG(IS_APPLE)
1684 return "8c99ca392ecff724da0d04b17453a45a";
1685#else
1686 return "cd5bbe9407c3fcc85d365172a9a55abd";
1687#endif
1688 }
1689#if BUILDFLAG(IS_APPLE)
1690 return "6eef7237f7591f07616e238422086737";
1691#else
1692 return "6dec98c848028fa4be3ad38d6782e304";
1693#endif
1694 }();
1695
1696 TestRenderPageBitmapWithFlags(page, FPDF_LCD_TEXT, lcd_text_checksum);
1697 TestRenderPageBitmapWithFlags(page, FPDF_RENDER_NO_SMOOTHTEXT,
1698 no_smoothtext_checksum);
1699
1700 // For text rendering, When anti-aliasing is disabled, LCD Optimization flag
1701 // will be ignored.
1702 TestRenderPageBitmapWithFlags(page, FPDF_LCD_TEXT | FPDF_RENDER_NO_SMOOTHTEXT,
1703 no_smoothtext_checksum);
1704
1705 UnloadPage(page);
1706}
1707
1708// Deliberately disabled because this test case renders a large bitmap, which is
1709// very slow for debug builds.
1710#if defined(NDEBUG)
1711#define MAYBE_LargeImageDoesNotRenderBlank LargeImageDoesNotRenderBlank
1712#else
1713#define MAYBE_LargeImageDoesNotRenderBlank DISABLED_LargeImageDoesNotRenderBlank
1714#endif
1716 static const char kChecksum[] = "a6056db6961f4e65c42ab2e246171fe1";
1717
1718 ASSERT_TRUE(OpenDocument("bug_1646.pdf"));
1719 FPDF_PAGE page = LoadPage(0);
1720 ASSERT_TRUE(page);
1721
1722 constexpr int kWidth = 40000;
1723 constexpr int kHeight = 100;
1724 TestRenderPageBitmapWithMatrix(page, kWidth, kHeight, {1000, 0, 0, 1, 0, 0},
1725 {0, 0, kWidth, kHeight}, kChecksum);
1726
1727 UnloadPage(page);
1728}
1729
1730#if BUILDFLAG(IS_WIN)
1731TEST_F(FPDFViewEmbedderTest, FPDFRenderPageEmf) {
1732 ASSERT_TRUE(OpenDocument("rectangles.pdf"));
1733 FPDF_PAGE page = LoadPage(0);
1734 ASSERT_TRUE(page);
1735
1736 std::vector<uint8_t> emf_normal = RenderPageWithFlagsToEmf(page, 0);
1737 EXPECT_EQ(3772u, emf_normal.size());
1738
1739 // FPDF_REVERSE_BYTE_ORDER is ignored since EMFs are always BGR.
1740 std::vector<uint8_t> emf_reverse_byte_order =
1741 RenderPageWithFlagsToEmf(page, FPDF_REVERSE_BYTE_ORDER);
1742 EXPECT_EQ(emf_normal, emf_reverse_byte_order);
1743
1744 UnloadPage(page);
1745}
1746
1747class PostScriptRenderEmbedderTestBase : public FPDFViewEmbedderTest {
1748 protected:
1749 ~PostScriptRenderEmbedderTestBase() override = default;
1750
1751 // FPDFViewEmbedderTest:
1752 void TearDown() override {
1753 FPDF_SetPrintMode(FPDF_PRINTMODE_EMF);
1754 FPDFViewEmbedderTest::TearDown();
1755 }
1756};
1757
1758class PostScriptLevel2EmbedderTest : public PostScriptRenderEmbedderTestBase {
1759 public:
1760 PostScriptLevel2EmbedderTest() = default;
1761 ~PostScriptLevel2EmbedderTest() override = default;
1762
1763 protected:
1764 // FPDFViewEmbedderTest:
1765 void SetUp() override {
1766 FPDFViewEmbedderTest::SetUp();
1767 FPDF_SetPrintMode(FPDF_PRINTMODE_POSTSCRIPT2);
1768 }
1769};
1770
1771class PostScriptLevel3EmbedderTest : public PostScriptRenderEmbedderTestBase {
1772 public:
1773 PostScriptLevel3EmbedderTest() = default;
1774 ~PostScriptLevel3EmbedderTest() override = default;
1775
1776 protected:
1777 // FPDFViewEmbedderTest:
1778 void SetUp() override {
1779 FPDFViewEmbedderTest::SetUp();
1780 FPDF_SetPrintMode(FPDF_PRINTMODE_POSTSCRIPT3);
1781 }
1782};
1783
1784TEST_F(PostScriptLevel2EmbedderTest, Rectangles) {
1785 ASSERT_TRUE(OpenDocument("rectangles.pdf"));
1786 FPDF_PAGE page = LoadPage(0);
1787 ASSERT_TRUE(page);
1788
1789 std::vector<uint8_t> emf_normal = RenderPageWithFlagsToEmf(page, 0);
1790 std::string ps_data = GetPostScriptFromEmf(emf_normal);
1791 EXPECT_EQ(kExpectedRectanglePostScript, ps_data);
1792
1793 // FPDF_REVERSE_BYTE_ORDER is ignored since PostScript is not bitmap-based.
1794 std::vector<uint8_t> emf_reverse_byte_order =
1795 RenderPageWithFlagsToEmf(page, FPDF_REVERSE_BYTE_ORDER);
1796 EXPECT_EQ(emf_normal, emf_reverse_byte_order);
1797
1798 UnloadPage(page);
1799}
1800
1801TEST_F(PostScriptLevel3EmbedderTest, Rectangles) {
1802 ASSERT_TRUE(OpenDocument("rectangles.pdf"));
1803 FPDF_PAGE page = LoadPage(0);
1804 ASSERT_TRUE(page);
1805
1806 std::vector<uint8_t> emf_normal = RenderPageWithFlagsToEmf(page, 0);
1807 std::string ps_data = GetPostScriptFromEmf(emf_normal);
1808 EXPECT_EQ(kExpectedRectanglePostScript, ps_data);
1809
1810 // FPDF_REVERSE_BYTE_ORDER is ignored since PostScript is not bitmap-based.
1811 std::vector<uint8_t> emf_reverse_byte_order =
1812 RenderPageWithFlagsToEmf(page, FPDF_REVERSE_BYTE_ORDER);
1813 EXPECT_EQ(emf_normal, emf_reverse_byte_order);
1814
1815 UnloadPage(page);
1816}
1817
1818TEST_F(PostScriptLevel2EmbedderTest, Image) {
1819 const char kExpected[] =
1820 "\n"
1821 "save\n"
1822 "/im/initmatrix load def\n"
1823 "/n/newpath load def/m/moveto load def/l/lineto load def/c/curveto load "
1824 "def/h/closepath load def\n"
1825 "/f/fill load def/F/eofill load def/s/stroke load def/W/clip load "
1826 "def/W*/eoclip load def\n"
1827 "/rg/setrgbcolor load def/k/setcmykcolor load def\n"
1828 "/J/setlinecap load def/j/setlinejoin load def/w/setlinewidth load "
1829 "def/M/setmiterlimit load def/d/setdash load def\n"
1830 "/q/gsave load def/Q/grestore load def/iM/imagemask load def\n"
1831 "/Tj/show load def/Ff/findfont load def/Fs/scalefont load def/Sf/setfont "
1832 "load def\n"
1833 "/cm/concat load def/Cm/currentmatrix load def/mx/matrix load "
1834 "def/sm/setmatrix load def\n"
1835 "0 792 m 0 0 l 612 0 l 612 792 l 0 792 l h W n\n"
1836 "q\n"
1837 "0 792 m 0 0 l 612 0 l 612 792 l 0 792 l h W n\n"
1838 "q\n"
1839 "Q\n"
1840 "q\n"
1841 "281 106.7 m 331 106.7 l 331 56.7 l 281 56.7 l 281 106.7 l h W* n\n"
1842 "q\n"
1843 "[49.9 0 0 -50 281.1 106.6]cm 50 50 8[50 0 0 -50 0 "
1844 "50]currentfile/ASCII85Decode filter /DCTDecode filter false 3 "
1845 "colorimage\n"
1846 "s4IA0!\"_al8O`[\\!<<*#!!*'\"s4[N@!!ic5#6k>;#6tJ?#m^kH'FbHY$Odmc'+Yct)"
1847 "BU\"@)B9_>\r\n"
1848 ",VCGe+tOrY*%3`p/2/e81c-:%3B]>W4>&EH1B6)/"
1849 "6NIK\"#n.1M(_$ok1*IV\\1,:U?1,:U?1,:U?\r\n"
1850 "1,:U?1,:U?1,:U?1,:U?1,:U?1,:U?1,:U?1,:U?1,:U?1,AmF!\"fJ:1&s'3!?qLF&HMtG!"
1851 "WU(<\r\n"
1852 "*rl9A\"T\\W)!<E3$z!!!!\"!WrQ/\"pYD?$4HmP!4<@<!W`B*!X&T/"
1853 "\"U\"r.!!.KK!WrE*&Hrdj0gQ!W\r\n"
1854 ";.0\\RE>10ZOeE%*6F\"?A;UOtZ1LbBV#mqFa(`=5<-7:2j.Ps\"@2`NfY6UX@47n?3D;"
1855 "cHat='/U/\r\n"
1856 "@q9._B4u!oF*)PJGBeCZK7nr5LPUeEP*;,qQC!u,R\\HRQV5C/"
1857 "hWN*81['d?O\\@K2f_o0O6a2lBF\r\n"
1858 "daQ^rf%8R-g>V&OjQ5OekiqC&o(2MHp@n@XqZ\"J6*ru?D!<E3%!<E3%!<<*\"!!!!\"!"
1859 "WrQ/\"pYD?\r\n"
1860 "$4HmP!4<C=!W`?*\"9Sc3\"U\"r.!<RHF!<N?8\"9fr'\"qj4!#@VTc+u4]T'LIqUZ,$_"
1861 "k1K*]W@WKj'\r\n"
1862 "(*k`q-1Mcg)&ahL-n-W'2E*TU3^Z;(7Rp!@8lJ\\h<``C+>%;)SAnPdkC3+K>G'A1VH@gd&"
1863 "KnbA=\r\n"
1864 "M2II[Pa.Q$R$jD;USO``Vl6SpZEppG[^WcW]#)A'`Q#s>ai`&\\eCE.%f\\,!<j5f="
1865 "akNM0qo(2MH\r\n"
1866 "p@n@XqZ#7L$j-M1!YGMH!'^JZre`+s!fAD!!fAD!!fAD!!fAD!!fAD!!fAD!!fAD!!fAD!!"
1867 "fAD!\r\n"
1868 "!fAD!!fAD!!fAD!!fAD!!fAD!!fAD!&-(;~>\n"
1869 "Q\n"
1870 "Q\n"
1871 "q\n"
1872 "q\n"
1873 "Q\n"
1874 "Q\n"
1875 "Q\n"
1876 "Q\n"
1877 "\n"
1878 "restore\n";
1879
1880 ASSERT_TRUE(OpenDocument("tagged_alt_text.pdf"));
1881 FPDF_PAGE page = LoadPage(0);
1882 ASSERT_TRUE(page);
1883
1884 std::vector<uint8_t> emf = RenderPageWithFlagsToEmf(page, 0);
1885 std::string ps_data = GetPostScriptFromEmf(emf);
1886 EXPECT_EQ(kExpected, ps_data);
1887
1888 UnloadPage(page);
1889}
1890
1891TEST_F(PostScriptLevel3EmbedderTest, Image) {
1892 const char kExpected[] = R"(
1893save
1894/im/initmatrix load def
1895/n/newpath load def/m/moveto load def/l/lineto load def/c/curveto load def/h/closepath load def
1896/f/fill load def/F/eofill load def/s/stroke load def/W/clip load def/W*/eoclip load def
1897/rg/setrgbcolor load def/k/setcmykcolor load def
1898/J/setlinecap load def/j/setlinejoin load def/w/setlinewidth load def/M/setmiterlimit load def/d/setdash load def
1899/q/gsave load def/Q/grestore load def/iM/imagemask load def
1900/Tj/show load def/Ff/findfont load def/Fs/scalefont load def/Sf/setfont load def
1901/cm/concat load def/Cm/currentmatrix load def/mx/matrix load def/sm/setmatrix load def
19020 792 m 0 0 l 612 0 l 612 792 l 0 792 l h W n
1903q
19040 792 m 0 0 l 612 0 l 612 792 l 0 792 l h W n
1905q
1906Q
1907q
1908281 106.7 m 331 106.7 l 331 56.7 l 281 56.7 l 281 106.7 l h W* n
1909q
1910[49.9 0 0 -50 281.1 106.6]cm 50 50 8[50 0 0 -50 0 50]currentfile/ASCII85Decode filter /FlateDecode filter false 3 colorimage
1911Gb"0;0`_7S!5bE%:[N')TE"rlzGQSs[!!*~>
1912Q
1913Q
1914q
1915q
1916Q
1917Q
1918Q
1919Q
1920
1921restore
1922)";
1923
1924 ASSERT_TRUE(OpenDocument("tagged_alt_text.pdf"));
1925 FPDF_PAGE page = LoadPage(0);
1926 ASSERT_TRUE(page);
1927
1928 std::vector<uint8_t> emf = RenderPageWithFlagsToEmf(page, 0);
1929 std::string ps_data = GetPostScriptFromEmf(emf);
1930 EXPECT_EQ(kExpected, ps_data);
1931
1932 UnloadPage(page);
1933}
1934
1935TEST_F(FPDFViewEmbedderTest, ImageMask) {
1936 ASSERT_TRUE(OpenDocument("bug_674771.pdf"));
1937 FPDF_PAGE page = LoadPage(0);
1938 ASSERT_TRUE(page);
1939
1940 // Render the page with more efficient processing of image masks.
1941 FPDF_SetPrintMode(FPDF_PRINTMODE_EMF_IMAGE_MASKS);
1942 std::vector<uint8_t> emf_image_masks = RenderPageWithFlagsToEmf(page, 0);
1943
1944 // Render the page normally.
1945 FPDF_SetPrintMode(FPDF_PRINTMODE_EMF);
1946 std::vector<uint8_t> emf_normal = RenderPageWithFlagsToEmf(page, 0);
1947
1948 EXPECT_LT(emf_image_masks.size(), emf_normal.size());
1949
1950 UnloadPage(page);
1951}
1952#endif // BUILDFLAG(IS_WIN)
1953
1955 ASSERT_TRUE(OpenDocument("two_signatures.pdf"));
1956
1957 // FPDF_GetTrailerEnds() positive testing.
1958 unsigned long size = FPDF_GetTrailerEnds(document(), nullptr, 0);
1959 const std::vector<unsigned int> kExpectedEnds{633, 1703, 2781};
1960 ASSERT_EQ(kExpectedEnds.size(), size);
1961 std::vector<unsigned int> ends(size);
1962 ASSERT_EQ(size, FPDF_GetTrailerEnds(document(), ends.data(), size));
1963 ASSERT_EQ(kExpectedEnds, ends);
1964
1965 // FPDF_GetTrailerEnds() negative testing.
1966 ASSERT_EQ(0U, FPDF_GetTrailerEnds(nullptr, nullptr, 0));
1967
1968 ends.resize(2);
1969 ends[0] = 0;
1970 ends[1] = 1;
1971 size = FPDF_GetTrailerEnds(document(), ends.data(), ends.size());
1972 ASSERT_EQ(kExpectedEnds.size(), size);
1973 EXPECT_EQ(0U, ends[0]);
1974 EXPECT_EQ(1U, ends[1]);
1975}
1976
1978 // Single trailer, \n line ending at the trailer end.
1979 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
1980
1981 // FPDF_GetTrailerEnds() positive testing.
1982 unsigned long size = FPDF_GetTrailerEnds(document(), nullptr, 0);
1983 const std::vector<unsigned int> kExpectedEnds{840};
1984 ASSERT_EQ(kExpectedEnds.size(), size);
1985 std::vector<unsigned int> ends(size);
1986 ASSERT_EQ(size, FPDF_GetTrailerEnds(document(), ends.data(), size));
1987 ASSERT_EQ(kExpectedEnds, ends);
1988}
1989
1991 // Multiple trailers, \r\n line ending at the trailer ends.
1992 ASSERT_TRUE(OpenDocument("annotation_stamp_with_ap.pdf"));
1993
1994 // FPDF_GetTrailerEnds() positive testing.
1995 unsigned long size = FPDF_GetTrailerEnds(document(), nullptr, 0);
1996 const std::vector<unsigned int> kExpectedEnds{441, 7945, 101719};
1997 ASSERT_EQ(kExpectedEnds.size(), size);
1998 std::vector<unsigned int> ends(size);
1999 ASSERT_EQ(size, FPDF_GetTrailerEnds(document(), ends.data(), size));
2000 ASSERT_EQ(kExpectedEnds, ends);
2001}
2002
2004 // Set up linearized PDF.
2005 FileAccessForTesting file_acc("linearized.pdf");
2006 FakeFileAccess fake_acc(&file_acc);
2007 CreateAvail(fake_acc.GetFileAvail(), fake_acc.GetFileAccess());
2009
2010 // Multiple trailers, \r line ending at the trailer ends (no \n).
2011 SetDocumentFromAvail();
2012 ASSERT_TRUE(document());
2013
2014 // FPDF_GetTrailerEnds() positive testing.
2015 unsigned long size = FPDF_GetTrailerEnds(document(), nullptr, 0);
2016 const std::vector<unsigned int> kExpectedEnds{474, 11384};
2017 ASSERT_EQ(kExpectedEnds.size(), size);
2018 std::vector<unsigned int> ends(size);
2019 ASSERT_EQ(size, FPDF_GetTrailerEnds(document(), ends.data(), size));
2020 ASSERT_EQ(kExpectedEnds, ends);
2021}
2022
2024 // Whitespace between 'endstream'/'endobj' and the newline.
2025 ASSERT_TRUE(OpenDocument("trailer_end_trailing_space.pdf"));
2026
2027 unsigned long size = FPDF_GetTrailerEnds(document(), nullptr, 0);
2028 const std::vector<unsigned int> kExpectedEnds{1193};
2029 // Without the accompanying fix in place, this test would have failed, as the
2030 // size was 0, not 1, i.e. no trailer ends were found.
2031 ASSERT_EQ(kExpectedEnds.size(), size);
2032 std::vector<unsigned int> ends(size);
2033 ASSERT_EQ(size, FPDF_GetTrailerEnds(document(), ends.data(), size));
2034 EXPECT_EQ(kExpectedEnds, ends);
2035}
2036
2038 ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
2039
2040 FPDF_PAGE page = LoadPage(0);
2041 ASSERT_TRUE(page);
2042
2043 // Should always be blank, as we're not testing `FPDF_FFLDraw()` here.
2044 TestRenderPageBitmapWithFlags(page, 0, pdfium::kBlankPage612By792Checksum);
2045
2046 UnloadPage(page);
2047}
2048
2049#if defined(PDF_USE_SKIA)
2050TEST_F(FPDFViewEmbedderTest, RenderPageToSkp) {
2051 if (!CFX_DefaultRenderDevice::UseSkiaRenderer()) {
2052 GTEST_SKIP() << "FPDF_RenderPageSkp() only makes sense with Skia";
2053 }
2054
2055 ASSERT_TRUE(OpenDocument("rectangles.pdf"));
2056
2057 FPDF_PAGE page = LoadPage(0);
2058 ASSERT_TRUE(page);
2059
2060 TestRenderPageSkp(page, pdfium::RectanglesChecksum());
2061
2062 UnloadPage(page);
2063}
2064
2065TEST_F(FPDFViewEmbedderTest, RenderXfaPageToSkp) {
2066 if (!CFX_DefaultRenderDevice::UseSkiaRenderer()) {
2067 GTEST_SKIP() << "FPDF_RenderPageSkp() only makes sense with Skia";
2068 }
2069
2070 ASSERT_TRUE(OpenDocument("simple_xfa.pdf"));
2071
2072 FPDF_PAGE page = LoadPage(0);
2073 ASSERT_TRUE(page);
2074
2075 // Should always be blank, as we're not testing `FPDF_FFLRecord()` here.
2076 TestRenderPageSkp(page, pdfium::kBlankPage612By792Checksum);
2077
2078 UnloadPage(page);
2079}
2080
2081TEST_F(FPDFViewEmbedderTest, Bug2087) {
2082 FPDF_DestroyLibrary();
2083
2084 std::string agg_checksum;
2085 const FPDF_LIBRARY_CONFIG kAggConfig = {
2086 .version = 4,
2087 .m_pUserFontPaths = nullptr,
2088 .m_pIsolate = nullptr,
2089 .m_v8EmbedderSlot = 0,
2090 .m_pPlatform = nullptr,
2091 .m_RendererType = FPDF_RENDERERTYPE_AGG,
2092 };
2093 FPDF_InitLibraryWithConfig(&kAggConfig);
2094 {
2095 ASSERT_TRUE(OpenDocument("rectangles.pdf"));
2096 FPDF_PAGE page = LoadPage(0);
2097 ScopedFPDFBitmap bitmap = RenderPage(page);
2098 agg_checksum = HashBitmap(bitmap.get());
2099 UnloadPage(page);
2100 CloseDocument();
2101 }
2102 FPDF_DestroyLibrary();
2103
2104 std::string skia_checksum;
2105 const FPDF_LIBRARY_CONFIG kSkiaConfig = {
2106 .version = 2,
2107 .m_pUserFontPaths = nullptr,
2108 .m_pIsolate = nullptr,
2109 .m_v8EmbedderSlot = 0,
2110 };
2111 FPDF_InitLibraryWithConfig(&kSkiaConfig);
2112 {
2113 ASSERT_TRUE(OpenDocument("rectangles.pdf"));
2114 FPDF_PAGE page = LoadPage(0);
2115 ScopedFPDFBitmap bitmap = RenderPage(page);
2116 skia_checksum = HashBitmap(bitmap.get());
2117 UnloadPage(page);
2118 CloseDocument();
2119 }
2120
2121 EXPECT_NE(agg_checksum, skia_checksum);
2122
2123 EmbedderTestEnvironment::GetInstance()->TearDown();
2124 EmbedderTestEnvironment::GetInstance()->SetUp();
2125}
2126#endif // defined(PDF_USE_SKIA)
2127
2129 ASSERT_TRUE(OpenDocument("bug_1919.pdf"));
2130 FPDF_PAGE page = LoadPage(0);
2131 ASSERT_TRUE(page);
2132
2133 const char* checksum = []() {
2134#if BUILDFLAG(IS_WIN)
2135 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
2136 return "d97d0a9da6a5955f68a58a3f25466bd7";
2137 }
2138#elif !BUILDFLAG(IS_APPLE)
2139 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
2140 return "ceeb93d2bcdb586d62c95b33cadcd873";
2141 }
2142#endif
2143 return "5f99e2fa2bad09393d6428e105a83c96";
2144 }();
2145
2146 TestRenderPageBitmapWithFlags(page, FPDF_RENDER_NO_SMOOTHTEXT, checksum);
2147 UnloadPage(page);
2148}
2149
2151 ASSERT_TRUE(OpenDocument("bug_1302355.pdf"));
2152 ScopedEmbedderTestPage page = LoadScopedPage(0);
2153 ASSERT_TRUE(page);
2154
2155 constexpr int kWidth = 200;
2156 constexpr int kHeight = 200;
2157 EXPECT_EQ(kWidth, static_cast<int>(FPDF_GetPageWidthF(page.get())));
2158 EXPECT_EQ(kHeight, static_cast<int>(FPDF_GetPageHeightF(page.get())));
2159 EXPECT_TRUE(FPDFPage_HasTransparency(page.get()));
2160 ScopedFPDFBitmap bitmap(FPDFBitmap_Create(kWidth, kHeight, /*alpha=*/true));
2161 ASSERT_TRUE(
2162 FPDFBitmap_FillRect(bitmap.get(), 0, 0, kWidth, kHeight, 0xFFFFFFFF));
2163 FPDF_RenderPageBitmap(bitmap.get(), page.get(), /*start_x=*/0,
2164 /*start_y=*/0, kWidth, kHeight, /*rotate=*/0,
2165 /*flags=*/0);
2166 // TODO(crbug.com/1302355): This page should not render blank.
2167 EXPECT_EQ("eee4600ac08b458ac7ac2320e225674c", HashBitmap(bitmap.get()));
2168}
2169
2171 constexpr int kWidth = 595;
2172 constexpr int kHeight = 842;
2173 constexpr int kStride = kWidth * 3;
2174 std::vector<uint8_t> vec(kStride * kHeight);
2175 ScopedFPDFBitmap bitmap(FPDFBitmap_CreateEx(kWidth, kHeight, FPDFBitmap_BGR,
2176 vec.data(), kStride));
2177 EXPECT_EQ(FPDFBitmap_BGR, FPDFBitmap_GetFormat(bitmap.get()));
2178}
2179
2181 ASSERT_TRUE(OpenDocument("annotation_highlight_square_with_ap.pdf"));
2182 ScopedEmbedderTestPage page = LoadScopedPage(0);
2183 ASSERT_TRUE(page);
2184
2185 const char* const gray_checksum = []() {
2186 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
2187#if BUILDFLAG(IS_WIN)
2188 return "c18c1b7ee995f16dfb18e6da73a3c2d3";
2189#elif BUILDFLAG(IS_APPLE)
2190 return "92e96cad5e6b93fee3e2017ea27e2497";
2191#else
2192 return "b73df08d5252615ad6ed2fe7d6c73883";
2193#endif
2194 }
2195 return "c02f449666bf2633d06b909c76bc1c1d";
2196 }();
2197
2198 TestRenderPageBitmapWithInternalMemory(page.get(), FPDFBitmap_Gray,
2199 gray_checksum);
2200}
2201
2203 constexpr int kWidth = 200;
2204 constexpr int kHeight = 200;
2205 constexpr char kExpectedChecksum[] = "acc736435c9f84aa82941ba561bc5dbc";
2206 ScopedFPDFBitmap bitmap(FPDFBitmap_Create(200, 200, /*alpha=*/true));
2207 ASSERT_TRUE(FPDFBitmap_FillRect(bitmap.get(), /*left=*/0, /*top=*/0,
2208 /*width=*/kWidth,
2209 /*height=*/kHeight, 0xFFFF0000));
2210 EXPECT_EQ(kExpectedChecksum, HashBitmap(bitmap.get()));
2211
2212 // Empty rect dimensions is a no-op.
2213 ASSERT_TRUE(FPDFBitmap_FillRect(bitmap.get(), /*left=*/0, /*top=*/0,
2214 /*width=*/0,
2215 /*height=*/0, 0xFF0000FF));
2216 EXPECT_EQ(kExpectedChecksum, HashBitmap(bitmap.get()));
2217
2218 // Rect dimension overflows are also no-ops.
2219 ASSERT_FALSE(FPDFBitmap_FillRect(
2220 bitmap.get(), /*left=*/std::numeric_limits<int>::max(),
2221 /*top=*/0, /*width=*/std::numeric_limits<int>::max(),
2222 /*height=*/kHeight, 0xFF0000FF));
2223 EXPECT_EQ(kExpectedChecksum, HashBitmap(bitmap.get()));
2224
2225 ASSERT_FALSE(FPDFBitmap_FillRect(
2226 bitmap.get(), /*left=*/0,
2227 /*top=*/std::numeric_limits<int>::max(), /*width=*/kWidth,
2228 /*height=*/std::numeric_limits<int>::max(), 0xFF0000FF));
2229 EXPECT_EQ(kExpectedChecksum, HashBitmap(bitmap.get()));
2230
2231 // Make sure null bitmap handle does not trigger a crash.
2232 ASSERT_FALSE(FPDFBitmap_FillRect(nullptr, 0, 0, kWidth, kHeight, 0xFF0000FF));
2233}
uint32_t GetParsedPageCountForTesting()
static EmbedderTestEnvironment * GetInstance()
static void CompareBitmap(FPDF_BITMAP bitmap, int expected_width, int expected_height, const char *expected_md5sum)
static int BytesPerPixelForFormat(int format)
void TestRenderPageBitmapWithExternalMemoryAndNoStride(FPDF_PAGE page, int format, const char *expected_checksum)
void TestRenderPageBitmapWithMatrix(FPDF_PAGE page, int bitmap_width, int bitmap_height, const FS_MATRIX &matrix, const FS_RECTF &rect, const char *expected_checksum)
void TestRenderPageBitmapWithInternalMemoryAndStride(FPDF_PAGE page, int format, int bitmap_stride, const char *expected_checksum)
void TestRenderPageBitmapWithInternalMemory(FPDF_PAGE page, int format, const char *expected_checksum)
void TestRenderPageBitmapWithExternalMemory(FPDF_PAGE page, int format, const char *expected_checksum)
void TestRenderPageBitmapWithFlags(FPDF_PAGE page, int flags, const char *expected_checksum)
FX_FILEAVAIL * GetFileAvail() const
FPDF_FILEACCESS * GetFileAccess() const
static std::string GetTestFilePath(const std::string &file_name)
~RecordUnsupportedErrorDelegate() override=default
#define PDF_DATA_AVAIL
#define PDF_DATA_NOTAVAIL
#define FPDF_UNSP_DOC_PORTABLECOLLECTION
Definition fpdf_ext.h:22
FPDF_EXPORT unsigned long FPDF_CALLCONV FPDF_GetLastError()
FPDF_EXPORT FPDF_BITMAP FPDF_CALLCONV FPDFBitmap_CreateEx(int width, int height, int format, void *first_scan, int stride)
FPDF_EXPORT void FPDF_CALLCONV FPDF_SetSandBoxPolicy(FPDF_DWORD policy, FPDF_BOOL enable)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_DeviceToPage(FPDF_PAGE page, int start_x, int start_y, int size_x, int size_y, int rotate, int device_x, int device_y, double *page_x, double *page_y)
FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV FPDF_LoadCustomDocument(FPDF_FILEACCESS *pFileAccess, FPDF_BYTESTRING password)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_PageToDevice(FPDF_PAGE page, int start_x, int start_y, int size_x, int size_y, int rotate, double page_x, double page_y, int *device_x, int *device_y)
FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV FPDF_LoadDocument(FPDF_STRING file_path, FPDF_BYTESTRING password)
FPDF_EXPORT int FPDF_CALLCONV FPDFBitmap_GetHeight(FPDF_BITMAP bitmap)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_DocumentHasValidCrossReferenceTable(FPDF_DOCUMENT document)
FPDF_EXPORT float FPDF_CALLCONV FPDF_GetPageHeightF(FPDF_PAGE page)
FPDF_EXPORT void FPDF_CALLCONV FPDF_DestroyLibrary()
FPDF_EXPORT int FPDF_CALLCONV FPDF_GetXFAPacketCount(FPDF_DOCUMENT document)
FPDF_EXPORT FPDF_BITMAP FPDF_CALLCONV FPDFBitmap_Create(int width, int height, int alpha)
FPDF_EXPORT int FPDF_CALLCONV FPDF_GetPageSizeByIndex(FPDF_DOCUMENT document, int page_index, double *width, double *height)
FPDF_EXPORT double FPDF_CALLCONV FPDF_GetPageWidth(FPDF_PAGE page)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFBitmap_FillRect(FPDF_BITMAP bitmap, int left, int top, int width, int height, FPDF_DWORD color)
FPDF_EXPORT void FPDF_CALLCONV FPDF_InitLibrary()
FPDF_EXPORT void FPDF_CALLCONV FPDF_RenderPageBitmap(FPDF_BITMAP bitmap, FPDF_PAGE page, int start_x, int start_y, int size_x, int size_y, int rotate, int flags)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_GetPageBoundingBox(FPDF_PAGE page, FS_RECTF *rect)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_GetPageSizeByIndexF(FPDF_DOCUMENT document, int page_index, FS_SIZEF *size)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_GetXFAPacketContent(FPDF_DOCUMENT document, int index, void *buffer, unsigned long buflen, unsigned long *out_buflen)
FPDF_EXPORT unsigned long FPDF_CALLCONV FPDF_GetXFAPacketName(FPDF_DOCUMENT document, int index, void *buffer, unsigned long buflen)
FPDF_EXPORT double FPDF_CALLCONV FPDF_GetPageHeight(FPDF_PAGE page)
FPDF_EXPORT int FPDF_CALLCONV FPDFBitmap_GetWidth(FPDF_BITMAP bitmap)
FPDF_EXPORT unsigned long FPDF_CALLCONV FPDF_GetTrailerEnds(FPDF_DOCUMENT document, unsigned int *buffer, unsigned long length)
FPDF_EXPORT float FPDF_CALLCONV FPDF_GetPageWidthF(FPDF_PAGE page)
int CheckPDFiumCApi()
#define MAYBE_LargeImageDoesNotRenderBlank
TEST_F(FPDFViewEmbedderTest, DeviceCoordinatesToPageCoordinates)
#define FPDF_RENDER_LIMITEDIMAGECACHE
Definition fpdfview.h:803
#define FPDF_RENDER_NO_SMOOTHTEXT
Definition fpdfview.h:810
#define FPDF_ERR_FILE
Definition fpdfview.h:585
#define FPDFBitmap_BGR
Definition fpdfview.h:1086
#define FPDF_PRINTING
Definition fpdfview.h:807
#define FPDFBitmap_BGRx
Definition fpdfview.h:1088
#define FPDF_RENDER_NO_SMOOTHIMAGE
Definition fpdfview.h:812
#define FPDF_REVERSE_BYTE_ORDER
Definition fpdfview.h:817
#define FPDFBitmap_BGRA
Definition fpdfview.h:1090
#define FPDF_POLICY_MACHINETIME_ACCESS
Definition fpdfview.h:327
#define FPDF_RENDER_FORCEHALFTONE
Definition fpdfview.h:805
#define FPDF_GRAYSCALE
Definition fpdfview.h:797
#define FPDF_NO_NATIVETEXT
Definition fpdfview.h:795
#define FPDFBitmap_Gray
Definition fpdfview.h:1084
#define FPDF_ANNOT
Definition fpdfview.h:790
#define FPDF_LCD_TEXT
Definition fpdfview.h:793
#define FPDF_RENDER_NO_SMOOTHPATH
Definition fpdfview.h:814
TEST(FXCRYPT, MD5GenerateEmtpyData)
std::string GetPlatformString(FPDF_WIDESTRING wstr)
const char kBlankPage612By792Checksum[]
const char * RectanglesChecksum()
const char * HelloWorldChecksum()
const char * ManyRectanglesChecksum()
void(* AddSegment)(struct _FX_DOWNLOADHINTS *pThis, size_t offset, size_t size)