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