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.cpp
Go to the documentation of this file.
1// Copyright 2014 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 "public/fpdf_ppo.h"
8
9#include <memory>
10#include <numeric>
11#include <utility>
12#include <vector>
13
14#include "core/fpdfapi/edit/cpdf_npagetooneexporter.h"
15#include "core/fpdfapi/edit/cpdf_pageexporter.h"
16#include "core/fpdfapi/page/cpdf_form.h"
17#include "core/fpdfapi/page/cpdf_formobject.h"
18#include "core/fpdfapi/page/cpdf_page.h"
19#include "core/fpdfapi/page/cpdf_pageimagecache.h"
20#include "core/fpdfapi/page/cpdf_pageobject.h"
21#include "core/fpdfapi/parser/cpdf_array.h"
22#include "core/fpdfapi/parser/cpdf_dictionary.h"
23#include "core/fpdfapi/parser/cpdf_document.h"
24#include "core/fpdfapi/parser/cpdf_object.h"
25#include "core/fpdfapi/parser/fpdf_parser_utility.h"
26#include "core/fxcrt/check.h"
27#include "core/fxcrt/retain_ptr.h"
28#include "core/fxcrt/span.h"
29#include "fpdfsdk/cpdfsdk_helpers.h"
30#include "public/cpp/fpdf_scopers.h"
31
32namespace {
33
34std::vector<uint32_t> GetPageIndices(const CPDF_Document& doc,
35 const ByteString& page_range) {
36 uint32_t count = doc.GetPageCount();
37 if (!page_range.IsEmpty()) {
38 return ParsePageRangeString(page_range, count);
39 }
40
41 std::vector<uint32_t> page_indices(count);
42 std::iota(page_indices.begin(), page_indices.end(), 0);
43 return page_indices;
44}
45
46
47// Make sure arrays only contain objects of basic types.
48bool IsValidViewerPreferencesArray(const CPDF_Array* array) {
49 CPDF_ArrayLocker locker(array);
50 for (const auto& obj : locker) {
51 if (obj->IsArray() || obj->IsDictionary() || obj->IsReference() ||
52 obj->IsStream()) {
53 return false;
54 }
55 }
56 return true;
57}
58
59bool IsValidViewerPreferencesObject(const CPDF_Object* obj) {
60 // Per spec, there are no valid entries of these types.
61 if (obj->IsDictionary() || obj->IsNull() || obj->IsReference() ||
62 obj->IsStream()) {
63 return false;
64 }
65
66 const CPDF_Array* array = obj->AsArray();
67 if (!array) {
68 return true;
69 }
70
71 return IsValidViewerPreferencesArray(array);
72}
73
74} // namespace
75
77FPDF_ImportPagesByIndex(FPDF_DOCUMENT dest_doc,
78 FPDF_DOCUMENT src_doc,
79 const int* page_indices,
80 unsigned long length,
81 int index) {
83 if (!cdest_doc) {
84 return false;
85 }
86
88 if (!csrc_doc) {
89 return false;
90 }
91
92 CPDF_PageExporter exporter(cdest_doc, csrc_doc);
93
94 if (!page_indices) {
95 std::vector<uint32_t> page_indices_vec(csrc_doc->GetPageCount());
96 std::iota(page_indices_vec.begin(), page_indices_vec.end(), 0);
97 return exporter.ExportPages(page_indices_vec, index);
98 }
99 if (length == 0) {
100 return false;
101 }
102
103 // SAFETY: required from caller.
104 auto page_span = UNSAFE_BUFFERS(pdfium::make_span(page_indices, length));
105 for (int page_index : page_span) {
106 if (page_index < 0) {
107 return false;
108 }
109 }
110 return exporter.ExportPages(
111 fxcrt::reinterpret_span<const uint32_t>(page_span), index);
112}
113
114FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_ImportPages(FPDF_DOCUMENT dest_doc,
115 FPDF_DOCUMENT src_doc,
116 FPDF_BYTESTRING pagerange,
117 int index) {
119 if (!cdest_doc) {
120 return false;
121 }
122
124 if (!csrc_doc) {
125 return false;
126 }
127
128 std::vector<uint32_t> page_indices = GetPageIndices(*csrc_doc, pagerange);
129 if (page_indices.empty())
130 return false;
131
132 CPDF_PageExporter exporter(cdest_doc, csrc_doc);
133 return exporter.ExportPages(page_indices, index);
134}
135
136FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV
137FPDF_ImportNPagesToOne(FPDF_DOCUMENT src_doc,
138 float output_width,
139 float output_height,
140 size_t pages_on_x_axis,
141 size_t pages_on_y_axis) {
143 if (!csrc_doc) {
144 return nullptr;
145 }
146
147 if (output_width <= 0 || output_height <= 0 || pages_on_x_axis <= 0 ||
148 pages_on_y_axis <= 0) {
149 return nullptr;
150 }
151
152 ScopedFPDFDocument output_doc(FPDF_CreateNewDocument());
153 if (!output_doc)
154 return nullptr;
155
156 CPDF_Document* dest_doc = CPDFDocumentFromFPDFDocument(output_doc.get());
157 DCHECK(dest_doc);
158
159 std::vector<uint32_t> page_indices = GetPageIndices(*csrc_doc, ByteString());
160 if (page_indices.empty())
161 return nullptr;
162
163 if (pages_on_x_axis == 1 && pages_on_y_axis == 1) {
164 CPDF_PageExporter exporter(dest_doc, csrc_doc);
165 if (!exporter.ExportPages(page_indices, 0)) {
166 return nullptr;
167 }
168 return output_doc.release();
169 }
170
171 CPDF_NPageToOneExporter exporter(dest_doc, csrc_doc);
172 if (!exporter.ExportNPagesToOne(page_indices,
173 CFX_SizeF(output_width, output_height),
174 pages_on_x_axis, pages_on_y_axis)) {
175 return nullptr;
176 }
177 return output_doc.release();
178}
179
180FPDF_EXPORT FPDF_XOBJECT FPDF_CALLCONV
181FPDF_NewXObjectFromPage(FPDF_DOCUMENT dest_doc,
182 FPDF_DOCUMENT src_doc,
183 int src_page_index) {
185 if (!dest)
186 return nullptr;
187
189 if (!src)
190 return nullptr;
191
192 CPDF_NPageToOneExporter exporter(dest, src);
193 std::unique_ptr<XObjectContext> xobject =
194 exporter.CreateXObjectContextFromPage(src_page_index);
195 return FPDFXObjectFromXObjectContext(xobject.release());
196}
197
198FPDF_EXPORT void FPDF_CALLCONV FPDF_CloseXObject(FPDF_XOBJECT xobject) {
199 std::unique_ptr<XObjectContext> xobject_deleter(
201}
202
203FPDF_EXPORT FPDF_PAGEOBJECT FPDF_CALLCONV
204FPDF_NewFormObjectFromXObject(FPDF_XOBJECT xobject) {
206 if (!xobj)
207 return nullptr;
208
209 auto form = std::make_unique<CPDF_Form>(xobj->dest_doc, nullptr,
210 xobj->xobject, nullptr);
211 form->ParseContent(nullptr, nullptr, nullptr);
212 auto form_object = std::make_unique<CPDF_FormObject>(
214 return FPDFPageObjectFromCPDFPageObject(form_object.release());
215}
216
218FPDF_CopyViewerPreferences(FPDF_DOCUMENT dest_doc, FPDF_DOCUMENT src_doc) {
220 if (!cdest_doc) {
221 return false;
222 }
223
225 if (!csrc_doc) {
226 return false;
227 }
228
229 RetainPtr<const CPDF_Dictionary> pref_dict =
230 csrc_doc->GetRoot()->GetDictFor("ViewerPreferences");
231 if (!pref_dict) {
232 return false;
233 }
234
235 RetainPtr<CPDF_Dictionary> dest_dict = cdest_doc->GetMutableRoot();
236 if (!dest_dict) {
237 return false;
238 }
239
240 auto cloned_dict = pdfium::MakeRetain<CPDF_Dictionary>();
241 CPDF_DictionaryLocker locker(pref_dict);
242 for (const auto& it : locker) {
243 if (IsValidViewerPreferencesObject(it.second)) {
244 cloned_dict->SetFor(it.first, it.second->Clone());
245 }
246 }
247
248 dest_dict->SetFor("ViewerPreferences", std::move(cloned_dict));
249 return true;
250}
fxcrt::ByteString ByteString
Definition bytestring.h:180
#define DCHECK
Definition check.h:33
constexpr CFX_Matrix()=default
CPDF_ArrayLocker(const CPDF_Array *pArray)
std::vector< RetainPtr< CPDF_Object > >::const_iterator const_iterator
Definition cpdf_array.h:29
std::map< ByteString, RetainPtr< CPDF_Object >, std::less<> > DictMap
int GetPageCount() const
CPDF_NPageToOneExporter(CPDF_Document *dest_doc, CPDF_Document *src_doc)
bool IsDictionary() const
bool IsStream() const
const CPDF_Array * AsArray() const
bool IsNull() const
bool IsReference() const
CPDF_PageExporter(CPDF_Document *dest_doc, CPDF_Document *src_doc)
static constexpr int32_t kNoContentStream
#define UNSAFE_BUFFERS(...)
XObjectContext * XObjectContextFromFPDFXObject(FPDF_XOBJECT xobject)
CPDF_Document * CPDFDocumentFromFPDFDocument(FPDF_DOCUMENT doc)
FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV FPDF_CreateNewDocument()
FPDF_EXPORT FPDF_DOCUMENT FPDF_CALLCONV FPDF_ImportNPagesToOne(FPDF_DOCUMENT src_doc, float output_width, float output_height, size_t pages_on_x_axis, size_t pages_on_y_axis)
Definition fpdf_ppo.cpp:137
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
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_CopyViewerPreferences(FPDF_DOCUMENT dest_doc, FPDF_DOCUMENT src_doc)
Definition fpdf_ppo.cpp:218
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_ImportPages(FPDF_DOCUMENT dest_doc, FPDF_DOCUMENT src_doc, FPDF_BYTESTRING pagerange, int index)
Definition fpdf_ppo.cpp:114
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_ImportPagesByIndex(FPDF_DOCUMENT dest_doc, FPDF_DOCUMENT src_doc, const int *page_indices, unsigned long length, int index)
Definition fpdf_ppo.cpp:77
#define FPDF_CALLCONV
Definition fpdfview.h:229
#define FPDF_EXPORT
Definition fpdfview.h:223