summaryrefslogtreecommitdiff
path: root/core/src/fpdfdoc/doc_tagged.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/src/fpdfdoc/doc_tagged.cpp')
-rw-r--r--core/src/fpdfdoc/doc_tagged.cpp896
1 files changed, 448 insertions, 448 deletions
diff --git a/core/src/fpdfdoc/doc_tagged.cpp b/core/src/fpdfdoc/doc_tagged.cpp
index 95ae8d581e..551042037b 100644
--- a/core/src/fpdfdoc/doc_tagged.cpp
+++ b/core/src/fpdfdoc/doc_tagged.cpp
@@ -1,448 +1,448 @@
-// Copyright 2014 PDFium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
-
-#include "../../include/fpdfapi/fpdf_parser.h"
-#include "../../include/fpdfapi/fpdf_page.h"
-#include "../../include/fpdfdoc/fpdf_tagged.h"
-#include "tagged_int.h"
-const int nMaxRecursion = 32;
-static FX_BOOL IsTagged(const CPDF_Document* pDoc)
-{
- CPDF_Dictionary* pCatalog = pDoc->GetRoot();
- CPDF_Dictionary* pMarkInfo = pCatalog->GetDict(FX_BSTRC("MarkInfo"));
- return pMarkInfo != NULL && pMarkInfo->GetInteger(FX_BSTRC("Marked"));
-}
-CPDF_StructTree* CPDF_StructTree::LoadPage(const CPDF_Document* pDoc, const CPDF_Dictionary* pPageDict)
-{
- if (!IsTagged(pDoc)) {
- return NULL;
- }
- CPDF_StructTreeImpl* pTree = FX_NEW CPDF_StructTreeImpl(pDoc);
- if (pTree == NULL) {
- return NULL;
- }
- pTree->LoadPageTree(pPageDict);
- return pTree;
-}
-CPDF_StructTree* CPDF_StructTree::LoadDoc(const CPDF_Document* pDoc)
-{
- if (!IsTagged(pDoc)) {
- return NULL;
- }
- CPDF_StructTreeImpl* pTree = FX_NEW CPDF_StructTreeImpl(pDoc);
- if (pTree == NULL) {
- return NULL;
- }
- pTree->LoadDocTree();
- return pTree;
-}
-CPDF_StructTreeImpl::CPDF_StructTreeImpl(const CPDF_Document* pDoc)
-{
- CPDF_Dictionary* pCatalog = pDoc->GetRoot();
- m_pTreeRoot = pCatalog->GetDict(FX_BSTRC("StructTreeRoot"));
- if (m_pTreeRoot == NULL) {
- return;
- }
- m_pRoleMap = m_pTreeRoot->GetDict(FX_BSTRC("RoleMap"));
-}
-CPDF_StructTreeImpl::~CPDF_StructTreeImpl()
-{
- for (int i = 0; i < m_Kids.GetSize(); i ++)
- if (m_Kids[i]) {
- m_Kids[i]->Release();
- }
-}
-void CPDF_StructTreeImpl::LoadDocTree()
-{
- m_pPage = NULL;
- if (m_pTreeRoot == NULL) {
- return;
- }
- CPDF_Object* pKids = m_pTreeRoot->GetElementValue(FX_BSTRC("K"));
- if (pKids == NULL) {
- return;
- }
- if (pKids->GetType() == PDFOBJ_DICTIONARY) {
- CPDF_StructElementImpl* pStructElementImpl = FX_NEW CPDF_StructElementImpl(this, NULL, (CPDF_Dictionary*)pKids);
- if (pStructElementImpl == NULL) {
- return;
- }
- m_Kids.Add(pStructElementImpl);
- return;
- }
- if (pKids->GetType() != PDFOBJ_ARRAY) {
- return;
- }
- CPDF_Array* pArray = (CPDF_Array*)pKids;
- for (FX_DWORD i = 0; i < pArray->GetCount(); i ++) {
- CPDF_Dictionary* pKid = pArray->GetDict(i);
- CPDF_StructElementImpl* pStructElementImpl = FX_NEW CPDF_StructElementImpl(this, NULL, pKid);
- if (pStructElementImpl == NULL) {
- return;
- }
- m_Kids.Add(pStructElementImpl);
- }
-}
-void CPDF_StructTreeImpl::LoadPageTree(const CPDF_Dictionary* pPageDict)
-{
- m_pPage = pPageDict;
- if (m_pTreeRoot == NULL) {
- return;
- }
- CPDF_Object* pKids = m_pTreeRoot->GetElementValue(FX_BSTRC("K"));
- if (pKids == NULL) {
- return;
- }
- FX_DWORD dwKids = 0;
- if (pKids->GetType() == PDFOBJ_DICTIONARY) {
- dwKids = 1;
- } else if (pKids->GetType() == PDFOBJ_ARRAY) {
- dwKids = ((CPDF_Array*)pKids)->GetCount();
- } else {
- return;
- }
- FX_DWORD i;
- m_Kids.SetSize(dwKids);
- for (i = 0; i < dwKids; i ++) {
- m_Kids[i] = NULL;
- }
- CFX_MapPtrToPtr element_map;
- CPDF_Dictionary* pParentTree = m_pTreeRoot->GetDict(FX_BSTRC("ParentTree"));
- if (pParentTree == NULL) {
- return;
- }
- CPDF_NumberTree parent_tree(pParentTree);
- int parents_id = pPageDict->GetInteger(FX_BSTRC("StructParents"), -1);
- if (parents_id >= 0) {
- CPDF_Object* pParents = parent_tree.LookupValue(parents_id);
- if (pParents == NULL || pParents->GetType() != PDFOBJ_ARRAY) {
- return;
- }
- CPDF_Array* pParentArray = (CPDF_Array*)pParents;
- for (i = 0; i < pParentArray->GetCount(); i ++) {
- CPDF_Dictionary* pParent = pParentArray->GetDict(i);
- if (pParent == NULL) {
- continue;
- }
- AddPageNode(pParent, element_map);
- }
- }
-}
-CPDF_StructElementImpl* CPDF_StructTreeImpl::AddPageNode(CPDF_Dictionary* pDict, CFX_MapPtrToPtr& map, int nLevel)
-{
- if (nLevel > nMaxRecursion) {
- return NULL;
- }
- CPDF_StructElementImpl* pElement = NULL;
- if (map.Lookup(pDict, (FX_LPVOID&)pElement)) {
- return pElement;
- }
- pElement = FX_NEW CPDF_StructElementImpl(this, NULL, pDict);
- if (pElement == NULL) {
- return NULL;
- }
- map.SetAt(pDict, pElement);
- CPDF_Dictionary* pParent = pDict->GetDict(FX_BSTRC("P"));
- if (pParent == NULL || pParent->GetString(FX_BSTRC("Type")) == FX_BSTRC("StructTreeRoot")) {
- if (!AddTopLevelNode(pDict, pElement)) {
- pElement->Release();
- map.RemoveKey(pDict);
- }
- } else {
- CPDF_StructElementImpl* pParentElement = AddPageNode(pParent, map, nLevel + 1);
- FX_BOOL bSave = FALSE;
- for (int i = 0; i < pParentElement->m_Kids.GetSize(); i ++) {
- if (pParentElement->m_Kids[i].m_Type != CPDF_StructKid::Element) {
- continue;
- }
- if (pParentElement->m_Kids[i].m_Element.m_pDict != pDict) {
- continue;
- }
- pParentElement->m_Kids[i].m_Element.m_pElement = pElement->Retain();
- bSave = TRUE;
- }
- if (!bSave) {
- pElement->Release();
- map.RemoveKey(pDict);
- }
- }
- return pElement;
-}
-FX_BOOL CPDF_StructTreeImpl::AddTopLevelNode(CPDF_Dictionary* pDict, CPDF_StructElementImpl* pElement)
-{
- CPDF_Object *pObj = m_pTreeRoot->GetElementValue(FX_BSTRC("K"));
- if (!pObj) {
- return FALSE;
- }
- if (pObj->GetType() == PDFOBJ_DICTIONARY) {
- if (pObj->GetObjNum() == pDict->GetObjNum()) {
- if (m_Kids[0]) {
- m_Kids[0]->Release();
- }
- m_Kids[0] = pElement->Retain();
- } else {
- return FALSE;
- }
- }
- if (pObj->GetType() == PDFOBJ_ARRAY) {
- CPDF_Array* pTopKids = (CPDF_Array*)pObj;
- FX_DWORD i;
- FX_BOOL bSave = FALSE;
- for (i = 0; i < pTopKids->GetCount(); i ++) {
- CPDF_Reference* pKidRef = (CPDF_Reference*)pTopKids->GetElement(i);
- if (pKidRef->GetType() != PDFOBJ_REFERENCE || pKidRef->GetRefObjNum() != pDict->GetObjNum()) {
- continue;
- }
- if (m_Kids[i]) {
- m_Kids[i]->Release();
- }
- m_Kids[i] = pElement->Retain();
- bSave = TRUE;
- }
- if (!bSave) {
- return FALSE;
- }
- }
- return TRUE;
-}
-CPDF_StructElementImpl::CPDF_StructElementImpl(CPDF_StructTreeImpl* pTree, CPDF_StructElementImpl* pParent, CPDF_Dictionary* pDict)
- : m_RefCount(0)
-{
- m_pTree = pTree;
- m_pDict = pDict;
- m_Type = pDict->GetString(FX_BSTRC("S"));
- CFX_ByteString mapped = pTree->m_pRoleMap->GetString(m_Type);
- if (!mapped.IsEmpty()) {
- m_Type = mapped;
- }
- m_pParent = pParent;
- LoadKids(pDict);
-}
-CPDF_StructElementImpl::~CPDF_StructElementImpl()
-{
- for (int i = 0; i < m_Kids.GetSize(); i ++) {
- if (m_Kids[i].m_Type == CPDF_StructKid::Element && m_Kids[i].m_Element.m_pElement) {
- ((CPDF_StructElementImpl*)m_Kids[i].m_Element.m_pElement)->Release();
- }
- }
-}
-CPDF_StructElementImpl* CPDF_StructElementImpl::Retain()
-{
- m_RefCount++;
- return this;
-}
-void CPDF_StructElementImpl::Release()
-{
- if(--m_RefCount < 1) {
- delete this;
- }
-}
-void CPDF_StructElementImpl::LoadKids(CPDF_Dictionary* pDict)
-{
- CPDF_Object* pObj = pDict->GetElement(FX_BSTRC("Pg"));
- FX_DWORD PageObjNum = 0;
- if (pObj && pObj->GetType() == PDFOBJ_REFERENCE) {
- PageObjNum = ((CPDF_Reference*)pObj)->GetRefObjNum();
- }
- CPDF_Object* pKids = pDict->GetElementValue(FX_BSTRC("K"));
- if (pKids == NULL) {
- return;
- }
- if (pKids->GetType() == PDFOBJ_ARRAY) {
- CPDF_Array* pArray = (CPDF_Array*)pKids;
- m_Kids.SetSize(pArray->GetCount());
- for (FX_DWORD i = 0; i < pArray->GetCount(); i ++) {
- CPDF_Object* pKid = pArray->GetElementValue(i);
- LoadKid(PageObjNum, pKid, &m_Kids[i]);
- }
- } else {
- m_Kids.SetSize(1);
- LoadKid(PageObjNum, pKids, &m_Kids[0]);
- }
-}
-void CPDF_StructElementImpl::LoadKid(FX_DWORD PageObjNum, CPDF_Object* pKidObj, CPDF_StructKid* pKid)
-{
- pKid->m_Type = CPDF_StructKid::Invalid;
- if (pKidObj == NULL) {
- return;
- }
- if (pKidObj->GetType() == PDFOBJ_NUMBER) {
- if (m_pTree->m_pPage && m_pTree->m_pPage->GetObjNum() != PageObjNum) {
- return;
- }
- pKid->m_Type = CPDF_StructKid::PageContent;
- pKid->m_PageContent.m_ContentId = pKidObj->GetInteger();
- pKid->m_PageContent.m_PageObjNum = PageObjNum;
- return;
- }
- if (pKidObj->GetType() != PDFOBJ_DICTIONARY) {
- return;
- }
- CPDF_Dictionary* pKidDict = (CPDF_Dictionary*)pKidObj;
- CPDF_Object* pPageObj = pKidDict->GetElement(FX_BSTRC("Pg"));
- if (pPageObj && pPageObj->GetType() == PDFOBJ_REFERENCE) {
- PageObjNum = ((CPDF_Reference*)pPageObj)->GetRefObjNum();
- }
- CFX_ByteString type = pKidDict->GetString(FX_BSTRC("Type"));
- if (type == FX_BSTRC("MCR")) {
- if (m_pTree->m_pPage && m_pTree->m_pPage->GetObjNum() != PageObjNum) {
- return;
- }
- pKid->m_Type = CPDF_StructKid::StreamContent;
- CPDF_Object* pStreamObj = pKidDict->GetElement(FX_BSTRC("Stm"));
- if (pStreamObj && pStreamObj->GetType() == PDFOBJ_REFERENCE) {
- pKid->m_StreamContent.m_RefObjNum = ((CPDF_Reference*)pStreamObj)->GetRefObjNum();
- } else {
- pKid->m_StreamContent.m_RefObjNum = 0;
- }
- pKid->m_StreamContent.m_PageObjNum = PageObjNum;
- pKid->m_StreamContent.m_ContentId = pKidDict->GetInteger(FX_BSTRC("MCID"));
- } else if (type == FX_BSTRC("OBJR")) {
- if (m_pTree->m_pPage && m_pTree->m_pPage->GetObjNum() != PageObjNum) {
- return;
- }
- pKid->m_Type = CPDF_StructKid::Object;
- CPDF_Object* pObj = pKidDict->GetElement(FX_BSTRC("Obj"));
- if (pObj && pObj->GetType() == PDFOBJ_REFERENCE) {
- pKid->m_Object.m_RefObjNum = ((CPDF_Reference*)pObj)->GetRefObjNum();
- } else {
- pKid->m_Object.m_RefObjNum = 0;
- }
- pKid->m_Object.m_PageObjNum = PageObjNum;
- } else {
- pKid->m_Type = CPDF_StructKid::Element;
- pKid->m_Element.m_pDict = pKidDict;
- if (m_pTree->m_pPage == NULL) {
- pKid->m_Element.m_pElement = FX_NEW CPDF_StructElementImpl(m_pTree, this, pKidDict);
- } else {
- pKid->m_Element.m_pElement = NULL;
- }
- }
-}
-static CPDF_Dictionary* FindAttrDict(CPDF_Object* pAttrs, FX_BSTR owner, FX_FLOAT nLevel = 0.0F)
-{
- if (nLevel > nMaxRecursion) {
- return NULL;
- }
- if (pAttrs == NULL) {
- return NULL;
- }
- CPDF_Dictionary* pDict = NULL;
- if (pAttrs->GetType() == PDFOBJ_DICTIONARY) {
- pDict = (CPDF_Dictionary*)pAttrs;
- } else if (pAttrs->GetType() == PDFOBJ_STREAM) {
- pDict = ((CPDF_Stream*)pAttrs)->GetDict();
- } else if (pAttrs->GetType() == PDFOBJ_ARRAY) {
- CPDF_Array* pArray = (CPDF_Array*)pAttrs;
- for (FX_DWORD i = 0; i < pArray->GetCount(); i ++) {
- CPDF_Object* pElement = pArray->GetElementValue(i);
- pDict = FindAttrDict(pElement, owner, nLevel + 1);
- if (pDict) {
- return pDict;
- }
- }
- }
- if (pDict && pDict->GetString(FX_BSTRC("O")) == owner) {
- return pDict;
- }
- return NULL;
-}
-CPDF_Object* CPDF_StructElementImpl::GetAttr(FX_BSTR owner, FX_BSTR name, FX_BOOL bInheritable, FX_FLOAT fLevel)
-{
- if (fLevel > nMaxRecursion) {
- return NULL;
- }
- if (bInheritable) {
- CPDF_Object* pAttr = GetAttr(owner, name, FALSE);
- if (pAttr) {
- return pAttr;
- }
- if (m_pParent == NULL) {
- return NULL;
- }
- return m_pParent->GetAttr(owner, name, TRUE, fLevel + 1);
- }
- CPDF_Object* pA = m_pDict->GetElementValue(FX_BSTRC("A"));
- if (pA) {
- CPDF_Dictionary* pAttrDict = FindAttrDict(pA, owner);
- if (pAttrDict) {
- CPDF_Object* pAttr = pAttrDict->GetElementValue(name);
- if (pAttr) {
- return pAttr;
- }
- }
- }
- CPDF_Object* pC = m_pDict->GetElementValue(FX_BSTRC("C"));
- if (pC == NULL) {
- return NULL;
- }
- CPDF_Dictionary* pClassMap = m_pTree->m_pTreeRoot->GetDict(FX_BSTRC("ClassMap"));
- if (pClassMap == NULL) {
- return NULL;
- }
- if (pC->GetType() == PDFOBJ_ARRAY) {
- CPDF_Array* pArray = (CPDF_Array*)pC;
- for (FX_DWORD i = 0; i < pArray->GetCount(); i ++) {
- CFX_ByteString class_name = pArray->GetString(i);
- CPDF_Dictionary* pClassDict = pClassMap->GetDict(class_name);
- if (pClassDict && pClassDict->GetString(FX_BSTRC("O")) == owner) {
- return pClassDict->GetElementValue(name);
- }
- }
- return NULL;
- }
- CFX_ByteString class_name = pC->GetString();
- CPDF_Dictionary* pClassDict = pClassMap->GetDict(class_name);
- if (pClassDict && pClassDict->GetString(FX_BSTRC("O")) == owner) {
- return pClassDict->GetElementValue(name);
- }
- return NULL;
-}
-CPDF_Object* CPDF_StructElementImpl::GetAttr(FX_BSTR owner, FX_BSTR name, FX_BOOL bInheritable, int subindex)
-{
- CPDF_Object* pAttr = GetAttr(owner, name, bInheritable);
- if (pAttr == NULL || subindex == -1 || pAttr->GetType() != PDFOBJ_ARRAY) {
- return pAttr;
- }
- CPDF_Array* pArray = (CPDF_Array*)pAttr;
- if (subindex >= (int)pArray->GetCount()) {
- return pAttr;
- }
- return pArray->GetElementValue(subindex);
-}
-CFX_ByteString CPDF_StructElementImpl::GetName(FX_BSTR owner, FX_BSTR name, FX_BSTR default_value, FX_BOOL bInheritable, int subindex)
-{
- CPDF_Object* pAttr = GetAttr(owner, name, bInheritable, subindex);
- if (pAttr == NULL || pAttr->GetType() != PDFOBJ_NAME) {
- return default_value;
- }
- return pAttr->GetString();
-}
-FX_ARGB CPDF_StructElementImpl::GetColor(FX_BSTR owner, FX_BSTR name, FX_ARGB default_value, FX_BOOL bInheritable, int subindex)
-{
- CPDF_Object* pAttr = GetAttr(owner, name, bInheritable, subindex);
- if (pAttr == NULL || pAttr->GetType() != PDFOBJ_ARRAY) {
- return default_value;
- }
- CPDF_Array* pArray = (CPDF_Array*)pAttr;
- return 0xff000000 | ((int)(pArray->GetNumber(0) * 255) << 16) | ((int)(pArray->GetNumber(1) * 255) << 8) | (int)(pArray->GetNumber(2) * 255);
-}
-FX_FLOAT CPDF_StructElementImpl::GetNumber(FX_BSTR owner, FX_BSTR name, FX_FLOAT default_value, FX_BOOL bInheritable, int subindex)
-{
- CPDF_Object* pAttr = GetAttr(owner, name, bInheritable, subindex);
- if (pAttr == NULL || pAttr->GetType() != PDFOBJ_NUMBER) {
- return default_value;
- }
- return pAttr->GetNumber();
-}
-int CPDF_StructElementImpl::GetInteger(FX_BSTR owner, FX_BSTR name, int default_value, FX_BOOL bInheritable, int subindex)
-{
- CPDF_Object* pAttr = GetAttr(owner, name, bInheritable, subindex);
- if (pAttr == NULL || pAttr->GetType() != PDFOBJ_NUMBER) {
- return default_value;
- }
- return pAttr->GetInteger();
-}
+// Copyright 2014 PDFium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
+
+#include "../../include/fpdfapi/fpdf_parser.h"
+#include "../../include/fpdfapi/fpdf_page.h"
+#include "../../include/fpdfdoc/fpdf_tagged.h"
+#include "tagged_int.h"
+const int nMaxRecursion = 32;
+static FX_BOOL IsTagged(const CPDF_Document* pDoc)
+{
+ CPDF_Dictionary* pCatalog = pDoc->GetRoot();
+ CPDF_Dictionary* pMarkInfo = pCatalog->GetDict(FX_BSTRC("MarkInfo"));
+ return pMarkInfo != NULL && pMarkInfo->GetInteger(FX_BSTRC("Marked"));
+}
+CPDF_StructTree* CPDF_StructTree::LoadPage(const CPDF_Document* pDoc, const CPDF_Dictionary* pPageDict)
+{
+ if (!IsTagged(pDoc)) {
+ return NULL;
+ }
+ CPDF_StructTreeImpl* pTree = FX_NEW CPDF_StructTreeImpl(pDoc);
+ if (pTree == NULL) {
+ return NULL;
+ }
+ pTree->LoadPageTree(pPageDict);
+ return pTree;
+}
+CPDF_StructTree* CPDF_StructTree::LoadDoc(const CPDF_Document* pDoc)
+{
+ if (!IsTagged(pDoc)) {
+ return NULL;
+ }
+ CPDF_StructTreeImpl* pTree = FX_NEW CPDF_StructTreeImpl(pDoc);
+ if (pTree == NULL) {
+ return NULL;
+ }
+ pTree->LoadDocTree();
+ return pTree;
+}
+CPDF_StructTreeImpl::CPDF_StructTreeImpl(const CPDF_Document* pDoc)
+{
+ CPDF_Dictionary* pCatalog = pDoc->GetRoot();
+ m_pTreeRoot = pCatalog->GetDict(FX_BSTRC("StructTreeRoot"));
+ if (m_pTreeRoot == NULL) {
+ return;
+ }
+ m_pRoleMap = m_pTreeRoot->GetDict(FX_BSTRC("RoleMap"));
+}
+CPDF_StructTreeImpl::~CPDF_StructTreeImpl()
+{
+ for (int i = 0; i < m_Kids.GetSize(); i ++)
+ if (m_Kids[i]) {
+ m_Kids[i]->Release();
+ }
+}
+void CPDF_StructTreeImpl::LoadDocTree()
+{
+ m_pPage = NULL;
+ if (m_pTreeRoot == NULL) {
+ return;
+ }
+ CPDF_Object* pKids = m_pTreeRoot->GetElementValue(FX_BSTRC("K"));
+ if (pKids == NULL) {
+ return;
+ }
+ if (pKids->GetType() == PDFOBJ_DICTIONARY) {
+ CPDF_StructElementImpl* pStructElementImpl = FX_NEW CPDF_StructElementImpl(this, NULL, (CPDF_Dictionary*)pKids);
+ if (pStructElementImpl == NULL) {
+ return;
+ }
+ m_Kids.Add(pStructElementImpl);
+ return;
+ }
+ if (pKids->GetType() != PDFOBJ_ARRAY) {
+ return;
+ }
+ CPDF_Array* pArray = (CPDF_Array*)pKids;
+ for (FX_DWORD i = 0; i < pArray->GetCount(); i ++) {
+ CPDF_Dictionary* pKid = pArray->GetDict(i);
+ CPDF_StructElementImpl* pStructElementImpl = FX_NEW CPDF_StructElementImpl(this, NULL, pKid);
+ if (pStructElementImpl == NULL) {
+ return;
+ }
+ m_Kids.Add(pStructElementImpl);
+ }
+}
+void CPDF_StructTreeImpl::LoadPageTree(const CPDF_Dictionary* pPageDict)
+{
+ m_pPage = pPageDict;
+ if (m_pTreeRoot == NULL) {
+ return;
+ }
+ CPDF_Object* pKids = m_pTreeRoot->GetElementValue(FX_BSTRC("K"));
+ if (pKids == NULL) {
+ return;
+ }
+ FX_DWORD dwKids = 0;
+ if (pKids->GetType() == PDFOBJ_DICTIONARY) {
+ dwKids = 1;
+ } else if (pKids->GetType() == PDFOBJ_ARRAY) {
+ dwKids = ((CPDF_Array*)pKids)->GetCount();
+ } else {
+ return;
+ }
+ FX_DWORD i;
+ m_Kids.SetSize(dwKids);
+ for (i = 0; i < dwKids; i ++) {
+ m_Kids[i] = NULL;
+ }
+ CFX_MapPtrToPtr element_map;
+ CPDF_Dictionary* pParentTree = m_pTreeRoot->GetDict(FX_BSTRC("ParentTree"));
+ if (pParentTree == NULL) {
+ return;
+ }
+ CPDF_NumberTree parent_tree(pParentTree);
+ int parents_id = pPageDict->GetInteger(FX_BSTRC("StructParents"), -1);
+ if (parents_id >= 0) {
+ CPDF_Object* pParents = parent_tree.LookupValue(parents_id);
+ if (pParents == NULL || pParents->GetType() != PDFOBJ_ARRAY) {
+ return;
+ }
+ CPDF_Array* pParentArray = (CPDF_Array*)pParents;
+ for (i = 0; i < pParentArray->GetCount(); i ++) {
+ CPDF_Dictionary* pParent = pParentArray->GetDict(i);
+ if (pParent == NULL) {
+ continue;
+ }
+ AddPageNode(pParent, element_map);
+ }
+ }
+}
+CPDF_StructElementImpl* CPDF_StructTreeImpl::AddPageNode(CPDF_Dictionary* pDict, CFX_MapPtrToPtr& map, int nLevel)
+{
+ if (nLevel > nMaxRecursion) {
+ return NULL;
+ }
+ CPDF_StructElementImpl* pElement = NULL;
+ if (map.Lookup(pDict, (FX_LPVOID&)pElement)) {
+ return pElement;
+ }
+ pElement = FX_NEW CPDF_StructElementImpl(this, NULL, pDict);
+ if (pElement == NULL) {
+ return NULL;
+ }
+ map.SetAt(pDict, pElement);
+ CPDF_Dictionary* pParent = pDict->GetDict(FX_BSTRC("P"));
+ if (pParent == NULL || pParent->GetString(FX_BSTRC("Type")) == FX_BSTRC("StructTreeRoot")) {
+ if (!AddTopLevelNode(pDict, pElement)) {
+ pElement->Release();
+ map.RemoveKey(pDict);
+ }
+ } else {
+ CPDF_StructElementImpl* pParentElement = AddPageNode(pParent, map, nLevel + 1);
+ FX_BOOL bSave = FALSE;
+ for (int i = 0; i < pParentElement->m_Kids.GetSize(); i ++) {
+ if (pParentElement->m_Kids[i].m_Type != CPDF_StructKid::Element) {
+ continue;
+ }
+ if (pParentElement->m_Kids[i].m_Element.m_pDict != pDict) {
+ continue;
+ }
+ pParentElement->m_Kids[i].m_Element.m_pElement = pElement->Retain();
+ bSave = TRUE;
+ }
+ if (!bSave) {
+ pElement->Release();
+ map.RemoveKey(pDict);
+ }
+ }
+ return pElement;
+}
+FX_BOOL CPDF_StructTreeImpl::AddTopLevelNode(CPDF_Dictionary* pDict, CPDF_StructElementImpl* pElement)
+{
+ CPDF_Object *pObj = m_pTreeRoot->GetElementValue(FX_BSTRC("K"));
+ if (!pObj) {
+ return FALSE;
+ }
+ if (pObj->GetType() == PDFOBJ_DICTIONARY) {
+ if (pObj->GetObjNum() == pDict->GetObjNum()) {
+ if (m_Kids[0]) {
+ m_Kids[0]->Release();
+ }
+ m_Kids[0] = pElement->Retain();
+ } else {
+ return FALSE;
+ }
+ }
+ if (pObj->GetType() == PDFOBJ_ARRAY) {
+ CPDF_Array* pTopKids = (CPDF_Array*)pObj;
+ FX_DWORD i;
+ FX_BOOL bSave = FALSE;
+ for (i = 0; i < pTopKids->GetCount(); i ++) {
+ CPDF_Reference* pKidRef = (CPDF_Reference*)pTopKids->GetElement(i);
+ if (pKidRef->GetType() != PDFOBJ_REFERENCE || pKidRef->GetRefObjNum() != pDict->GetObjNum()) {
+ continue;
+ }
+ if (m_Kids[i]) {
+ m_Kids[i]->Release();
+ }
+ m_Kids[i] = pElement->Retain();
+ bSave = TRUE;
+ }
+ if (!bSave) {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+CPDF_StructElementImpl::CPDF_StructElementImpl(CPDF_StructTreeImpl* pTree, CPDF_StructElementImpl* pParent, CPDF_Dictionary* pDict)
+ : m_RefCount(0)
+{
+ m_pTree = pTree;
+ m_pDict = pDict;
+ m_Type = pDict->GetString(FX_BSTRC("S"));
+ CFX_ByteString mapped = pTree->m_pRoleMap->GetString(m_Type);
+ if (!mapped.IsEmpty()) {
+ m_Type = mapped;
+ }
+ m_pParent = pParent;
+ LoadKids(pDict);
+}
+CPDF_StructElementImpl::~CPDF_StructElementImpl()
+{
+ for (int i = 0; i < m_Kids.GetSize(); i ++) {
+ if (m_Kids[i].m_Type == CPDF_StructKid::Element && m_Kids[i].m_Element.m_pElement) {
+ ((CPDF_StructElementImpl*)m_Kids[i].m_Element.m_pElement)->Release();
+ }
+ }
+}
+CPDF_StructElementImpl* CPDF_StructElementImpl::Retain()
+{
+ m_RefCount++;
+ return this;
+}
+void CPDF_StructElementImpl::Release()
+{
+ if(--m_RefCount < 1) {
+ delete this;
+ }
+}
+void CPDF_StructElementImpl::LoadKids(CPDF_Dictionary* pDict)
+{
+ CPDF_Object* pObj = pDict->GetElement(FX_BSTRC("Pg"));
+ FX_DWORD PageObjNum = 0;
+ if (pObj && pObj->GetType() == PDFOBJ_REFERENCE) {
+ PageObjNum = ((CPDF_Reference*)pObj)->GetRefObjNum();
+ }
+ CPDF_Object* pKids = pDict->GetElementValue(FX_BSTRC("K"));
+ if (pKids == NULL) {
+ return;
+ }
+ if (pKids->GetType() == PDFOBJ_ARRAY) {
+ CPDF_Array* pArray = (CPDF_Array*)pKids;
+ m_Kids.SetSize(pArray->GetCount());
+ for (FX_DWORD i = 0; i < pArray->GetCount(); i ++) {
+ CPDF_Object* pKid = pArray->GetElementValue(i);
+ LoadKid(PageObjNum, pKid, &m_Kids[i]);
+ }
+ } else {
+ m_Kids.SetSize(1);
+ LoadKid(PageObjNum, pKids, &m_Kids[0]);
+ }
+}
+void CPDF_StructElementImpl::LoadKid(FX_DWORD PageObjNum, CPDF_Object* pKidObj, CPDF_StructKid* pKid)
+{
+ pKid->m_Type = CPDF_StructKid::Invalid;
+ if (pKidObj == NULL) {
+ return;
+ }
+ if (pKidObj->GetType() == PDFOBJ_NUMBER) {
+ if (m_pTree->m_pPage && m_pTree->m_pPage->GetObjNum() != PageObjNum) {
+ return;
+ }
+ pKid->m_Type = CPDF_StructKid::PageContent;
+ pKid->m_PageContent.m_ContentId = pKidObj->GetInteger();
+ pKid->m_PageContent.m_PageObjNum = PageObjNum;
+ return;
+ }
+ if (pKidObj->GetType() != PDFOBJ_DICTIONARY) {
+ return;
+ }
+ CPDF_Dictionary* pKidDict = (CPDF_Dictionary*)pKidObj;
+ CPDF_Object* pPageObj = pKidDict->GetElement(FX_BSTRC("Pg"));
+ if (pPageObj && pPageObj->GetType() == PDFOBJ_REFERENCE) {
+ PageObjNum = ((CPDF_Reference*)pPageObj)->GetRefObjNum();
+ }
+ CFX_ByteString type = pKidDict->GetString(FX_BSTRC("Type"));
+ if (type == FX_BSTRC("MCR")) {
+ if (m_pTree->m_pPage && m_pTree->m_pPage->GetObjNum() != PageObjNum) {
+ return;
+ }
+ pKid->m_Type = CPDF_StructKid::StreamContent;
+ CPDF_Object* pStreamObj = pKidDict->GetElement(FX_BSTRC("Stm"));
+ if (pStreamObj && pStreamObj->GetType() == PDFOBJ_REFERENCE) {
+ pKid->m_StreamContent.m_RefObjNum = ((CPDF_Reference*)pStreamObj)->GetRefObjNum();
+ } else {
+ pKid->m_StreamContent.m_RefObjNum = 0;
+ }
+ pKid->m_StreamContent.m_PageObjNum = PageObjNum;
+ pKid->m_StreamContent.m_ContentId = pKidDict->GetInteger(FX_BSTRC("MCID"));
+ } else if (type == FX_BSTRC("OBJR")) {
+ if (m_pTree->m_pPage && m_pTree->m_pPage->GetObjNum() != PageObjNum) {
+ return;
+ }
+ pKid->m_Type = CPDF_StructKid::Object;
+ CPDF_Object* pObj = pKidDict->GetElement(FX_BSTRC("Obj"));
+ if (pObj && pObj->GetType() == PDFOBJ_REFERENCE) {
+ pKid->m_Object.m_RefObjNum = ((CPDF_Reference*)pObj)->GetRefObjNum();
+ } else {
+ pKid->m_Object.m_RefObjNum = 0;
+ }
+ pKid->m_Object.m_PageObjNum = PageObjNum;
+ } else {
+ pKid->m_Type = CPDF_StructKid::Element;
+ pKid->m_Element.m_pDict = pKidDict;
+ if (m_pTree->m_pPage == NULL) {
+ pKid->m_Element.m_pElement = FX_NEW CPDF_StructElementImpl(m_pTree, this, pKidDict);
+ } else {
+ pKid->m_Element.m_pElement = NULL;
+ }
+ }
+}
+static CPDF_Dictionary* FindAttrDict(CPDF_Object* pAttrs, FX_BSTR owner, FX_FLOAT nLevel = 0.0F)
+{
+ if (nLevel > nMaxRecursion) {
+ return NULL;
+ }
+ if (pAttrs == NULL) {
+ return NULL;
+ }
+ CPDF_Dictionary* pDict = NULL;
+ if (pAttrs->GetType() == PDFOBJ_DICTIONARY) {
+ pDict = (CPDF_Dictionary*)pAttrs;
+ } else if (pAttrs->GetType() == PDFOBJ_STREAM) {
+ pDict = ((CPDF_Stream*)pAttrs)->GetDict();
+ } else if (pAttrs->GetType() == PDFOBJ_ARRAY) {
+ CPDF_Array* pArray = (CPDF_Array*)pAttrs;
+ for (FX_DWORD i = 0; i < pArray->GetCount(); i ++) {
+ CPDF_Object* pElement = pArray->GetElementValue(i);
+ pDict = FindAttrDict(pElement, owner, nLevel + 1);
+ if (pDict) {
+ return pDict;
+ }
+ }
+ }
+ if (pDict && pDict->GetString(FX_BSTRC("O")) == owner) {
+ return pDict;
+ }
+ return NULL;
+}
+CPDF_Object* CPDF_StructElementImpl::GetAttr(FX_BSTR owner, FX_BSTR name, FX_BOOL bInheritable, FX_FLOAT fLevel)
+{
+ if (fLevel > nMaxRecursion) {
+ return NULL;
+ }
+ if (bInheritable) {
+ CPDF_Object* pAttr = GetAttr(owner, name, FALSE);
+ if (pAttr) {
+ return pAttr;
+ }
+ if (m_pParent == NULL) {
+ return NULL;
+ }
+ return m_pParent->GetAttr(owner, name, TRUE, fLevel + 1);
+ }
+ CPDF_Object* pA = m_pDict->GetElementValue(FX_BSTRC("A"));
+ if (pA) {
+ CPDF_Dictionary* pAttrDict = FindAttrDict(pA, owner);
+ if (pAttrDict) {
+ CPDF_Object* pAttr = pAttrDict->GetElementValue(name);
+ if (pAttr) {
+ return pAttr;
+ }
+ }
+ }
+ CPDF_Object* pC = m_pDict->GetElementValue(FX_BSTRC("C"));
+ if (pC == NULL) {
+ return NULL;
+ }
+ CPDF_Dictionary* pClassMap = m_pTree->m_pTreeRoot->GetDict(FX_BSTRC("ClassMap"));
+ if (pClassMap == NULL) {
+ return NULL;
+ }
+ if (pC->GetType() == PDFOBJ_ARRAY) {
+ CPDF_Array* pArray = (CPDF_Array*)pC;
+ for (FX_DWORD i = 0; i < pArray->GetCount(); i ++) {
+ CFX_ByteString class_name = pArray->GetString(i);
+ CPDF_Dictionary* pClassDict = pClassMap->GetDict(class_name);
+ if (pClassDict && pClassDict->GetString(FX_BSTRC("O")) == owner) {
+ return pClassDict->GetElementValue(name);
+ }
+ }
+ return NULL;
+ }
+ CFX_ByteString class_name = pC->GetString();
+ CPDF_Dictionary* pClassDict = pClassMap->GetDict(class_name);
+ if (pClassDict && pClassDict->GetString(FX_BSTRC("O")) == owner) {
+ return pClassDict->GetElementValue(name);
+ }
+ return NULL;
+}
+CPDF_Object* CPDF_StructElementImpl::GetAttr(FX_BSTR owner, FX_BSTR name, FX_BOOL bInheritable, int subindex)
+{
+ CPDF_Object* pAttr = GetAttr(owner, name, bInheritable);
+ if (pAttr == NULL || subindex == -1 || pAttr->GetType() != PDFOBJ_ARRAY) {
+ return pAttr;
+ }
+ CPDF_Array* pArray = (CPDF_Array*)pAttr;
+ if (subindex >= (int)pArray->GetCount()) {
+ return pAttr;
+ }
+ return pArray->GetElementValue(subindex);
+}
+CFX_ByteString CPDF_StructElementImpl::GetName(FX_BSTR owner, FX_BSTR name, FX_BSTR default_value, FX_BOOL bInheritable, int subindex)
+{
+ CPDF_Object* pAttr = GetAttr(owner, name, bInheritable, subindex);
+ if (pAttr == NULL || pAttr->GetType() != PDFOBJ_NAME) {
+ return default_value;
+ }
+ return pAttr->GetString();
+}
+FX_ARGB CPDF_StructElementImpl::GetColor(FX_BSTR owner, FX_BSTR name, FX_ARGB default_value, FX_BOOL bInheritable, int subindex)
+{
+ CPDF_Object* pAttr = GetAttr(owner, name, bInheritable, subindex);
+ if (pAttr == NULL || pAttr->GetType() != PDFOBJ_ARRAY) {
+ return default_value;
+ }
+ CPDF_Array* pArray = (CPDF_Array*)pAttr;
+ return 0xff000000 | ((int)(pArray->GetNumber(0) * 255) << 16) | ((int)(pArray->GetNumber(1) * 255) << 8) | (int)(pArray->GetNumber(2) * 255);
+}
+FX_FLOAT CPDF_StructElementImpl::GetNumber(FX_BSTR owner, FX_BSTR name, FX_FLOAT default_value, FX_BOOL bInheritable, int subindex)
+{
+ CPDF_Object* pAttr = GetAttr(owner, name, bInheritable, subindex);
+ if (pAttr == NULL || pAttr->GetType() != PDFOBJ_NUMBER) {
+ return default_value;
+ }
+ return pAttr->GetNumber();
+}
+int CPDF_StructElementImpl::GetInteger(FX_BSTR owner, FX_BSTR name, int default_value, FX_BOOL bInheritable, int subindex)
+{
+ CPDF_Object* pAttr = GetAttr(owner, name, bInheritable, subindex);
+ if (pAttr == NULL || pAttr->GetType() != PDFOBJ_NUMBER) {
+ return default_value;
+ }
+ return pAttr->GetInteger();
+}