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