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