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