1e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov// Copyright 2014 PDFium Authors. All rights reserved.
2e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov// Use of this source code is governed by a BSD-style license that can be
3e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov// found in the LICENSE file.
4e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
5e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
6e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov
7e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include "../../include/fpdfapi/fpdf_parser.h"
8e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include "../../include/fpdfapi/fpdf_page.h"
9e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include "../../include/fpdfdoc/fpdf_tagged.h"
10e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov#include "tagged_int.h"
11e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovconst int nMaxRecursion = 32;
12e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovstatic FX_BOOL IsTagged(const CPDF_Document* pDoc)
13e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
14e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    CPDF_Dictionary* pCatalog = pDoc->GetRoot();
15e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    CPDF_Dictionary* pMarkInfo = pCatalog->GetDict(FX_BSTRC("MarkInfo"));
16e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    return pMarkInfo != NULL && pMarkInfo->GetInteger(FX_BSTRC("Marked"));
17e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
18e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovCPDF_StructTree* CPDF_StructTree::LoadPage(const CPDF_Document* pDoc, const CPDF_Dictionary* pPageDict)
19e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
20e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (!IsTagged(pDoc)) {
21e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        return NULL;
22e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
23e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    CPDF_StructTreeImpl* pTree = new CPDF_StructTreeImpl(pDoc);
24e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    pTree->LoadPageTree(pPageDict);
25e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    return pTree;
26e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
27e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovCPDF_StructTree* CPDF_StructTree::LoadDoc(const CPDF_Document* pDoc)
28e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
29e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (!IsTagged(pDoc)) {
30e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        return NULL;
31e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
32e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    CPDF_StructTreeImpl* pTree = new CPDF_StructTreeImpl(pDoc);
33e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    pTree->LoadDocTree();
34e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    return pTree;
35e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
36e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovCPDF_StructTreeImpl::CPDF_StructTreeImpl(const CPDF_Document* pDoc)
37e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
38e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    CPDF_Dictionary* pCatalog = pDoc->GetRoot();
39e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    m_pTreeRoot = pCatalog->GetDict(FX_BSTRC("StructTreeRoot"));
40e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (m_pTreeRoot == NULL) {
41e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        return;
42e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
43e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    m_pRoleMap = m_pTreeRoot->GetDict(FX_BSTRC("RoleMap"));
44e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
45e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovCPDF_StructTreeImpl::~CPDF_StructTreeImpl()
46e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
47e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    for (int i = 0; i < m_Kids.GetSize(); i ++)
48e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        if (m_Kids[i]) {
49e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            m_Kids[i]->Release();
50e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
51e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
52e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovvoid CPDF_StructTreeImpl::LoadDocTree()
53e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
54e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    m_pPage = NULL;
55e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (m_pTreeRoot == NULL) {
56e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        return;
57e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
58e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    CPDF_Object* pKids = m_pTreeRoot->GetElementValue(FX_BSTRC("K"));
59e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (pKids == NULL) {
60e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        return;
61e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
62e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (pKids->GetType() == PDFOBJ_DICTIONARY) {
63e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        CPDF_StructElementImpl* pStructElementImpl = new CPDF_StructElementImpl(this, NULL, (CPDF_Dictionary*)pKids);
64e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        m_Kids.Add(pStructElementImpl);
65e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        return;
66e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
67e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (pKids->GetType() != PDFOBJ_ARRAY) {
68e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        return;
69e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
70e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    CPDF_Array* pArray = (CPDF_Array*)pKids;
71e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    for (FX_DWORD i = 0; i < pArray->GetCount(); i ++) {
72e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        CPDF_Dictionary* pKid = pArray->GetDict(i);
73e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        CPDF_StructElementImpl* pStructElementImpl = new CPDF_StructElementImpl(this, NULL, pKid);
74e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        m_Kids.Add(pStructElementImpl);
75e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
76e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
77e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovvoid CPDF_StructTreeImpl::LoadPageTree(const CPDF_Dictionary* pPageDict)
78e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
79e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    m_pPage = pPageDict;
80e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (m_pTreeRoot == NULL) {
81e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        return;
82e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
83e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    CPDF_Object* pKids = m_pTreeRoot->GetElementValue(FX_BSTRC("K"));
84e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (pKids == NULL) {
85e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        return;
86e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
87e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    FX_DWORD dwKids = 0;
88e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (pKids->GetType() == PDFOBJ_DICTIONARY) {
89e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        dwKids = 1;
90e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    } else if (pKids->GetType() == PDFOBJ_ARRAY) {
91e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        dwKids = ((CPDF_Array*)pKids)->GetCount();
92e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    } else {
93e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        return;
94e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
95e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    FX_DWORD i;
96e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    m_Kids.SetSize(dwKids);
97e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    for (i = 0; i < dwKids; i ++) {
98e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        m_Kids[i] = NULL;
99e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
100e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    CFX_MapPtrToPtr element_map;
101e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    CPDF_Dictionary* pParentTree = m_pTreeRoot->GetDict(FX_BSTRC("ParentTree"));
102e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (pParentTree == NULL) {
103e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        return;
104e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
105e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    CPDF_NumberTree parent_tree(pParentTree);
106e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    int parents_id = pPageDict->GetInteger(FX_BSTRC("StructParents"), -1);
107e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (parents_id >= 0) {
108e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        CPDF_Object* pParents = parent_tree.LookupValue(parents_id);
109e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        if (pParents == NULL || pParents->GetType() != PDFOBJ_ARRAY) {
110e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            return;
111e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
112e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        CPDF_Array* pParentArray = (CPDF_Array*)pParents;
113e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        for (i = 0; i < pParentArray->GetCount(); i ++) {
114e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            CPDF_Dictionary* pParent = pParentArray->GetDict(i);
115e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            if (pParent == NULL) {
116e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                continue;
117e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            }
118e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            AddPageNode(pParent, element_map);
119e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
120e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
121e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
122e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovCPDF_StructElementImpl* CPDF_StructTreeImpl::AddPageNode(CPDF_Dictionary* pDict, CFX_MapPtrToPtr& map, int nLevel)
123e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
124e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (nLevel > nMaxRecursion) {
125e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        return NULL;
126e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
127e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    CPDF_StructElementImpl* pElement = NULL;
128e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (map.Lookup(pDict, (FX_LPVOID&)pElement)) {
129e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        return pElement;
130e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
131e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    pElement = new CPDF_StructElementImpl(this, NULL, pDict);
132e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    map.SetAt(pDict, pElement);
133e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    CPDF_Dictionary* pParent = pDict->GetDict(FX_BSTRC("P"));
134e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (pParent == NULL || pParent->GetString(FX_BSTRC("Type")) == FX_BSTRC("StructTreeRoot")) {
135e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        if (!AddTopLevelNode(pDict, pElement)) {
136e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            pElement->Release();
137e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            map.RemoveKey(pDict);
138e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
139e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    } else {
140e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        CPDF_StructElementImpl* pParentElement = AddPageNode(pParent, map, nLevel + 1);
141e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        FX_BOOL bSave = FALSE;
142e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        for (int i = 0; i < pParentElement->m_Kids.GetSize(); i ++) {
143e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            if (pParentElement->m_Kids[i].m_Type != CPDF_StructKid::Element) {
144e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                continue;
145e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            }
146e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            if (pParentElement->m_Kids[i].m_Element.m_pDict != pDict) {
147e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                continue;
148e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            }
149e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            pParentElement->m_Kids[i].m_Element.m_pElement = pElement->Retain();
150e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            bSave = TRUE;
151e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
152e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        if (!bSave) {
153e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            pElement->Release();
154e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            map.RemoveKey(pDict);
155e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
156e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
157e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    return pElement;
158e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
159e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovFX_BOOL CPDF_StructTreeImpl::AddTopLevelNode(CPDF_Dictionary* pDict, CPDF_StructElementImpl* pElement)
160e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
161e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    CPDF_Object *pObj = m_pTreeRoot->GetElementValue(FX_BSTRC("K"));
162e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (!pObj) {
163e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        return FALSE;
164e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
165e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (pObj->GetType() == PDFOBJ_DICTIONARY) {
166e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        if (pObj->GetObjNum() == pDict->GetObjNum()) {
167e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            if (m_Kids[0]) {
168e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                m_Kids[0]->Release();
169e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            }
170e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            m_Kids[0] = pElement->Retain();
171e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        } else {
172e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            return FALSE;
173e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
174e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
175e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (pObj->GetType() == PDFOBJ_ARRAY) {
176e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        CPDF_Array* pTopKids = (CPDF_Array*)pObj;
177e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        FX_DWORD i;
178e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        FX_BOOL bSave = FALSE;
179e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        for (i = 0; i < pTopKids->GetCount(); i ++) {
180e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            CPDF_Object* pKidRef = pTopKids->GetElement(i);
181e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            if (pKidRef == NULL || pKidRef->GetType() != PDFOBJ_REFERENCE) {
182e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                continue;
183e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            }
184e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            if (((CPDF_Reference*) pKidRef)->GetRefObjNum() != pDict->GetObjNum()) {
185e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                continue;
186e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            }
187e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            if (m_Kids[i]) {
188e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                m_Kids[i]->Release();
189e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            }
190e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            m_Kids[i] = pElement->Retain();
191e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            bSave = TRUE;
192e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
193e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        if (!bSave) {
194e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            return FALSE;
195e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
196e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
197e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    return TRUE;
198e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
199e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovCPDF_StructElementImpl::CPDF_StructElementImpl(CPDF_StructTreeImpl* pTree, CPDF_StructElementImpl* pParent, CPDF_Dictionary* pDict)
200e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    : m_RefCount(0)
201e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
202e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    m_pTree = pTree;
203e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    m_pDict = pDict;
204e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    m_Type = pDict->GetString(FX_BSTRC("S"));
205e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (pTree->m_pRoleMap) {
206e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        CFX_ByteString mapped = pTree->m_pRoleMap->GetString(m_Type);
207e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        if (!mapped.IsEmpty()) {
208e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            m_Type = mapped;
209e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
210e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
211e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    m_pParent = pParent;
212e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    LoadKids(pDict);
213e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
214e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovCPDF_StructElementImpl::~CPDF_StructElementImpl()
215e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
216e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    for (int i = 0; i < m_Kids.GetSize(); i ++) {
217e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        if (m_Kids[i].m_Type == CPDF_StructKid::Element && m_Kids[i].m_Element.m_pElement) {
218e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            ((CPDF_StructElementImpl*)m_Kids[i].m_Element.m_pElement)->Release();
219e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
220e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
221e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
222e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovCPDF_StructElementImpl* CPDF_StructElementImpl::Retain()
223e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
224e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    m_RefCount++;
225e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    return this;
226e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
227e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovvoid CPDF_StructElementImpl::Release()
228e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
229e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if(--m_RefCount < 1) {
230e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        delete this;
231e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
232e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
233e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovvoid CPDF_StructElementImpl::LoadKids(CPDF_Dictionary* pDict)
234e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
235e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    CPDF_Object* pObj = pDict->GetElement(FX_BSTRC("Pg"));
236e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    FX_DWORD PageObjNum = 0;
237e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (pObj && pObj->GetType() == PDFOBJ_REFERENCE) {
238e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        PageObjNum = ((CPDF_Reference*)pObj)->GetRefObjNum();
239e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
240e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    CPDF_Object* pKids = pDict->GetElementValue(FX_BSTRC("K"));
241e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (pKids == NULL) {
242e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        return;
243e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
244e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (pKids->GetType() == PDFOBJ_ARRAY) {
245e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        CPDF_Array* pArray = (CPDF_Array*)pKids;
246e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        m_Kids.SetSize(pArray->GetCount());
247e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        for (FX_DWORD i = 0; i < pArray->GetCount(); i ++) {
248e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            CPDF_Object* pKid = pArray->GetElementValue(i);
249e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            LoadKid(PageObjNum, pKid, &m_Kids[i]);
250e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
251e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    } else {
252e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        m_Kids.SetSize(1);
253e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        LoadKid(PageObjNum, pKids, &m_Kids[0]);
254e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
255e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
256e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovvoid CPDF_StructElementImpl::LoadKid(FX_DWORD PageObjNum, CPDF_Object* pKidObj, CPDF_StructKid* pKid)
257e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
258e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    pKid->m_Type = CPDF_StructKid::Invalid;
259e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (pKidObj == NULL) {
260e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        return;
261e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
262e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (pKidObj->GetType() == PDFOBJ_NUMBER) {
263e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        if (m_pTree->m_pPage && m_pTree->m_pPage->GetObjNum() != PageObjNum) {
264e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            return;
265e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
266e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        pKid->m_Type = CPDF_StructKid::PageContent;
267e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        pKid->m_PageContent.m_ContentId = pKidObj->GetInteger();
268e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        pKid->m_PageContent.m_PageObjNum = PageObjNum;
269e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        return;
270e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
271e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (pKidObj->GetType() != PDFOBJ_DICTIONARY) {
272e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        return;
273e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
274e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    CPDF_Dictionary* pKidDict = (CPDF_Dictionary*)pKidObj;
275e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    CPDF_Object* pPageObj = pKidDict->GetElement(FX_BSTRC("Pg"));
276e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (pPageObj && pPageObj->GetType() == PDFOBJ_REFERENCE) {
277e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        PageObjNum = ((CPDF_Reference*)pPageObj)->GetRefObjNum();
278e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
279e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    CFX_ByteString type = pKidDict->GetString(FX_BSTRC("Type"));
280e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (type == FX_BSTRC("MCR")) {
281e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        if (m_pTree->m_pPage && m_pTree->m_pPage->GetObjNum() != PageObjNum) {
282e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            return;
283e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
284e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        pKid->m_Type = CPDF_StructKid::StreamContent;
285e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        CPDF_Object* pStreamObj = pKidDict->GetElement(FX_BSTRC("Stm"));
286e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        if (pStreamObj && pStreamObj->GetType() == PDFOBJ_REFERENCE) {
287e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            pKid->m_StreamContent.m_RefObjNum = ((CPDF_Reference*)pStreamObj)->GetRefObjNum();
288e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        } else {
289e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            pKid->m_StreamContent.m_RefObjNum = 0;
290e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
291e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        pKid->m_StreamContent.m_PageObjNum = PageObjNum;
292e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        pKid->m_StreamContent.m_ContentId = pKidDict->GetInteger(FX_BSTRC("MCID"));
293e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    } else if (type == FX_BSTRC("OBJR")) {
294e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        if (m_pTree->m_pPage && m_pTree->m_pPage->GetObjNum() != PageObjNum) {
295e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            return;
296e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
297e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        pKid->m_Type = CPDF_StructKid::Object;
298e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        CPDF_Object* pObj = pKidDict->GetElement(FX_BSTRC("Obj"));
299e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        if (pObj && pObj->GetType() == PDFOBJ_REFERENCE) {
300e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            pKid->m_Object.m_RefObjNum = ((CPDF_Reference*)pObj)->GetRefObjNum();
301e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        } else {
302e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            pKid->m_Object.m_RefObjNum = 0;
303e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
304e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        pKid->m_Object.m_PageObjNum = PageObjNum;
305e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    } else {
306e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        pKid->m_Type = CPDF_StructKid::Element;
307e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        pKid->m_Element.m_pDict = pKidDict;
308e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        if (m_pTree->m_pPage == NULL) {
309e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            pKid->m_Element.m_pElement = new CPDF_StructElementImpl(m_pTree, this, pKidDict);
310e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        } else {
311e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            pKid->m_Element.m_pElement = NULL;
312e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
313e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
314e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
315e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovstatic CPDF_Dictionary* FindAttrDict(CPDF_Object* pAttrs, FX_BSTR owner, FX_FLOAT nLevel = 0.0F)
316e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
317e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (nLevel > nMaxRecursion) {
318e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        return NULL;
319e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
320e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (pAttrs == NULL) {
321e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        return NULL;
322e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
323e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    CPDF_Dictionary* pDict = NULL;
324e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (pAttrs->GetType() == PDFOBJ_DICTIONARY) {
325e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        pDict = (CPDF_Dictionary*)pAttrs;
326e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    } else if (pAttrs->GetType() == PDFOBJ_STREAM) {
327e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        pDict = ((CPDF_Stream*)pAttrs)->GetDict();
328e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    } else if (pAttrs->GetType() == PDFOBJ_ARRAY) {
329e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        CPDF_Array* pArray = (CPDF_Array*)pAttrs;
330e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        for (FX_DWORD i = 0; i < pArray->GetCount(); i ++) {
331e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            CPDF_Object* pElement = pArray->GetElementValue(i);
332e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            pDict = FindAttrDict(pElement, owner, nLevel + 1);
333e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            if (pDict) {
334e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                return pDict;
335e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            }
336e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
337e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
338e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (pDict && pDict->GetString(FX_BSTRC("O")) == owner) {
339e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        return pDict;
340e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
341e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    return NULL;
342e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
343e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovCPDF_Object* CPDF_StructElementImpl::GetAttr(FX_BSTR owner, FX_BSTR name, FX_BOOL bInheritable, FX_FLOAT fLevel)
344e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
345e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (fLevel > nMaxRecursion) {
346e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        return NULL;
347e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
348e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (bInheritable) {
349e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        CPDF_Object* pAttr = GetAttr(owner, name, FALSE);
350e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        if (pAttr) {
351e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            return pAttr;
352e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
353e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        if (m_pParent == NULL) {
354e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            return NULL;
355e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
356e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        return m_pParent->GetAttr(owner, name, TRUE, fLevel + 1);
357e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
358e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    CPDF_Object* pA = m_pDict->GetElementValue(FX_BSTRC("A"));
359e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (pA) {
360e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        CPDF_Dictionary* pAttrDict = FindAttrDict(pA, owner);
361e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        if (pAttrDict) {
362e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            CPDF_Object* pAttr = pAttrDict->GetElementValue(name);
363e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            if (pAttr) {
364e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                return pAttr;
365e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            }
366e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
367e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
368e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    CPDF_Object* pC = m_pDict->GetElementValue(FX_BSTRC("C"));
369e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (pC == NULL) {
370e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        return NULL;
371e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
372e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    CPDF_Dictionary* pClassMap = m_pTree->m_pTreeRoot->GetDict(FX_BSTRC("ClassMap"));
373e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (pClassMap == NULL) {
374e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        return NULL;
375e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
376e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (pC->GetType() == PDFOBJ_ARRAY) {
377e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        CPDF_Array* pArray = (CPDF_Array*)pC;
378e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        for (FX_DWORD i = 0; i < pArray->GetCount(); i ++) {
379e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            CFX_ByteString class_name = pArray->GetString(i);
380e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            CPDF_Dictionary* pClassDict = pClassMap->GetDict(class_name);
381e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            if (pClassDict && pClassDict->GetString(FX_BSTRC("O")) == owner) {
382e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov                return pClassDict->GetElementValue(name);
383e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov            }
384e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        }
385e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        return NULL;
386e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
387e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    CFX_ByteString class_name = pC->GetString();
388e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    CPDF_Dictionary* pClassDict = pClassMap->GetDict(class_name);
389e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (pClassDict && pClassDict->GetString(FX_BSTRC("O")) == owner) {
390e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        return pClassDict->GetElementValue(name);
391e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
392e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    return NULL;
393e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
394e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovCPDF_Object* CPDF_StructElementImpl::GetAttr(FX_BSTR owner, FX_BSTR name, FX_BOOL bInheritable, int subindex)
395e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
396e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    CPDF_Object* pAttr = GetAttr(owner, name, bInheritable);
397e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (pAttr == NULL || subindex == -1 || pAttr->GetType() != PDFOBJ_ARRAY) {
398e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        return pAttr;
399e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
400e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    CPDF_Array* pArray = (CPDF_Array*)pAttr;
401e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (subindex >= (int)pArray->GetCount()) {
402e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        return pAttr;
403e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
404e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    return pArray->GetElementValue(subindex);
405e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
406e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovCFX_ByteString CPDF_StructElementImpl::GetName(FX_BSTR owner, FX_BSTR name, FX_BSTR default_value, FX_BOOL bInheritable, int subindex)
407e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
408e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    CPDF_Object* pAttr = GetAttr(owner, name, bInheritable, subindex);
409e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (pAttr == NULL || pAttr->GetType() != PDFOBJ_NAME) {
410e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        return default_value;
411e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
412e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    return pAttr->GetString();
413e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
414e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovFX_ARGB	CPDF_StructElementImpl::GetColor(FX_BSTR owner, FX_BSTR name, FX_ARGB default_value, FX_BOOL bInheritable, int subindex)
415e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
416e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    CPDF_Object* pAttr = GetAttr(owner, name, bInheritable, subindex);
417e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (pAttr == NULL || pAttr->GetType() != PDFOBJ_ARRAY) {
418e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        return default_value;
419e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
420e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    CPDF_Array* pArray = (CPDF_Array*)pAttr;
421e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    return 0xff000000 | ((int)(pArray->GetNumber(0) * 255) << 16) | ((int)(pArray->GetNumber(1) * 255) << 8) | (int)(pArray->GetNumber(2) * 255);
422e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
423e6986e1e8d4a57987f47c215490cb080a65ee29aSvet GanovFX_FLOAT CPDF_StructElementImpl::GetNumber(FX_BSTR owner, FX_BSTR name, FX_FLOAT default_value, FX_BOOL bInheritable, int subindex)
424e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
425e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    CPDF_Object* pAttr = GetAttr(owner, name, bInheritable, subindex);
426e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (pAttr == NULL || pAttr->GetType() != PDFOBJ_NUMBER) {
427e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        return default_value;
428e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
429e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    return pAttr->GetNumber();
430e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
431e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganovint	CPDF_StructElementImpl::GetInteger(FX_BSTR owner, FX_BSTR name, int default_value, FX_BOOL bInheritable, int subindex)
432e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov{
433e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    CPDF_Object* pAttr = GetAttr(owner, name, bInheritable, subindex);
434e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    if (pAttr == NULL || pAttr->GetType() != PDFOBJ_NUMBER) {
435e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov        return default_value;
436e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    }
437e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov    return pAttr->GetInteger();
438e6986e1e8d4a57987f47c215490cb080a65ee29aSvet Ganov}
439