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_ppo_embeddertest.cpp
Go to the documentation of this file.
1// Copyright 2016 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 <array>
6#include <iterator>
7#include <memory>
8#include <string>
9#include <vector>
10
11#include "core/fpdfapi/page/cpdf_form.h"
12#include "core/fpdfapi/page/cpdf_formobject.h"
13#include "core/fpdfapi/parser/cpdf_array.h"
14#include "core/fpdfapi/parser/cpdf_dictionary.h"
15#include "core/fpdfapi/parser/cpdf_document.h"
16#include "core/fpdfapi/parser/cpdf_name.h"
17#include "core/fpdfapi/parser/cpdf_number.h"
18#include "core/fpdfapi/parser/cpdf_stream.h"
19#include "core/fpdfapi/parser/cpdf_string.h"
20#include "core/fxge/cfx_defaultrenderdevice.h"
21#include "fpdfsdk/cpdfsdk_helpers.h"
22#include "public/cpp/fpdf_scopers.h"
23#include "public/fpdf_edit.h"
24#include "public/fpdf_ppo.h"
25#include "public/fpdf_save.h"
26#include "public/fpdfview.h"
27#include "testing/embedder_test.h"
28#include "testing/embedder_test_constants.h"
29#include "testing/gtest/include/gtest/gtest.h"
30#include "testing/utils/file_util.h"
31#include "testing/utils/path_service.h"
32
33namespace {
34
35class FPDFPPOEmbedderTest : public EmbedderTest {};
36
37int FakeBlockWriter(FPDF_FILEWRITE* pThis,
38 const void* pData,
39 unsigned long size) {
40 return 1; // Always succeeds.
41}
42
43constexpr int kRectanglesMultiPagesPageCount = 2;
44
45const char* RectanglesMultiPagesExpectedChecksum(int page_index) {
46 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
47 static constexpr std::array<const char*, kRectanglesMultiPagesPageCount>
48 kChecksums = {{"07606a12487bd0c28a88f23fa00fc313",
49 "94ea6e1eef220833a3ec14d6a1c612b0"}};
50 return kChecksums[page_index];
51 }
52 static constexpr std::array<const char*, kRectanglesMultiPagesPageCount>
53 kChecksums = {{"72d0d7a19a2f40e010ca6a1133b33e1e",
54 "fb18142190d770cfbc329d2b071aee4d"}};
55 return kChecksums[page_index];
56}
57
58const char* Bug750568PageHash(int page_index) {
59 constexpr int kBug750568PageCount = 4;
60 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
61 static constexpr std::array<const char*, kBug750568PageCount> kChecksums = {
62 {"eaa139e944eafb43d31e8742a0e158de", "226485e9d4fa6a67dfe0a88723f12060",
63 "c5601a3492ae5dcc5dd25140fc463bfe",
64 "1f60055b54de4fac8a59c65e90da156e"}};
65 return kChecksums[page_index];
66 }
67 static constexpr std::array<const char*, kBug750568PageCount> kChecksums = {
68 {"64ad08132a1c5a166768298c8a578f57", "83b83e2f6bc80707d0a917c7634140b9",
69 "913cd3723a451e4e46fbc2c05702d1ee", "81fb7cfd4860f855eb468f73dfeb6d60"}};
70 return kChecksums[page_index];
71}
72
73} // namespace
74
75TEST_F(FPDFPPOEmbedderTest, NoViewerPreferences) {
76 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
77
78 ScopedFPDFDocument output_doc(FPDF_CreateNewDocument());
79 EXPECT_TRUE(output_doc);
80 EXPECT_FALSE(FPDF_CopyViewerPreferences(output_doc.get(), document()));
81}
82
83TEST_F(FPDFPPOEmbedderTest, ViewerPreferences) {
84 ASSERT_TRUE(OpenDocument("viewer_ref.pdf"));
85
86 ScopedFPDFDocument output_doc(FPDF_CreateNewDocument());
87 EXPECT_TRUE(output_doc);
88 EXPECT_TRUE(FPDF_CopyViewerPreferences(output_doc.get(), document()));
89}
90
91TEST_F(FPDFPPOEmbedderTest, ImportPagesByIndex) {
92 ASSERT_TRUE(OpenDocument("viewer_ref.pdf"));
93
94 FPDF_PAGE page = LoadPage(0);
95 EXPECT_TRUE(page);
96
97 ScopedFPDFDocument output_doc(FPDF_CreateNewDocument());
98 ASSERT_TRUE(output_doc);
99 EXPECT_TRUE(FPDF_CopyViewerPreferences(output_doc.get(), document()));
100
101 static constexpr int kPageIndices[] = {1};
102 EXPECT_TRUE(FPDF_ImportPagesByIndex(
103 output_doc.get(), document(), kPageIndices, std::size(kPageIndices), 0));
104 EXPECT_EQ(1, FPDF_GetPageCount(output_doc.get()));
105
106 UnloadPage(page);
107}
108
109TEST_F(FPDFPPOEmbedderTest, ImportPages) {
110 ASSERT_TRUE(OpenDocument("viewer_ref.pdf"));
111
112 FPDF_PAGE page = LoadPage(0);
113 EXPECT_TRUE(page);
114
115 ScopedFPDFDocument output_doc(FPDF_CreateNewDocument());
116 ASSERT_TRUE(output_doc);
117 EXPECT_TRUE(FPDF_CopyViewerPreferences(output_doc.get(), document()));
118 EXPECT_TRUE(FPDF_ImportPages(output_doc.get(), document(), "1", 0));
119 EXPECT_EQ(1, FPDF_GetPageCount(output_doc.get()));
120
121 UnloadPage(page);
122}
123
124TEST_F(FPDFPPOEmbedderTest, ImportNPages) {
125 ASSERT_TRUE(OpenDocument("rectangles_multi_pages.pdf"));
126
127 ScopedFPDFDocument output_doc_2up(
128 FPDF_ImportNPagesToOne(document(), 612, 792, 2, 1));
129 ASSERT_TRUE(output_doc_2up);
130 EXPECT_EQ(3, FPDF_GetPageCount(output_doc_2up.get()));
131 ScopedFPDFDocument output_doc_5up(
132 FPDF_ImportNPagesToOne(document(), 612, 792, 5, 1));
133 ASSERT_TRUE(output_doc_5up);
134 EXPECT_EQ(1, FPDF_GetPageCount(output_doc_5up.get()));
135 ScopedFPDFDocument output_doc_8up(
136 FPDF_ImportNPagesToOne(document(), 792, 612, 8, 1));
137 ASSERT_TRUE(output_doc_8up);
138 EXPECT_EQ(1, FPDF_GetPageCount(output_doc_8up.get()));
139 ScopedFPDFDocument output_doc_128up(
140 FPDF_ImportNPagesToOne(document(), 792, 612, 128, 1));
141 ASSERT_TRUE(output_doc_128up);
142 EXPECT_EQ(1, FPDF_GetPageCount(output_doc_128up.get()));
143}
144
145TEST_F(FPDFPPOEmbedderTest, BadNupParams) {
146 ASSERT_TRUE(OpenDocument("rectangles_multi_pages.pdf"));
147
148 FPDF_DOCUMENT output_doc_zero_row =
149 FPDF_ImportNPagesToOne(document(), 612, 792, 0, 3);
150 ASSERT_FALSE(output_doc_zero_row);
151 FPDF_DOCUMENT output_doc_zero_col =
152 FPDF_ImportNPagesToOne(document(), 612, 792, 2, 0);
153 ASSERT_FALSE(output_doc_zero_col);
154 FPDF_DOCUMENT output_doc_zero_width =
155 FPDF_ImportNPagesToOne(document(), 0, 792, 2, 1);
156 ASSERT_FALSE(output_doc_zero_width);
157 FPDF_DOCUMENT output_doc_zero_height =
158 FPDF_ImportNPagesToOne(document(), 612, 0, 7, 1);
159 ASSERT_FALSE(output_doc_zero_height);
160}
161
162// TODO(Xlou): Add more tests to check output doc content of
163// FPDF_ImportNPagesToOne()
164TEST_F(FPDFPPOEmbedderTest, NupRenderImage) {
165 ASSERT_TRUE(OpenDocument("rectangles_multi_pages.pdf"));
166 ScopedFPDFDocument output_doc_3up(
167 FPDF_ImportNPagesToOne(document(), 792, 612, 3, 1));
168 ASSERT_TRUE(output_doc_3up);
169 ASSERT_EQ(kRectanglesMultiPagesPageCount,
170 FPDF_GetPageCount(output_doc_3up.get()));
171 for (int i = 0; i < kRectanglesMultiPagesPageCount; ++i) {
172 ScopedFPDFPage page(FPDF_LoadPage(output_doc_3up.get(), i));
173 ASSERT_TRUE(page);
174 ScopedFPDFBitmap bitmap = RenderPage(page.get());
175 EXPECT_EQ(792, FPDFBitmap_GetWidth(bitmap.get()));
176 EXPECT_EQ(612, FPDFBitmap_GetHeight(bitmap.get()));
177 EXPECT_EQ(RectanglesMultiPagesExpectedChecksum(i),
178 HashBitmap(bitmap.get()));
179 }
180}
181
182TEST_F(FPDFPPOEmbedderTest, ImportPageToXObject) {
183 const char* checksum = []() {
184 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
185 return "d6ebc0a8afc22fe0137f54ce54e1a19c";
186 }
187 return "2d88d180af7109eb346439f7c855bb29";
188 }();
189
190 ASSERT_TRUE(OpenDocument("rectangles.pdf"));
191
192 {
193 ScopedFPDFDocument output_doc(FPDF_CreateNewDocument());
194 ASSERT_TRUE(output_doc);
195
196 FPDF_XOBJECT xobject =
197 FPDF_NewXObjectFromPage(output_doc.get(), document(), 0);
198 ASSERT_TRUE(xobject);
199
200 for (int i = 0; i < 2; ++i) {
201 ScopedFPDFPage page(FPDFPage_New(output_doc.get(), 0, 612, 792));
202 ASSERT_TRUE(page);
203
204 FPDF_PAGEOBJECT page_object = FPDF_NewFormObjectFromXObject(xobject);
205 ASSERT_TRUE(page_object);
206 EXPECT_EQ(FPDF_PAGEOBJ_FORM, FPDFPageObj_GetType(page_object));
207 FPDFPage_InsertObject(page.get(), page_object);
208 EXPECT_TRUE(FPDFPage_GenerateContent(page.get()));
209
210 ScopedFPDFBitmap page_bitmap = RenderPage(page.get());
211 CompareBitmap(page_bitmap.get(), 612, 792, checksum);
212
213 float left;
214 float bottom;
215 float right;
216 float top;
217 ASSERT_TRUE(
218 FPDFPageObj_GetBounds(page_object, &left, &bottom, &right, &top));
219 EXPECT_FLOAT_EQ(-1.0f, left);
220 EXPECT_FLOAT_EQ(-1.0f, bottom);
221 EXPECT_FLOAT_EQ(201.0f, right);
222 EXPECT_FLOAT_EQ(301.0f, top);
223 }
224
225 EXPECT_TRUE(FPDF_SaveAsCopy(output_doc.get(), this, 0));
226
227 FPDF_CloseXObject(xobject);
228 }
229
230 constexpr int kExpectedPageCount = 2;
231 ASSERT_TRUE(OpenSavedDocument());
232
233 std::array<FPDF_PAGE, kExpectedPageCount> saved_pages;
234 std::array<FPDF_PAGEOBJECT, kExpectedPageCount> xobjects;
235 for (int i = 0; i < kExpectedPageCount; ++i) {
236 saved_pages[i] = LoadSavedPage(i);
237 ASSERT_TRUE(saved_pages[i]);
238
239 EXPECT_EQ(1, FPDFPage_CountObjects(saved_pages[i]));
240 xobjects[i] = FPDFPage_GetObject(saved_pages[i], 0);
241 ASSERT_TRUE(xobjects[i]);
242 ASSERT_EQ(FPDF_PAGEOBJ_FORM, FPDFPageObj_GetType(xobjects[i]));
243 EXPECT_EQ(8, FPDFFormObj_CountObjects(xobjects[i]));
244
245 {
246 ScopedFPDFBitmap page_bitmap = RenderPage(saved_pages[i]);
247 CompareBitmap(page_bitmap.get(), 612, 792, checksum);
248 }
249 }
250
251 for (int i = 0; i < kExpectedPageCount; ++i) {
252 float left;
253 float bottom;
254 float right;
255 float top;
256 ASSERT_TRUE(
257 FPDFPageObj_GetBounds(xobjects[i], &left, &bottom, &right, &top));
258 EXPECT_FLOAT_EQ(-1.0f, left);
259 EXPECT_FLOAT_EQ(-1.0f, bottom);
260 EXPECT_FLOAT_EQ(201.0f, right);
261 EXPECT_FLOAT_EQ(301.0f, top);
262 }
263
264 // Peek at object internals to make sure the two XObjects use the same
265 // stream.
266 EXPECT_NE(xobjects[0], xobjects[1]);
267 CPDF_PageObject* obj1 = CPDFPageObjectFromFPDFPageObject(xobjects[0]);
268 ASSERT_TRUE(obj1->AsForm());
269 ASSERT_TRUE(obj1->AsForm()->form());
270 ASSERT_TRUE(obj1->AsForm()->form()->GetStream());
271 CPDF_PageObject* obj2 = CPDFPageObjectFromFPDFPageObject(xobjects[1]);
272 ASSERT_TRUE(obj2->AsForm());
273 ASSERT_TRUE(obj2->AsForm()->form());
274 ASSERT_TRUE(obj2->AsForm()->form()->GetStream());
275 EXPECT_EQ(obj1->AsForm()->form()->GetStream(),
277
278 for (FPDF_PAGE saved_page : saved_pages)
279 CloseSavedPage(saved_page);
280
281 CloseSavedDocument();
282}
283
285 const char* checksum = []() {
286 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
287 return "8e7d672f49f9ca98fb9157824cefc204";
288 }
289 return "4d5ca14827b7707f8283e639b33c121a";
290 }();
291
292 ASSERT_TRUE(OpenDocument("rectangles.pdf"));
293
294 FPDF_XOBJECT xobject = FPDF_NewXObjectFromPage(document(), document(), 0);
295 ASSERT_TRUE(xobject);
296
297 FPDF_PAGE page = LoadPage(0);
298 ASSERT_TRUE(page);
299
300 {
301 ScopedFPDFBitmap bitmap = RenderLoadedPage(page);
302 CompareBitmap(bitmap.get(), 200, 300, pdfium::RectanglesChecksum());
303 }
304
305 FPDF_PAGEOBJECT page_object = FPDF_NewFormObjectFromXObject(xobject);
306 ASSERT_TRUE(page_object);
307 ASSERT_EQ(FPDF_PAGEOBJ_FORM, FPDFPageObj_GetType(page_object));
308
309 static constexpr FS_MATRIX kMatrix = {0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f};
310 EXPECT_TRUE(FPDFPageObj_SetMatrix(page_object, &kMatrix));
311
312 FPDFPage_InsertObject(page, page_object);
313 EXPECT_TRUE(FPDFPage_GenerateContent(page));
314
315 {
316 ScopedFPDFBitmap bitmap = RenderLoadedPage(page);
317 CompareBitmap(bitmap.get(), 200, 300, checksum);
318 }
319
320 FPDF_CloseXObject(xobject);
321
322 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
323 VerifySavedDocument(200, 300, checksum);
324
325 UnloadPage(page);
326}
327
328TEST_F(FPDFPPOEmbedderTest, XObjectNullParams) {
329 ASSERT_TRUE(OpenDocument("rectangles.pdf"));
330 ASSERT_EQ(1, FPDF_GetPageCount(document()));
331
332 EXPECT_FALSE(FPDF_NewXObjectFromPage(nullptr, nullptr, -1));
333 EXPECT_FALSE(FPDF_NewXObjectFromPage(nullptr, nullptr, 0));
334 EXPECT_FALSE(FPDF_NewXObjectFromPage(nullptr, nullptr, 1));
335 EXPECT_FALSE(FPDF_NewXObjectFromPage(document(), nullptr, -1));
336 EXPECT_FALSE(FPDF_NewXObjectFromPage(document(), nullptr, 0));
337 EXPECT_FALSE(FPDF_NewXObjectFromPage(document(), nullptr, 1));
338 EXPECT_FALSE(FPDF_NewXObjectFromPage(nullptr, document(), -1));
339 EXPECT_FALSE(FPDF_NewXObjectFromPage(nullptr, document(), 0));
340 EXPECT_FALSE(FPDF_NewXObjectFromPage(nullptr, document(), 1));
341
342 {
343 ScopedFPDFDocument output_doc(FPDF_CreateNewDocument());
344 ASSERT_TRUE(output_doc);
345 EXPECT_FALSE(FPDF_NewXObjectFromPage(output_doc.get(), document(), -1));
346 EXPECT_FALSE(FPDF_NewXObjectFromPage(output_doc.get(), document(), 1));
347 }
348
349 // Should be a no-op.
350 FPDF_CloseXObject(nullptr);
351
352 EXPECT_FALSE(FPDF_NewFormObjectFromXObject(nullptr));
353}
354
355TEST_F(FPDFPPOEmbedderTest, Bug925981) {
356 ASSERT_TRUE(OpenDocument("bug_925981.pdf"));
357 ScopedFPDFDocument output_doc_2up(
358 FPDF_ImportNPagesToOne(document(), 612, 792, 2, 1));
359 EXPECT_EQ(1, FPDF_GetPageCount(output_doc_2up.get()));
360}
361
362TEST_F(FPDFPPOEmbedderTest, Bug1229106) {
363 static constexpr int kPageCount = 4;
364 static constexpr int kTwoUpPageCount = 2;
365 static const char kRectsChecksum[] = "140d629b3c96a07ced2e3e408ea85a1d";
366 static const char kTwoUpChecksum[] = "fa4501562301b2e75da354bd067495ec";
367
368 ASSERT_TRUE(OpenDocument("bug_1229106.pdf"));
369
370 // Show all pages render the same.
371 ASSERT_EQ(kPageCount, FPDF_GetPageCount(document()));
372 for (int i = 0; i < kPageCount; ++i) {
373 FPDF_PAGE page = LoadPage(0);
374 ScopedFPDFBitmap bitmap = RenderLoadedPage(page);
375 CompareBitmap(bitmap.get(), 792, 612, kRectsChecksum);
376 UnloadPage(page);
377 }
378
379 // Create a 2-up PDF.
380 ScopedFPDFDocument output_doc_2up(
381 FPDF_ImportNPagesToOne(document(), 612, 792, 1, 2));
382 ASSERT_EQ(kTwoUpPageCount, FPDF_GetPageCount(output_doc_2up.get()));
383 for (int i = 0; i < kTwoUpPageCount; ++i) {
384 ScopedFPDFPage page(FPDF_LoadPage(output_doc_2up.get(), i));
385 ScopedFPDFBitmap bitmap = RenderPage(page.get());
386 CompareBitmap(bitmap.get(), 612, 792, kTwoUpChecksum);
387 }
388}
389
390TEST_F(FPDFPPOEmbedderTest, BadRepeatViewerPref) {
391 ASSERT_TRUE(OpenDocument("repeat_viewer_ref.pdf"));
392
393 ScopedFPDFDocument output_doc(FPDF_CreateNewDocument());
394 EXPECT_TRUE(output_doc);
395 EXPECT_TRUE(FPDF_CopyViewerPreferences(output_doc.get(), document()));
396
397 FPDF_FILEWRITE writer;
398 writer.version = 1;
399 writer.WriteBlock = FakeBlockWriter;
400
401 EXPECT_TRUE(FPDF_SaveAsCopy(output_doc.get(), &writer, 0));
402}
403
404TEST_F(FPDFPPOEmbedderTest, BadCircularViewerPref) {
405 ASSERT_TRUE(OpenDocument("circular_viewer_ref.pdf"));
406
407 ScopedFPDFDocument output_doc(FPDF_CreateNewDocument());
408 EXPECT_TRUE(output_doc);
409 EXPECT_TRUE(FPDF_CopyViewerPreferences(output_doc.get(), document()));
410
411 FPDF_FILEWRITE writer;
412 writer.version = 1;
413 writer.WriteBlock = FakeBlockWriter;
414
415 EXPECT_TRUE(FPDF_SaveAsCopy(output_doc.get(), &writer, 0));
416}
417
418TEST_F(FPDFPPOEmbedderTest, CopyViewerPrefTypes) {
419 ASSERT_TRUE(OpenDocument("viewer_pref_types.pdf"));
420
421 ScopedFPDFDocument output_doc(FPDF_CreateNewDocument());
422 ASSERT_TRUE(output_doc);
423 EXPECT_TRUE(FPDF_CopyViewerPreferences(output_doc.get(), document()));
424
425 // Peek under the hook to check the result.
426 const CPDF_Document* output_doc_impl =
427 CPDFDocumentFromFPDFDocument(output_doc.get());
428 RetainPtr<const CPDF_Dictionary> prefs =
429 output_doc_impl->GetRoot()->GetDictFor("ViewerPreferences");
430 ASSERT_TRUE(prefs);
431 EXPECT_EQ(6u, prefs->size());
432
433 RetainPtr<const CPDF_Object> bool_obj = prefs->GetObjectFor("Bool");
434 ASSERT_TRUE(bool_obj);
435 EXPECT_TRUE(bool_obj->IsBoolean());
436
437 RetainPtr<const CPDF_Number> num_obj = prefs->GetNumberFor("Num");
438 ASSERT_TRUE(num_obj);
439 EXPECT_TRUE(num_obj->IsInteger());
440 EXPECT_EQ(1, num_obj->GetInteger());
441
442 RetainPtr<const CPDF_String> str_obj = prefs->GetStringFor("Str");
443 ASSERT_TRUE(str_obj);
444 EXPECT_EQ("str", str_obj->GetString());
445
446 EXPECT_EQ("name", prefs->GetNameFor("Name"));
447
448 RetainPtr<const CPDF_Array> empty_array_obj =
449 prefs->GetArrayFor("EmptyArray");
450 ASSERT_TRUE(empty_array_obj);
451 EXPECT_TRUE(empty_array_obj->IsEmpty());
452
453 RetainPtr<const CPDF_Array> good_array_obj = prefs->GetArrayFor("GoodArray");
454 ASSERT_TRUE(good_array_obj);
455 EXPECT_EQ(4u, good_array_obj->size());
456}
457
458TEST_F(FPDFPPOEmbedderTest, BadIndices) {
459 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
460
461 FPDF_PAGE page = LoadPage(0);
462 EXPECT_TRUE(page);
463
464 ScopedFPDFDocument output_doc(FPDF_CreateNewDocument());
465 EXPECT_TRUE(output_doc);
466
467 static constexpr int kBadIndices1[] = {-1};
468 EXPECT_FALSE(FPDF_ImportPagesByIndex(
469 output_doc.get(), document(), kBadIndices1, std::size(kBadIndices1), 0));
470
471 static constexpr int kBadIndices2[] = {1};
472 EXPECT_FALSE(FPDF_ImportPagesByIndex(
473 output_doc.get(), document(), kBadIndices2, std::size(kBadIndices2), 0));
474
475 static constexpr int kBadIndices3[] = {-1, 0, 1};
476 EXPECT_FALSE(FPDF_ImportPagesByIndex(
477 output_doc.get(), document(), kBadIndices3, std::size(kBadIndices3), 0));
478
479 static constexpr int kBadIndices4[] = {42};
480 EXPECT_FALSE(FPDF_ImportPagesByIndex(
481 output_doc.get(), document(), kBadIndices4, std::size(kBadIndices4), 0));
482
483 UnloadPage(page);
484}
485
486TEST_F(FPDFPPOEmbedderTest, GoodIndices) {
487 ASSERT_TRUE(OpenDocument("viewer_ref.pdf"));
488
489 FPDF_PAGE page = LoadPage(0);
490 EXPECT_TRUE(page);
491
492 ScopedFPDFDocument output_doc(FPDF_CreateNewDocument());
493 EXPECT_TRUE(output_doc);
494
495 static constexpr int kGoodIndices1[] = {0, 0, 0, 0};
496 EXPECT_TRUE(FPDF_ImportPagesByIndex(output_doc.get(), document(),
497 kGoodIndices1, std::size(kGoodIndices1),
498 0));
499 EXPECT_EQ(4, FPDF_GetPageCount(output_doc.get()));
500
501 static constexpr int kGoodIndices2[] = {0};
502 EXPECT_TRUE(FPDF_ImportPagesByIndex(output_doc.get(), document(),
503 kGoodIndices2, std::size(kGoodIndices2),
504 0));
505 EXPECT_EQ(5, FPDF_GetPageCount(output_doc.get()));
506
507 static constexpr int kGoodIndices3[] = {4};
508 EXPECT_TRUE(FPDF_ImportPagesByIndex(output_doc.get(), document(),
509 kGoodIndices3, std::size(kGoodIndices3),
510 0));
511 EXPECT_EQ(6, FPDF_GetPageCount(output_doc.get()));
512
513 static constexpr int kGoodIndices4[] = {1, 2, 3};
514 EXPECT_TRUE(FPDF_ImportPagesByIndex(output_doc.get(), document(),
515 kGoodIndices4, std::size(kGoodIndices4),
516 0));
517 EXPECT_EQ(9, FPDF_GetPageCount(output_doc.get()));
518
519 // Passing in a nullptr should import all the pages.
520 EXPECT_TRUE(
521 FPDF_ImportPagesByIndex(output_doc.get(), document(), nullptr, 0, 0));
522 EXPECT_EQ(14, FPDF_GetPageCount(output_doc.get()));
523
524 UnloadPage(page);
525}
526
527TEST_F(FPDFPPOEmbedderTest, BadRanges) {
528 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
529
530 FPDF_PAGE page = LoadPage(0);
531 EXPECT_TRUE(page);
532
533 ScopedFPDFDocument output_doc(FPDF_CreateNewDocument());
534 EXPECT_TRUE(output_doc);
535 EXPECT_FALSE(FPDF_ImportPages(output_doc.get(), document(), "clams", 0));
536 EXPECT_FALSE(FPDF_ImportPages(output_doc.get(), document(), "0", 0));
537 EXPECT_FALSE(FPDF_ImportPages(output_doc.get(), document(), "42", 0));
538 EXPECT_FALSE(FPDF_ImportPages(output_doc.get(), document(), "1,2", 0));
539 EXPECT_FALSE(FPDF_ImportPages(output_doc.get(), document(), "1-2", 0));
540 EXPECT_FALSE(FPDF_ImportPages(output_doc.get(), document(), ",1", 0));
541 EXPECT_FALSE(FPDF_ImportPages(output_doc.get(), document(), "1,", 0));
542 EXPECT_FALSE(FPDF_ImportPages(output_doc.get(), document(), "1-", 0));
543 EXPECT_FALSE(FPDF_ImportPages(output_doc.get(), document(), "-1", 0));
544 EXPECT_FALSE(FPDF_ImportPages(output_doc.get(), document(), "-,0,,,1-", 0));
545
546 UnloadPage(page);
547}
548
549TEST_F(FPDFPPOEmbedderTest, GoodRanges) {
550 ASSERT_TRUE(OpenDocument("viewer_ref.pdf"));
551
552 FPDF_PAGE page = LoadPage(0);
553 EXPECT_TRUE(page);
554
555 ScopedFPDFDocument output_doc(FPDF_CreateNewDocument());
556 EXPECT_TRUE(output_doc);
557 EXPECT_TRUE(FPDF_CopyViewerPreferences(output_doc.get(), document()));
558 EXPECT_TRUE(FPDF_ImportPages(output_doc.get(), document(), "1,1,1,1", 0));
559 EXPECT_EQ(4, FPDF_GetPageCount(output_doc.get()));
560 EXPECT_TRUE(FPDF_ImportPages(output_doc.get(), document(), "1-1", 0));
561 EXPECT_EQ(5, FPDF_GetPageCount(output_doc.get()));
562 EXPECT_TRUE(FPDF_ImportPages(output_doc.get(), document(), "5-5", 0));
563 EXPECT_EQ(6, FPDF_GetPageCount(output_doc.get()));
564 EXPECT_TRUE(FPDF_ImportPages(output_doc.get(), document(), "2-4", 0));
565 EXPECT_EQ(9, FPDF_GetPageCount(output_doc.get()));
566
567 UnloadPage(page);
568}
569
570TEST_F(FPDFPPOEmbedderTest, Bug664284) {
571 ASSERT_TRUE(OpenDocument("bug_664284.pdf"));
572
573 FPDF_PAGE page = LoadPage(0);
574 ASSERT_NE(nullptr, page);
575
576 ScopedFPDFDocument output_doc(FPDF_CreateNewDocument());
577 EXPECT_TRUE(output_doc);
578
579 static constexpr int kIndices[] = {0};
580 EXPECT_TRUE(FPDF_ImportPagesByIndex(output_doc.get(), document(), kIndices,
581 std::size(kIndices), 0));
582
583 UnloadPage(page);
584}
585
586TEST_F(FPDFPPOEmbedderTest, Bug750568) {
587 ASSERT_TRUE(OpenDocument("bug_750568.pdf"));
588 ASSERT_EQ(4, FPDF_GetPageCount(document()));
589
590 for (size_t i = 0; i < 4; ++i) {
591 FPDF_PAGE page = LoadPage(i);
592 ASSERT_TRUE(page);
593
594 ScopedFPDFBitmap bitmap = RenderLoadedPage(page);
595 CompareBitmap(bitmap.get(), 200, 200, Bug750568PageHash(i));
596 UnloadPage(page);
597 }
598
599 ScopedFPDFDocument output_doc(FPDF_CreateNewDocument());
600 ASSERT_TRUE(output_doc);
601
602 static constexpr int kIndices[] = {0, 1, 2, 3};
603 EXPECT_TRUE(FPDF_ImportPagesByIndex(output_doc.get(), document(), kIndices,
604 std::size(kIndices), 0));
605 ASSERT_EQ(4, FPDF_GetPageCount(output_doc.get()));
606 for (size_t i = 0; i < 4; ++i) {
607 ScopedFPDFPage page(FPDF_LoadPage(output_doc.get(), i));
608 ASSERT_TRUE(page);
609
610 ScopedFPDFBitmap bitmap = RenderPage(page.get());
611 CompareBitmap(bitmap.get(), 200, 200, Bug750568PageHash(i));
612 }
613}
614
615TEST_F(FPDFPPOEmbedderTest, ImportWithZeroLengthStream) {
616 ASSERT_TRUE(OpenDocument("zero_length_stream.pdf"));
617 FPDF_PAGE page = LoadPage(0);
618 ASSERT_TRUE(page);
619
620 ScopedFPDFBitmap bitmap = RenderLoadedPage(page);
621 CompareBitmap(bitmap.get(), 200, 200, pdfium::HelloWorldChecksum());
622 UnloadPage(page);
623
624 ScopedFPDFDocument new_doc(FPDF_CreateNewDocument());
625 ASSERT_TRUE(new_doc);
626
627 static constexpr int kIndices[] = {0};
628 EXPECT_TRUE(FPDF_ImportPagesByIndex(new_doc.get(), document(), kIndices,
629 std::size(kIndices), 0));
630
631 EXPECT_EQ(1, FPDF_GetPageCount(new_doc.get()));
632 ScopedFPDFPage new_page(FPDF_LoadPage(new_doc.get(), 0));
633 ASSERT_TRUE(new_page);
634 ScopedFPDFBitmap new_bitmap = RenderPage(new_page.get());
635 CompareBitmap(new_bitmap.get(), 200, 200, pdfium::HelloWorldChecksum());
636}
637
639 ASSERT_TRUE(OpenDocument("hello_world.pdf"));
640 EXPECT_EQ(1, FPDF_GetPageCount(document()));
641
642 std::string file_path = PathService::GetTestFilePath("rectangles.pdf");
643 ASSERT_FALSE(file_path.empty());
644 std::vector<uint8_t> file_contents = GetFileContents(file_path.c_str());
645 ASSERT_FALSE(file_contents.empty());
646
647 ScopedFPDFDocument src_doc(FPDF_LoadMemDocument(
648 file_contents.data(), file_contents.size(), nullptr));
649 ASSERT_TRUE(src_doc);
650
651 static constexpr int kIndices[] = {0};
652 EXPECT_TRUE(FPDF_ImportPagesByIndex(document(), src_doc.get(), kIndices,
653 std::size(kIndices), 0));
654 EXPECT_EQ(2, FPDF_GetPageCount(document()));
655
656 EXPECT_TRUE(FPDF_ImportPages(document(), src_doc.get(), "1", 0));
657 EXPECT_EQ(3, FPDF_GetPageCount(document()));
658}
659
661 ASSERT_TRUE(OpenDocument("bad_page_type.pdf"));
662 EXPECT_EQ(2, FPDF_GetPageCount(document()));
663
664 std::string file_path = PathService::GetTestFilePath("rectangles.pdf");
665 ASSERT_FALSE(file_path.empty());
666 std::vector<uint8_t> file_contents = GetFileContents(file_path.c_str());
667 ASSERT_FALSE(file_contents.empty());
668
669 ScopedFPDFDocument src_doc(FPDF_LoadMemDocument(
670 file_contents.data(), file_contents.size(), nullptr));
671 ASSERT_TRUE(src_doc);
672 EXPECT_EQ(1, FPDF_GetPageCount(src_doc.get()));
673
674 FPDFPage_Delete(document(), 0);
675 EXPECT_EQ(1, FPDF_GetPageCount(document()));
676
677 static constexpr int kPageIndices[] = {0};
678 ASSERT_TRUE(FPDF_ImportPagesByIndex(document(), src_doc.get(), kPageIndices,
679 std::size(kPageIndices), 0));
680 EXPECT_EQ(2, FPDF_GetPageCount(document()));
681 const char* const new_page_1_checksum = []() {
682 if (CFX_DefaultRenderDevice::UseSkiaRenderer()) {
683 return "b4e411a6b5ffa59a50efede2efece597";
684 }
685 return "0a90de37f52127619c3dfb642b5fa2fe";
686 }();
687 const char new_page_2_checksum[] = "39336760026e7f3d26135e3b765125c3";
688 {
689 FPDF_PAGE page = LoadPage(0);
690 ASSERT_TRUE(page);
691 ScopedFPDFBitmap bitmap = RenderPage(page);
692 CompareBitmap(bitmap.get(), 200, 300, new_page_1_checksum);
693 UnloadPage(page);
694 }
695 {
696 FPDF_PAGE page = LoadPage(1);
697 ASSERT_TRUE(page);
698 ScopedFPDFBitmap bitmap = RenderPage(page);
699 CompareBitmap(bitmap.get(), 200, 100, new_page_2_checksum);
700 UnloadPage(page);
701 }
702
703 EXPECT_TRUE(FPDF_SaveAsCopy(document(), this, 0));
704
705 ASSERT_TRUE(OpenSavedDocument());
706 EXPECT_EQ(2, FPDF_GetPageCount(saved_document()));
707 {
708 FPDF_PAGE page = LoadSavedPage(0);
709 ASSERT_TRUE(page);
710 ScopedFPDFBitmap bitmap = RenderPage(page);
711 CompareBitmap(bitmap.get(), 200, 300, new_page_1_checksum);
712 CloseSavedPage(page);
713 }
714 {
715 FPDF_PAGE page = LoadSavedPage(1);
716 ASSERT_TRUE(page);
717 ScopedFPDFBitmap bitmap = RenderPage(page);
718 CompareBitmap(bitmap.get(), 200, 100, new_page_2_checksum);
719 CloseSavedPage(page);
720 }
721}
std::vector< RetainPtr< CPDF_Object > >::const_iterator const_iterator
Definition cpdf_array.h:29
std::map< ByteString, RetainPtr< CPDF_Object >, std::less<> > DictMap
const CPDF_Form * form() const
RetainPtr< const CPDF_Stream > GetStream() const
virtual CPDF_FormObject * AsForm()
FPDF_EXPORT void FPDF_CALLCONV FPDFPage_InsertObject(FPDF_PAGE page, FPDF_PAGEOBJECT page_object)
FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV FPDF_CreateNewDocument()
FPDF_EXPORT int FPDF_CALLCONV FPDFPageObj_GetType(FPDF_PAGEOBJECT page_object)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPageObj_GetBounds(FPDF_PAGEOBJECT page_object, float *left, float *bottom, float *right, float *top)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPageObj_SetMatrix(FPDF_PAGEOBJECT page_object, const FS_MATRIX *matrix)
#define FPDF_PAGEOBJ_FORM
Definition fpdf_edit.h:43
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDFPage_GenerateContent(FPDF_PAGE page)
FPDF_EXPORT void FPDF_CALLCONV FPDF_CloseXObject(FPDF_XOBJECT xobject)
Definition fpdf_ppo.cpp:198
FPDF_EXPORT FPDF_PAGEOBJECT FPDF_CALLCONV FPDF_NewFormObjectFromXObject(FPDF_XOBJECT xobject)
Definition fpdf_ppo.cpp:204
FPDF_EXPORT FPDF_XOBJECT FPDF_CALLCONV FPDF_NewXObjectFromPage(FPDF_DOCUMENT dest_doc, FPDF_DOCUMENT src_doc, int src_page_index)
Definition fpdf_ppo.cpp:181
TEST_F(FPDFPPOEmbedderTest, NoViewerPreferences)
const char * RectanglesChecksum()
const char * HelloWorldChecksum()
int(* WriteBlock)(struct FPDF_FILEWRITE_ *pThis, const void *pData, unsigned long size)
Definition fpdf_save.h:39