Home | History | Annotate | Download | only in fpdfsdk
      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 
     17 CPDF_StructTree* ToStructTree(FPDF_STRUCTTREE struct_tree) {
     18   return static_cast<CPDF_StructTree*>(struct_tree);
     19 }
     20 
     21 CPDF_StructElement* ToStructTreeElement(FPDF_STRUCTELEMENT struct_element) {
     22   return static_cast<CPDF_StructElement*>(struct_element);
     23 }
     24 
     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
     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
     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
     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
     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
     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
     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
     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
    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
    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
    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