| // Copyright 2024 The PDFium Authors | |
| // Use of this source code is governed by a BSD-style license that can be | |
| // found in the LICENSE file. | |
| // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | |
| #include "core/fpdfapi/edit/cpdf_pageexporter.h" | |
| #include "constants/page_object.h" | |
| #include "core/fpdfapi/parser/cpdf_dictionary.h" | |
| #include "core/fpdfapi/parser/cpdf_document.h" | |
| #include "core/fpdfapi/parser/cpdf_object.h" | |
| CPDF_PageExporter::CPDF_PageExporter(CPDF_Document* dest_doc, | |
| CPDF_Document* src_doc) | |
| : CPDF_PageOrganizer(dest_doc, src_doc) {} | |
| CPDF_PageExporter::~CPDF_PageExporter() = default; | |
| bool CPDF_PageExporter::ExportPages(pdfium::span<const uint32_t> page_indices, | |
| int index) { | |
| if (!Init()) { | |
| return false; | |
| } | |
| int curpage = index; | |
| for (uint32_t pageIndex : page_indices) { | |
| RetainPtr<CPDF_Dictionary> dest_page_dict = dest()->CreateNewPage(curpage); | |
| RetainPtr<const CPDF_Dictionary> src_page_dict = | |
| src()->GetPageDictionary(pageIndex); | |
| if (!src_page_dict || !dest_page_dict) { | |
| return false; | |
| } | |
| // Clone the page dictionary | |
| CPDF_DictionaryLocker locker(src_page_dict); | |
| for (const auto& it : locker) { | |
| const ByteString& src_key = it.first; | |
| const RetainPtr<CPDF_Object>& obj = it.second; | |
| if (src_key == pdfium::page_object::kType || | |
| src_key == pdfium::page_object::kParent) { | |
| continue; | |
| } | |
| dest_page_dict->SetFor(src_key, obj->Clone()); | |
| } | |
| // inheritable item | |
| // Even though some entries are required by the PDF spec, there exist | |
| // PDFs that omit them. Set some defaults in this case. | |
| // 1 MediaBox - required | |
| if (!CopyInheritable(dest_page_dict, src_page_dict, | |
| pdfium::page_object::kMediaBox)) { | |
| // Search for "CropBox" in the source page dictionary. | |
| // If it does not exist, use the default letter size. | |
| RetainPtr<const CPDF_Object> inheritable = PageDictGetInheritableTag( | |
| src_page_dict, pdfium::page_object::kCropBox); | |
| if (inheritable) { | |
| dest_page_dict->SetFor(pdfium::page_object::kMediaBox, | |
| inheritable->Clone()); | |
| } else { | |
| // Make the default size letter size (8.5"x11") | |
| static const CFX_FloatRect kDefaultLetterRect(0, 0, 612, 792); | |
| dest_page_dict->SetRectFor(pdfium::page_object::kMediaBox, | |
| kDefaultLetterRect); | |
| } | |
| } | |
| // 2 Resources - required | |
| if (!CopyInheritable(dest_page_dict, src_page_dict, | |
| pdfium::page_object::kResources)) { | |
| // Use a default empty resources if it does not exist. | |
| dest_page_dict->SetNewFor<CPDF_Dictionary>( | |
| pdfium::page_object::kResources); | |
| } | |
| // 3 CropBox - optional | |
| CopyInheritable(dest_page_dict, src_page_dict, | |
| pdfium::page_object::kCropBox); | |
| // 4 Rotate - optional | |
| CopyInheritable(dest_page_dict, src_page_dict, | |
| pdfium::page_object::kRotate); | |
| // Update the reference | |
| uint32_t old_page_obj_num = src_page_dict->GetObjNum(); | |
| uint32_t new_page_obj_num = dest_page_dict->GetObjNum(); | |
| AddObjectMapping(old_page_obj_num, new_page_obj_num); | |
| UpdateReference(dest_page_dict); | |
| ++curpage; | |
| } | |
| return true; | |
| } |