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_structtree.cpp
Go to the documentation of this file.
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 "public/fpdf_structtree.h"
6
7#include <memory>
8
9#include "core/fpdfapi/page/cpdf_page.h"
10#include "core/fpdfapi/parser/cpdf_array.h"
11#include "core/fpdfapi/parser/cpdf_dictionary.h"
12#include "core/fpdfdoc/cpdf_structelement.h"
13#include "core/fpdfdoc/cpdf_structtree.h"
14#include "core/fxcrt/fx_safe_types.h"
15#include "core/fxcrt/stl_util.h"
16#include "fpdfsdk/cpdfsdk_helpers.h"
17#include "third_party/base/numerics/safe_conversions.h"
18
19namespace {
20
21unsigned long WideStringToBuffer(const WideString& str,
22 void* buffer,
23 unsigned long buflen) {
24 if (str.IsEmpty())
25 return 0;
26
27 return Utf16EncodeMaybeCopyAndReturnLength(str, buffer, buflen);
28}
29
30int GetMcidFromDict(const CPDF_Dictionary* dict) {
31 if (dict && dict->GetNameFor("Type") == "MCR") {
32 RetainPtr<const CPDF_Object> obj = dict->GetObjectFor("MCID");
33 if (obj && obj->IsNumber())
34 return obj->GetInteger();
35 }
36 return -1;
37}
38
39} // namespace
40
41FPDF_EXPORT FPDF_STRUCTTREE FPDF_CALLCONV
43 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
44 if (!pPage)
45 return nullptr;
46
47 // Caller takes onwership.
48 return FPDFStructTreeFromCPDFStructTree(
49 CPDF_StructTree::LoadPage(pPage->GetDocument(), pPage->GetDict())
50 .release());
51}
52
54FPDF_StructTree_Close(FPDF_STRUCTTREE struct_tree) {
55 std::unique_ptr<CPDF_StructTree>(
56 CPDFStructTreeFromFPDFStructTree(struct_tree));
57}
58
60FPDF_StructTree_CountChildren(FPDF_STRUCTTREE struct_tree) {
62 if (!tree)
63 return -1;
64
65 FX_SAFE_INT32 tmp_size = tree->CountTopElements();
66 return tmp_size.ValueOrDefault(-1);
67}
68
69FPDF_EXPORT FPDF_STRUCTELEMENT FPDF_CALLCONV
70FPDF_StructTree_GetChildAtIndex(FPDF_STRUCTTREE struct_tree, int index) {
72 if (!tree || index < 0 ||
73 static_cast<size_t>(index) >= tree->CountTopElements()) {
74 return nullptr;
75 }
76 return FPDFStructElementFromCPDFStructElement(
77 tree->GetTopElement(static_cast<size_t>(index)));
78}
79
80FPDF_EXPORT unsigned long FPDF_CALLCONV
81FPDF_StructElement_GetAltText(FPDF_STRUCTELEMENT struct_element,
82 void* buffer,
83 unsigned long buflen) {
84 CPDF_StructElement* elem =
86 return elem ? WideStringToBuffer(elem->GetAltText(), buffer, buflen) : 0;
87}
88
89FPDF_EXPORT unsigned long FPDF_CALLCONV
90FPDF_StructElement_GetActualText(FPDF_STRUCTELEMENT struct_element,
91 void* buffer,
92 unsigned long buflen) {
93 CPDF_StructElement* elem =
95 return elem ? WideStringToBuffer(elem->GetActualText(), buffer, buflen) : 0;
96}
97
98FPDF_EXPORT unsigned long FPDF_CALLCONV
99FPDF_StructElement_GetID(FPDF_STRUCTELEMENT struct_element,
100 void* buffer,
101 unsigned long buflen) {
102 CPDF_StructElement* elem =
104 if (!elem)
105 return 0;
106 absl::optional<WideString> id = elem->GetID();
107 if (!id.has_value())
108 return 0;
109 return Utf16EncodeMaybeCopyAndReturnLength(id.value(), buffer, buflen);
110}
111
112FPDF_EXPORT unsigned long FPDF_CALLCONV
113FPDF_StructElement_GetLang(FPDF_STRUCTELEMENT struct_element,
114 void* buffer,
115 unsigned long buflen) {
116 CPDF_StructElement* elem =
118 if (!elem)
119 return 0;
120 absl::optional<WideString> lang = elem->GetLang();
121 if (!lang.has_value())
122 return 0;
123 return Utf16EncodeMaybeCopyAndReturnLength(lang.value(), buffer, buflen);
124}
125
127FPDF_StructElement_GetAttributeCount(FPDF_STRUCTELEMENT struct_element) {
128 CPDF_StructElement* elem =
130 if (!elem)
131 return -1;
132 RetainPtr<const CPDF_Object> attr_obj = elem->GetA();
133 if (!attr_obj) {
134 return -1;
135 }
136 attr_obj = attr_obj->GetDirect();
137 if (!attr_obj)
138 return -1;
139 if (attr_obj->IsArray())
140 return fxcrt::CollectionSize<int>(*attr_obj->AsArray());
141 return attr_obj->IsDictionary() ? 1 : -1;
142}
143
144FPDF_EXPORT FPDF_STRUCTELEMENT_ATTR FPDF_CALLCONV
145FPDF_StructElement_GetAttributeAtIndex(FPDF_STRUCTELEMENT struct_element,
146 int index) {
147 CPDF_StructElement* elem =
149 if (!elem)
150 return nullptr;
151
152 RetainPtr<const CPDF_Object> attr_obj = elem->GetA();
153 if (!attr_obj)
154 return nullptr;
155
156 attr_obj = attr_obj->GetDirect();
157 if (!attr_obj) {
158 return nullptr;
159 }
160 if (attr_obj->IsDictionary()) {
161 return index == 0 ? FPDFStructElementAttrFromCPDFDictionary(
162 attr_obj->AsDictionary())
163 : nullptr;
164 }
165 if (attr_obj->IsArray()) {
166 const CPDF_Array* array = attr_obj->AsArray();
167 if (index < 0 || static_cast<size_t>(index) >= array->size())
168 return nullptr;
169
170 // TODO(tsepez): should embedder take a reference here?
171 // Unretained reference in public API. NOLINTNEXTLINE
172 return FPDFStructElementAttrFromCPDFDictionary(array->GetDictAt(index));
173 }
174 return nullptr;
175}
176
177FPDF_EXPORT unsigned long FPDF_CALLCONV
178FPDF_StructElement_GetStringAttribute(FPDF_STRUCTELEMENT struct_element,
179 FPDF_BYTESTRING attr_name,
180 void* buffer,
181 unsigned long buflen) {
182 CPDF_StructElement* elem =
184 if (!elem)
185 return 0;
186 RetainPtr<const CPDF_Array> array = ToArray(elem->GetA());
187 if (!array)
188 return 0;
189 CPDF_ArrayLocker locker(array);
190 for (const RetainPtr<CPDF_Object>& obj : locker) {
191 const CPDF_Dictionary* obj_dict = obj->AsDictionary();
192 if (!obj_dict)
193 continue;
194 RetainPtr<const CPDF_Object> attr = obj_dict->GetObjectFor(attr_name);
195 if (!attr || !(attr->IsString() || attr->IsName()))
196 continue;
197 return Utf16EncodeMaybeCopyAndReturnLength(attr->GetUnicodeText(), buffer,
198 buflen);
199 }
200 return 0;
201}
202
204FPDF_StructElement_GetMarkedContentID(FPDF_STRUCTELEMENT struct_element) {
205 CPDF_StructElement* elem =
207 if (!elem)
208 return -1;
209 RetainPtr<const CPDF_Object> p = elem->GetK();
210 return p && p->IsNumber() ? p->GetInteger() : -1;
211}
212
213FPDF_EXPORT unsigned long FPDF_CALLCONV
214FPDF_StructElement_GetType(FPDF_STRUCTELEMENT struct_element,
215 void* buffer,
216 unsigned long buflen) {
217 CPDF_StructElement* elem =
219 return elem ? WideStringToBuffer(
220 WideString::FromUTF8(elem->GetType().AsStringView()),
221 buffer, buflen)
222 : 0;
223}
224
225FPDF_EXPORT unsigned long FPDF_CALLCONV
226FPDF_StructElement_GetObjType(FPDF_STRUCTELEMENT struct_element,
227 void* buffer,
228 unsigned long buflen) {
229 CPDF_StructElement* elem =
231 return elem ? WideStringToBuffer(
232 WideString::FromUTF8(elem->GetObjType().AsStringView()),
233 buffer, buflen)
234 : 0;
235}
236
237FPDF_EXPORT unsigned long FPDF_CALLCONV
238FPDF_StructElement_GetTitle(FPDF_STRUCTELEMENT struct_element,
239 void* buffer,
240 unsigned long buflen) {
241 CPDF_StructElement* elem =
243 return elem ? WideStringToBuffer(elem->GetTitle(), buffer, buflen) : 0;
244}
245
247FPDF_StructElement_CountChildren(FPDF_STRUCTELEMENT struct_element) {
248 CPDF_StructElement* elem =
250 if (!elem)
251 return -1;
252
253 FX_SAFE_INT32 tmp_size = elem->CountKids();
254 return tmp_size.ValueOrDefault(-1);
255}
256
257FPDF_EXPORT FPDF_STRUCTELEMENT FPDF_CALLCONV
258FPDF_StructElement_GetChildAtIndex(FPDF_STRUCTELEMENT struct_element,
259 int index) {
260 CPDF_StructElement* elem =
262 if (!elem || index < 0 || static_cast<size_t>(index) >= elem->CountKids())
263 return nullptr;
264
265 return FPDFStructElementFromCPDFStructElement(elem->GetKidIfElement(index));
266}
267
269FPDF_StructElement_GetChildMarkedContentID(FPDF_STRUCTELEMENT struct_element,
270 int index) {
271 CPDF_StructElement* elem =
273 if (!elem || index < 0 || static_cast<size_t>(index) >= elem->CountKids()) {
274 return -1;
275 }
276
277 return elem->GetKidContentId(index);
278}
279
280FPDF_EXPORT FPDF_STRUCTELEMENT FPDF_CALLCONV
281FPDF_StructElement_GetParent(FPDF_STRUCTELEMENT struct_element) {
282 CPDF_StructElement* elem =
284 CPDF_StructElement* parent = elem ? elem->GetParent() : nullptr;
285 if (!parent) {
286 return nullptr;
287 }
289}
290
292FPDF_StructElement_Attr_GetCount(FPDF_STRUCTELEMENT_ATTR struct_attribute) {
293 const CPDF_Dictionary* dict =
295 if (!dict)
296 return -1;
297 return fxcrt::CollectionSize<int>(*dict);
298}
299
301FPDF_StructElement_Attr_GetName(FPDF_STRUCTELEMENT_ATTR struct_attribute,
302 int index,
303 void* buffer,
304 unsigned long buflen,
305 unsigned long* out_buflen) {
306 if (!out_buflen) {
307 return false;
308 }
309
310 const CPDF_Dictionary* dict =
312 if (!dict)
313 return false;
314
315 CPDF_DictionaryLocker locker(dict);
316 for (auto& it : locker) {
317 if (index == 0) {
318 *out_buflen =
319 NulTerminateMaybeCopyAndReturnLength(it.first, buffer, buflen);
320 return true;
321 }
322 --index;
323 }
324 return false;
325}
326
327FPDF_EXPORT FPDF_OBJECT_TYPE FPDF_CALLCONV
328FPDF_StructElement_Attr_GetType(FPDF_STRUCTELEMENT_ATTR struct_attribute,
329 FPDF_BYTESTRING name) {
330 const CPDF_Dictionary* dict =
332 if (!dict)
333 return FPDF_OBJECT_UNKNOWN;
334
335 RetainPtr<const CPDF_Object> obj = dict->GetObjectFor(name);
336 return obj ? obj->GetType() : FPDF_OBJECT_UNKNOWN;
337}
338
340 FPDF_STRUCTELEMENT_ATTR struct_attribute,
341 FPDF_BYTESTRING name,
342 FPDF_BOOL* out_value) {
343 if (!out_value)
344 return false;
345
346 const CPDF_Dictionary* dict =
348 if (!dict)
349 return false;
350
351 RetainPtr<const CPDF_Object> obj = dict->GetObjectFor(name);
352 if (!obj || !obj->IsBoolean())
353 return false;
354
355 *out_value = obj->GetInteger();
356 return true;
357}
358
360FPDF_StructElement_Attr_GetNumberValue(FPDF_STRUCTELEMENT_ATTR struct_attribute,
361 FPDF_BYTESTRING name,
362 float* out_value) {
363 if (!out_value)
364 return false;
365
366 const CPDF_Dictionary* dict =
368 if (!dict)
369 return false;
370
371 RetainPtr<const CPDF_Object> obj = dict->GetDirectObjectFor(name);
372 if (!obj || !obj->IsNumber())
373 return false;
374
375 *out_value = obj->GetNumber();
376 return true;
377}
378
380FPDF_StructElement_Attr_GetStringValue(FPDF_STRUCTELEMENT_ATTR struct_attribute,
381 FPDF_BYTESTRING name,
382 void* buffer,
383 unsigned long buflen,
384 unsigned long* out_buflen) {
385 if (!out_buflen)
386 return false;
387
388 const CPDF_Dictionary* dict =
390 if (!dict)
391 return false;
392
393 RetainPtr<const CPDF_Object> obj = dict->GetObjectFor(name);
394 if (!obj || !(obj->IsString() || obj->IsName()))
395 return false;
396
397 *out_buflen = Utf16EncodeMaybeCopyAndReturnLength(
398 WideString::FromUTF8(obj->GetString().AsStringView()), buffer, buflen);
399 return true;
400}
401
403FPDF_StructElement_Attr_GetBlobValue(FPDF_STRUCTELEMENT_ATTR struct_attribute,
404 FPDF_BYTESTRING name,
405 void* buffer,
406 unsigned long buflen,
407 unsigned long* out_buflen) {
408 if (!out_buflen)
409 return false;
410
411 const CPDF_Dictionary* dict =
413 if (!dict)
414 return false;
415
416 RetainPtr<const CPDF_Object> obj = dict->GetObjectFor(name);
417 if (!obj || !obj->IsString())
418 return false;
419
420 ByteString result = obj->GetString();
421 const unsigned long len =
422 pdfium::base::checked_cast<unsigned long>(result.GetLength());
423 if (buffer && len <= buflen)
424 memcpy(buffer, result.c_str(), len);
425
426 *out_buflen = len;
427 return true;
428}
429
431FPDF_StructElement_GetMarkedContentIdCount(FPDF_STRUCTELEMENT struct_element) {
432 CPDF_StructElement* elem =
434 if (!elem)
435 return -1;
436 RetainPtr<const CPDF_Object> p = elem->GetK();
437 if (!p)
438 return -1;
439
440 if (p->IsNumber() || p->IsDictionary())
441 return 1;
442
443 return p->IsArray() ? fxcrt::CollectionSize<int>(*p->AsArray()) : -1;
444}
445
447FPDF_StructElement_GetMarkedContentIdAtIndex(FPDF_STRUCTELEMENT struct_element,
448 int index) {
449 CPDF_StructElement* elem =
451 if (!elem)
452 return -1;
453 RetainPtr<const CPDF_Object> p = elem->GetK();
454 if (!p)
455 return -1;
456
457 if (p->IsNumber())
458 return index == 0 ? p->GetInteger() : -1;
459
460 if (p->IsDictionary())
461 return GetMcidFromDict(p->GetDict().Get());
462
463 if (p->IsArray()) {
464 const CPDF_Array* array = p->AsArray();
465 if (index < 0 || static_cast<size_t>(index) >= array->size())
466 return -1;
467 RetainPtr<const CPDF_Object> array_elem = array->GetObjectAt(index);
468 if (array_elem->IsNumber())
469 return array_elem->GetInteger();
470 if (array_elem->IsDictionary()) {
471 return GetMcidFromDict(array_elem->GetDict().Get());
472 }
473 }
474 return -1;
475}
CPDF_DictionaryLocker(const CPDF_Dictionary *pDictionary)
ByteString GetNameFor(const ByteString &key) const
CPDF_Document * GetDocument() const override
Definition cpdf_page.cpp:51
ByteString GetType() const
WideString GetTitle() const
WideString GetActualText() const
CPDF_StructElement * GetParent() const
ByteString GetObjType() const
WideString GetAltText() const
bool operator==(const char *ptr) const
const char * c_str() const
Definition bytestring.h:76
static WideString FromUTF8(ByteStringView str)
bool IsEmpty() const
Definition widestring.h:118
CPDF_StructElement * CPDFStructElementFromFPDFStructElement(FPDF_STRUCTELEMENT struct_element)
unsigned long Utf16EncodeMaybeCopyAndReturnLength(const WideString &text, void *buffer, unsigned long buflen)
FPDF_STRUCTELEMENT FPDFStructElementFromCPDFStructElement(CPDF_StructElement *struct_element)
CPDF_Page * CPDFPageFromFPDFPage(FPDF_PAGE page)
CPDF_StructTree * CPDFStructTreeFromFPDFStructTree(FPDF_STRUCTTREE struct_tree)
const CPDF_Dictionary * CPDFDictionaryFromFPDFStructElementAttr(FPDF_STRUCTELEMENT_ATTR struct_element_attr)
FPDF_EXPORT FPDF_STRUCTELEMENT FPDF_CALLCONV FPDF_StructElement_GetParent(FPDF_STRUCTELEMENT struct_element)
FPDF_EXPORT unsigned long FPDF_CALLCONV FPDF_StructElement_GetLang(FPDF_STRUCTELEMENT struct_element, void *buffer, unsigned long buflen)
FPDF_EXPORT int FPDF_CALLCONV FPDF_StructElement_GetAttributeCount(FPDF_STRUCTELEMENT struct_element)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_StructElement_Attr_GetStringValue(FPDF_STRUCTELEMENT_ATTR struct_attribute, FPDF_BYTESTRING name, void *buffer, unsigned long buflen, unsigned long *out_buflen)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_StructElement_Attr_GetBooleanValue(FPDF_STRUCTELEMENT_ATTR struct_attribute, FPDF_BYTESTRING name, FPDF_BOOL *out_value)
FPDF_EXPORT void FPDF_CALLCONV FPDF_StructTree_Close(FPDF_STRUCTTREE struct_tree)
FPDF_EXPORT FPDF_STRUCTTREE FPDF_CALLCONV FPDF_StructTree_GetForPage(FPDF_PAGE page)
FPDF_EXPORT int FPDF_CALLCONV FPDF_StructElement_GetMarkedContentID(FPDF_STRUCTELEMENT struct_element)
FPDF_EXPORT unsigned long FPDF_CALLCONV FPDF_StructElement_GetStringAttribute(FPDF_STRUCTELEMENT struct_element, FPDF_BYTESTRING attr_name, void *buffer, unsigned long buflen)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_StructElement_Attr_GetBlobValue(FPDF_STRUCTELEMENT_ATTR struct_attribute, FPDF_BYTESTRING name, void *buffer, unsigned long buflen, unsigned long *out_buflen)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_StructElement_Attr_GetName(FPDF_STRUCTELEMENT_ATTR struct_attribute, int index, void *buffer, unsigned long buflen, unsigned long *out_buflen)
FPDF_EXPORT int FPDF_CALLCONV FPDF_StructElement_GetMarkedContentIdAtIndex(FPDF_STRUCTELEMENT struct_element, int index)
FPDF_EXPORT unsigned long FPDF_CALLCONV FPDF_StructElement_GetActualText(FPDF_STRUCTELEMENT struct_element, void *buffer, unsigned long buflen)
FPDF_EXPORT FPDF_STRUCTELEMENT FPDF_CALLCONV FPDF_StructTree_GetChildAtIndex(FPDF_STRUCTTREE struct_tree, int index)
FPDF_EXPORT int FPDF_CALLCONV FPDF_StructElement_Attr_GetCount(FPDF_STRUCTELEMENT_ATTR struct_attribute)
FPDF_EXPORT unsigned long FPDF_CALLCONV FPDF_StructElement_GetID(FPDF_STRUCTELEMENT struct_element, void *buffer, unsigned long buflen)
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_StructElement_Attr_GetNumberValue(FPDF_STRUCTELEMENT_ATTR struct_attribute, FPDF_BYTESTRING name, float *out_value)
FPDF_EXPORT FPDF_STRUCTELEMENT FPDF_CALLCONV FPDF_StructElement_GetChildAtIndex(FPDF_STRUCTELEMENT struct_element, int index)
FPDF_EXPORT unsigned long FPDF_CALLCONV FPDF_StructElement_GetObjType(FPDF_STRUCTELEMENT struct_element, void *buffer, unsigned long buflen)
FPDF_EXPORT FPDF_OBJECT_TYPE FPDF_CALLCONV FPDF_StructElement_Attr_GetType(FPDF_STRUCTELEMENT_ATTR struct_attribute, FPDF_BYTESTRING name)
FPDF_EXPORT FPDF_STRUCTELEMENT_ATTR FPDF_CALLCONV FPDF_StructElement_GetAttributeAtIndex(FPDF_STRUCTELEMENT struct_element, int index)
FPDF_EXPORT unsigned long FPDF_CALLCONV FPDF_StructElement_GetType(FPDF_STRUCTELEMENT struct_element, void *buffer, unsigned long buflen)
FPDF_EXPORT unsigned long FPDF_CALLCONV FPDF_StructElement_GetAltText(FPDF_STRUCTELEMENT struct_element, void *buffer, unsigned long buflen)
FPDF_EXPORT int FPDF_CALLCONV FPDF_StructElement_GetChildMarkedContentID(FPDF_STRUCTELEMENT struct_element, int index)
FPDF_EXPORT int FPDF_CALLCONV FPDF_StructTree_CountChildren(FPDF_STRUCTTREE struct_tree)
FPDF_EXPORT int FPDF_CALLCONV FPDF_StructElement_CountChildren(FPDF_STRUCTELEMENT struct_element)
FPDF_EXPORT int FPDF_CALLCONV FPDF_StructElement_GetMarkedContentIdCount(FPDF_STRUCTELEMENT struct_element)
FPDF_EXPORT unsigned long FPDF_CALLCONV FPDF_StructElement_GetTitle(FPDF_STRUCTELEMENT struct_element, void *buffer, unsigned long buflen)
#define FPDF_CALLCONV
Definition fpdfview.h:227
#define FPDF_EXPORT
Definition fpdfview.h:221
#define FPDF_OBJECT_UNKNOWN
Definition fpdfview.h:36