1 // Copyright 2024 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 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6
7 #include "core/fpdfapi/edit/cpdf_pageexporter.h"
8
9 #include "constants/page_object.h"
10 #include "core/fpdfapi/parser/cpdf_dictionary.h"
11 #include "core/fpdfapi/parser/cpdf_document.h"
12 #include "core/fpdfapi/parser/cpdf_object.h"
13
CPDF_PageExporter(CPDF_Document * dest_doc,CPDF_Document * src_doc)14 CPDF_PageExporter::CPDF_PageExporter(CPDF_Document* dest_doc,
15 CPDF_Document* src_doc)
16 : CPDF_PageOrganizer(dest_doc, src_doc) {}
17
18 CPDF_PageExporter::~CPDF_PageExporter() = default;
19
ExportPages(pdfium::span<const uint32_t> page_indices,int index)20 bool CPDF_PageExporter::ExportPages(pdfium::span<const uint32_t> page_indices,
21 int index) {
22 if (!Init()) {
23 return false;
24 }
25
26 int curpage = index;
27 for (uint32_t pageIndex : page_indices) {
28 RetainPtr<CPDF_Dictionary> dest_page_dict = dest()->CreateNewPage(curpage);
29 RetainPtr<const CPDF_Dictionary> src_page_dict =
30 src()->GetPageDictionary(pageIndex);
31 if (!src_page_dict || !dest_page_dict) {
32 return false;
33 }
34
35 // Clone the page dictionary
36 CPDF_DictionaryLocker locker(src_page_dict);
37 for (const auto& it : locker) {
38 const ByteString& src_key = it.first;
39 const RetainPtr<CPDF_Object>& obj = it.second;
40 if (src_key == pdfium::page_object::kType ||
41 src_key == pdfium::page_object::kParent) {
42 continue;
43 }
44 dest_page_dict->SetFor(src_key, obj->Clone());
45 }
46
47 // inheritable item
48 // Even though some entries are required by the PDF spec, there exist
49 // PDFs that omit them. Set some defaults in this case.
50 // 1 MediaBox - required
51 if (!CopyInheritable(dest_page_dict, src_page_dict,
52 pdfium::page_object::kMediaBox)) {
53 // Search for "CropBox" in the source page dictionary.
54 // If it does not exist, use the default letter size.
55 RetainPtr<const CPDF_Object> inheritable = PageDictGetInheritableTag(
56 src_page_dict, pdfium::page_object::kCropBox);
57 if (inheritable) {
58 dest_page_dict->SetFor(pdfium::page_object::kMediaBox,
59 inheritable->Clone());
60 } else {
61 // Make the default size letter size (8.5"x11")
62 static const CFX_FloatRect kDefaultLetterRect(0, 0, 612, 792);
63 dest_page_dict->SetRectFor(pdfium::page_object::kMediaBox,
64 kDefaultLetterRect);
65 }
66 }
67
68 // 2 Resources - required
69 if (!CopyInheritable(dest_page_dict, src_page_dict,
70 pdfium::page_object::kResources)) {
71 // Use a default empty resources if it does not exist.
72 dest_page_dict->SetNewFor<CPDF_Dictionary>(
73 pdfium::page_object::kResources);
74 }
75
76 // 3 CropBox - optional
77 CopyInheritable(dest_page_dict, src_page_dict,
78 pdfium::page_object::kCropBox);
79 // 4 Rotate - optional
80 CopyInheritable(dest_page_dict, src_page_dict,
81 pdfium::page_object::kRotate);
82
83 // Update the reference
84 uint32_t old_page_obj_num = src_page_dict->GetObjNum();
85 uint32_t new_page_obj_num = dest_page_dict->GetObjNum();
86 AddObjectMapping(old_page_obj_num, new_page_obj_num);
87 UpdateReference(dest_page_dict);
88 ++curpage;
89 }
90
91 return true;
92 }
93