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; }
CPDF_StructElementImpl* CPDF_StructTreeImpl::AddPageNode( CPDF_Dictionary* pDict, std::map<CPDF_Dictionary*, CPDF_StructElementImpl*>& map, int nLevel) { if (nLevel > nMaxRecursion) return nullptr; auto it = map.find(pDict); if (it != map.end()) return it->second; CPDF_StructElementImpl* pElement = new CPDF_StructElementImpl(this, nullptr, pDict); map[pDict] = pElement; CPDF_Dictionary* pParent = pDict->GetDictBy("P"); if (!pParent || pParent->GetStringBy("Type") == "StructTreeRoot") { if (!AddTopLevelNode(pDict, pElement)) { pElement->Release(); map.erase(pDict); } } else { CPDF_StructElementImpl* pParentElement = AddPageNode(pParent, map, nLevel + 1); FX_BOOL bSave = FALSE; for (CPDF_StructKid& kid : pParentElement->m_Kids) { if (kid.m_Type != CPDF_StructKid::Element) continue; if (kid.m_Element.m_pDict != pDict) continue; kid.m_Element.m_pElement = pElement->Retain(); bSave = TRUE; } if (!bSave) { pElement->Release(); map.erase(pDict); } } return pElement; }
void CPDF_StructTreeImpl::LoadPageTree(const CPDF_Dictionary* pPageDict) { m_pPage = pPageDict; if (!m_pTreeRoot) return; CPDF_Object* pKids = m_pTreeRoot->GetDirectObjectBy("K"); if (!pKids) return; uint32_t dwKids = 0; if (pKids->IsDictionary()) dwKids = 1; else if (CPDF_Array* pArray = pKids->AsArray()) dwKids = pArray->GetCount(); else return; m_Kids.clear(); m_Kids.resize(dwKids); CPDF_Dictionary* pParentTree = m_pTreeRoot->GetDictBy("ParentTree"); if (!pParentTree) return; CPDF_NumberTree parent_tree(pParentTree); int parents_id = pPageDict->GetIntegerBy("StructParents", -1); if (parents_id < 0) return; CPDF_Array* pParentArray = ToArray(parent_tree.LookupValue(parents_id)); if (!pParentArray) return; std::map<CPDF_Dictionary*, CPDF_StructElementImpl*> element_map; for (size_t i = 0; i < pParentArray->GetCount(); i++) { if (CPDF_Dictionary* pParent = pParentArray->GetDictAt(i)) AddPageNode(pParent, element_map); } }