• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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