1 // Copyright 2016 PDFium Authors. All rights reserved.
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_dictionary.h"
11 #include "core/fpdfdoc/cpdf_structelement.h"
12 #include "core/fpdfdoc/cpdf_structtree.h"
13 #include "fpdfsdk/cpdfsdk_helpers.h"
14
15 namespace {
16
WideStringToBuffer(const WideString & str,void * buffer,unsigned long buflen)17 unsigned long WideStringToBuffer(const WideString& str,
18 void* buffer,
19 unsigned long buflen) {
20 if (str.IsEmpty())
21 return 0;
22
23 ByteString encodedStr = str.ToUTF16LE();
24 const unsigned long len = encodedStr.GetLength();
25 if (buffer && len <= buflen)
26 memcpy(buffer, encodedStr.c_str(), len);
27 return len;
28 }
29
30 } // namespace
31
32 FPDF_EXPORT FPDF_STRUCTTREE FPDF_CALLCONV
FPDF_StructTree_GetForPage(FPDF_PAGE page)33 FPDF_StructTree_GetForPage(FPDF_PAGE page) {
34 CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
35 if (!pPage)
36 return nullptr;
37
38 // Caller takes onwership.
39 return FPDFStructTreeFromCPDFStructTree(
40 CPDF_StructTree::LoadPage(pPage->GetDocument(), pPage->GetDict())
41 .release());
42 }
43
44 FPDF_EXPORT void FPDF_CALLCONV
FPDF_StructTree_Close(FPDF_STRUCTTREE struct_tree)45 FPDF_StructTree_Close(FPDF_STRUCTTREE struct_tree) {
46 std::unique_ptr<CPDF_StructTree>(
47 CPDFStructTreeFromFPDFStructTree(struct_tree));
48 }
49
50 FPDF_EXPORT int FPDF_CALLCONV
FPDF_StructTree_CountChildren(FPDF_STRUCTTREE struct_tree)51 FPDF_StructTree_CountChildren(FPDF_STRUCTTREE struct_tree) {
52 CPDF_StructTree* tree = CPDFStructTreeFromFPDFStructTree(struct_tree);
53 if (!tree)
54 return -1;
55
56 pdfium::base::CheckedNumeric<int> tmp_size = tree->CountTopElements();
57 return tmp_size.ValueOrDefault(-1);
58 }
59
60 FPDF_EXPORT FPDF_STRUCTELEMENT FPDF_CALLCONV
FPDF_StructTree_GetChildAtIndex(FPDF_STRUCTTREE struct_tree,int index)61 FPDF_StructTree_GetChildAtIndex(FPDF_STRUCTTREE struct_tree, int index) {
62 CPDF_StructTree* tree = CPDFStructTreeFromFPDFStructTree(struct_tree);
63 if (!tree || index < 0 ||
64 static_cast<size_t>(index) >= tree->CountTopElements()) {
65 return nullptr;
66 }
67 return FPDFStructElementFromCPDFStructElement(
68 tree->GetTopElement(static_cast<size_t>(index)));
69 }
70
71 FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDF_StructElement_GetAltText(FPDF_STRUCTELEMENT struct_element,void * buffer,unsigned long buflen)72 FPDF_StructElement_GetAltText(FPDF_STRUCTELEMENT struct_element,
73 void* buffer,
74 unsigned long buflen) {
75 CPDF_StructElement* elem =
76 CPDFStructElementFromFPDFStructElement(struct_element);
77 return elem ? WideStringToBuffer(elem->GetAltText(), buffer, buflen) : 0;
78 }
79
80 FPDF_EXPORT int FPDF_CALLCONV
FPDF_StructElement_GetMarkedContentID(FPDF_STRUCTELEMENT struct_element)81 FPDF_StructElement_GetMarkedContentID(FPDF_STRUCTELEMENT struct_element) {
82 CPDF_StructElement* elem =
83 CPDFStructElementFromFPDFStructElement(struct_element);
84 const CPDF_Object* p = elem ? elem->GetDict()->GetObjectFor("K") : nullptr;
85 return p && p->IsNumber() ? p->GetInteger() : -1;
86 }
87
88 FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDF_StructElement_GetType(FPDF_STRUCTELEMENT struct_element,void * buffer,unsigned long buflen)89 FPDF_StructElement_GetType(FPDF_STRUCTELEMENT struct_element,
90 void* buffer,
91 unsigned long buflen) {
92 CPDF_StructElement* elem =
93 CPDFStructElementFromFPDFStructElement(struct_element);
94 return elem ? WideStringToBuffer(
95 WideString::FromUTF8(elem->GetType().AsStringView()),
96 buffer, buflen)
97 : 0;
98 }
99
100 FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDF_StructElement_GetTitle(FPDF_STRUCTELEMENT struct_element,void * buffer,unsigned long buflen)101 FPDF_StructElement_GetTitle(FPDF_STRUCTELEMENT struct_element,
102 void* buffer,
103 unsigned long buflen) {
104 CPDF_StructElement* elem =
105 CPDFStructElementFromFPDFStructElement(struct_element);
106 return elem ? WideStringToBuffer(elem->GetTitle(), buffer, buflen) : 0;
107 }
108
109 FPDF_EXPORT int FPDF_CALLCONV
FPDF_StructElement_CountChildren(FPDF_STRUCTELEMENT struct_element)110 FPDF_StructElement_CountChildren(FPDF_STRUCTELEMENT struct_element) {
111 CPDF_StructElement* elem =
112 CPDFStructElementFromFPDFStructElement(struct_element);
113 if (!elem)
114 return -1;
115
116 pdfium::base::CheckedNumeric<int> tmp_size = elem->CountKids();
117 return tmp_size.ValueOrDefault(-1);
118 }
119
120 FPDF_EXPORT FPDF_STRUCTELEMENT FPDF_CALLCONV
FPDF_StructElement_GetChildAtIndex(FPDF_STRUCTELEMENT struct_element,int index)121 FPDF_StructElement_GetChildAtIndex(FPDF_STRUCTELEMENT struct_element,
122 int index) {
123 CPDF_StructElement* elem =
124 CPDFStructElementFromFPDFStructElement(struct_element);
125 if (!elem || index < 0 || static_cast<size_t>(index) >= elem->CountKids())
126 return nullptr;
127
128 return FPDFStructElementFromCPDFStructElement(
129 elem->GetKidIfElement(static_cast<size_t>(index)));
130 }
131