1// Copyright 2014 PDFium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6 7#include "../../../include/fpdfapi/fpdf_parser.h" 8#include "../../../include/fpdfapi/fpdf_module.h" 9 10CPDF_Document::CPDF_Document(CPDF_Parser* pParser) : CPDF_IndirectObjects(pParser) 11{ 12 ASSERT(pParser != NULL); 13 m_pRootDict = NULL; 14 m_pInfoDict = NULL; 15 m_bLinearized = FALSE; 16 m_dwFirstPageNo = 0; 17 m_dwFirstPageObjNum = 0; 18 m_pDocPage = CPDF_ModuleMgr::Get()->GetPageModule()->CreateDocData(this); 19 m_pDocRender = CPDF_ModuleMgr::Get()->GetRenderModule()->CreateDocData(this); 20} 21CPDF_DocPageData* CPDF_Document::GetValidatePageData() 22{ 23 if (m_pDocPage) { 24 return m_pDocPage; 25 } 26 m_pDocPage = CPDF_ModuleMgr::Get()->GetPageModule()->CreateDocData(this); 27 return m_pDocPage; 28} 29CPDF_DocRenderData* CPDF_Document::GetValidateRenderData() 30{ 31 if (m_pDocRender) { 32 return m_pDocRender; 33 } 34 m_pDocRender = CPDF_ModuleMgr::Get()->GetRenderModule()->CreateDocData(this); 35 return m_pDocRender; 36} 37void CPDF_Document::LoadDoc() 38{ 39 m_LastObjNum = m_pParser->GetLastObjNum(); 40 CPDF_Object* pRootObj = GetIndirectObject(m_pParser->GetRootObjNum()); 41 if (pRootObj == NULL) { 42 return; 43 } 44 m_pRootDict = pRootObj->GetDict(); 45 if (m_pRootDict == NULL) { 46 return; 47 } 48 CPDF_Object* pInfoObj = GetIndirectObject(m_pParser->GetInfoObjNum()); 49 if (pInfoObj) { 50 m_pInfoDict = pInfoObj->GetDict(); 51 } 52 CPDF_Array* pIDArray = m_pParser->GetIDArray(); 53 if (pIDArray) { 54 m_ID1 = pIDArray->GetString(0); 55 m_ID2 = pIDArray->GetString(1); 56 } 57 m_PageList.SetSize(_GetPageCount()); 58} 59void CPDF_Document::LoadAsynDoc(CPDF_Dictionary *pLinearized) 60{ 61 m_bLinearized = TRUE; 62 m_LastObjNum = m_pParser->GetLastObjNum(); 63 CPDF_Object* indirectObj = GetIndirectObject(m_pParser->GetRootObjNum()); 64 m_pRootDict = indirectObj ? indirectObj->GetDict() : NULL; 65 if (m_pRootDict == NULL) { 66 return; 67 } 68 indirectObj = GetIndirectObject(m_pParser->GetInfoObjNum()); 69 m_pInfoDict = indirectObj ? indirectObj->GetDict() : NULL; 70 CPDF_Array* pIDArray = m_pParser->GetIDArray(); 71 if (pIDArray) { 72 m_ID1 = pIDArray->GetString(0); 73 m_ID2 = pIDArray->GetString(1); 74 } 75 FX_DWORD dwPageCount = 0; 76 CPDF_Object *pCount = pLinearized->GetElement(FX_BSTRC("N")); 77 if (pCount && pCount->GetType() == PDFOBJ_NUMBER) { 78 dwPageCount = pCount->GetInteger(); 79 } 80 m_PageList.SetSize(dwPageCount); 81 CPDF_Object *pNo = pLinearized->GetElement(FX_BSTRC("P")); 82 if (pNo && pNo->GetType() == PDFOBJ_NUMBER) { 83 m_dwFirstPageNo = pNo->GetInteger(); 84 } 85 CPDF_Object *pObjNum = pLinearized->GetElement(FX_BSTRC("O")); 86 if (pObjNum && pObjNum->GetType() == PDFOBJ_NUMBER) { 87 m_dwFirstPageObjNum = pObjNum->GetInteger(); 88 } 89} 90void CPDF_Document::LoadPages() 91{ 92 m_PageList.SetSize(_GetPageCount()); 93} 94extern void FPDF_TTFaceMapper_ReleaseDoc(CPDF_Document*); 95CPDF_Document::~CPDF_Document() 96{ 97 if (m_pDocPage) { 98 CPDF_ModuleMgr::Get()->GetPageModule()->ReleaseDoc(this); 99 CPDF_ModuleMgr::Get()->GetPageModule()->ClearStockFont(this); 100 } 101 if (m_pDocRender) { 102 CPDF_ModuleMgr::Get()->GetRenderModule()->DestroyDocData(m_pDocRender); 103 } 104} 105#define FX_MAX_PAGE_LEVEL 1024 106CPDF_Dictionary* CPDF_Document::_FindPDFPage(CPDF_Dictionary* pPages, int iPage, int nPagesToGo, int level) 107{ 108 CPDF_Array* pKidList = pPages->GetArray(FX_BSTRC("Kids")); 109 if (pKidList == NULL) { 110 if (nPagesToGo == 0) { 111 return pPages; 112 } 113 return NULL; 114 } 115 if (level >= FX_MAX_PAGE_LEVEL) { 116 return NULL; 117 } 118 int nKids = pKidList->GetCount(); 119 for (int i = 0; i < nKids; i ++) { 120 CPDF_Dictionary* pKid = pKidList->GetDict(i); 121 if (pKid == NULL) { 122 nPagesToGo --; 123 continue; 124 } 125 if (pKid == pPages) { 126 continue; 127 } 128 if (!pKid->KeyExist(FX_BSTRC("Kids"))) { 129 if (nPagesToGo == 0) { 130 return pKid; 131 } 132 m_PageList.SetAt(iPage - nPagesToGo, pKid->GetObjNum()); 133 nPagesToGo --; 134 } else { 135 int nPages = pKid->GetInteger(FX_BSTRC("Count")); 136 if (nPagesToGo < nPages) { 137 return _FindPDFPage(pKid, iPage, nPagesToGo, level + 1); 138 } 139 nPagesToGo -= nPages; 140 } 141 } 142 return NULL; 143} 144CPDF_Dictionary* CPDF_Document::GetPage(int iPage) 145{ 146 if (iPage < 0 || iPage >= m_PageList.GetSize()) { 147 return NULL; 148 } 149 if (m_bLinearized && (iPage == (int)m_dwFirstPageNo)) { 150 CPDF_Object* pObj = GetIndirectObject(m_dwFirstPageObjNum); 151 if (pObj && pObj->GetType() == PDFOBJ_DICTIONARY) { 152 return (CPDF_Dictionary*)pObj; 153 } 154 } 155 int objnum = m_PageList.GetAt(iPage); 156 if (objnum) { 157 CPDF_Object* pObj = GetIndirectObject(objnum); 158 ASSERT(pObj->GetType() == PDFOBJ_DICTIONARY); 159 return (CPDF_Dictionary*)pObj; 160 } 161 CPDF_Dictionary* pRoot = GetRoot(); 162 if (pRoot == NULL) { 163 return NULL; 164 } 165 CPDF_Dictionary* pPages = pRoot->GetDict(FX_BSTRC("Pages")); 166 if (pPages == NULL) { 167 return NULL; 168 } 169 CPDF_Dictionary* pPage = _FindPDFPage(pPages, iPage, iPage, 0); 170 if (pPage == NULL) { 171 return NULL; 172 } 173 m_PageList.SetAt(iPage, pPage->GetObjNum()); 174 return pPage; 175} 176int CPDF_Document::_FindPageIndex(CPDF_Dictionary* pNode, FX_DWORD& skip_count, FX_DWORD objnum, int& index, int level) 177{ 178 if (pNode->KeyExist(FX_BSTRC("Kids"))) { 179 CPDF_Array* pKidList = pNode->GetArray(FX_BSTRC("Kids")); 180 if (pKidList == NULL) { 181 return -1; 182 } 183 if (level >= FX_MAX_PAGE_LEVEL) { 184 return -1; 185 } 186 FX_DWORD count = pNode->GetInteger(FX_BSTRC("Count")); 187 if (count <= skip_count) { 188 skip_count -= count; 189 index += count; 190 return -1; 191 } 192 if (count && count == pKidList->GetCount()) { 193 for (FX_DWORD i = 0; i < count; i ++) { 194 CPDF_Object* pKid = pKidList->GetElement(i); 195 if (pKid && pKid->GetType() == PDFOBJ_REFERENCE) { 196 if (((CPDF_Reference*) pKid)->GetRefObjNum() == objnum) { 197 m_PageList.SetAt(index + i, objnum); 198 return index + i; 199 } 200 } 201 } 202 } 203 for (FX_DWORD i = 0; i < pKidList->GetCount(); i ++) { 204 CPDF_Dictionary* pKid = pKidList->GetDict(i); 205 if (pKid == NULL) { 206 continue; 207 } 208 if (pKid == pNode) { 209 continue; 210 } 211 int found_index = _FindPageIndex(pKid, skip_count, objnum, index, level + 1); 212 if (found_index >= 0) { 213 return found_index; 214 } 215 } 216 } else { 217 if (objnum == pNode->GetObjNum()) { 218 return index; 219 } 220 if (skip_count) { 221 skip_count--; 222 } 223 index ++; 224 } 225 return -1; 226} 227int CPDF_Document::GetPageIndex(FX_DWORD objnum) 228{ 229 FX_DWORD nPages = m_PageList.GetSize(); 230 FX_DWORD skip_count = 0; 231 FX_BOOL bSkipped = FALSE; 232 for (FX_DWORD i = 0; i < nPages; i ++) { 233 FX_DWORD objnum1 = m_PageList.GetAt(i); 234 if (objnum1 == objnum) { 235 return i; 236 } 237 if (!bSkipped && objnum1 == 0) { 238 skip_count = i; 239 bSkipped = TRUE; 240 } 241 } 242 CPDF_Dictionary* pRoot = GetRoot(); 243 if (pRoot == NULL) { 244 return -1; 245 } 246 CPDF_Dictionary* pPages = pRoot->GetDict(FX_BSTRC("Pages")); 247 if (pPages == NULL) { 248 return -1; 249 } 250 int index = 0; 251 return _FindPageIndex(pPages, skip_count, objnum, index); 252} 253int CPDF_Document::GetPageCount() const 254{ 255 return m_PageList.GetSize(); 256} 257static int _CountPages(CPDF_Dictionary* pPages, int level) 258{ 259 if (level > 128) { 260 return 0; 261 } 262 int count = pPages->GetInteger(FX_BSTRC("Count")); 263 if (count > 0 && count < FPDF_PAGE_MAX_NUM) { 264 return count; 265 } 266 CPDF_Array* pKidList = pPages->GetArray(FX_BSTRC("Kids")); 267 if (pKidList == NULL) { 268 return 0; 269 } 270 count = 0; 271 for (FX_DWORD i = 0; i < pKidList->GetCount(); i ++) { 272 CPDF_Dictionary* pKid = pKidList->GetDict(i); 273 if (pKid == NULL) { 274 continue; 275 } 276 if (!pKid->KeyExist(FX_BSTRC("Kids"))) { 277 count ++; 278 } else { 279 count += _CountPages(pKid, level + 1); 280 } 281 } 282 pPages->SetAtInteger(FX_BSTRC("Count"), count); 283 return count; 284} 285int CPDF_Document::_GetPageCount() const 286{ 287 CPDF_Dictionary* pRoot = GetRoot(); 288 if (pRoot == NULL) { 289 return 0; 290 } 291 CPDF_Dictionary* pPages = pRoot->GetDict(FX_BSTRC("Pages")); 292 if (pPages == NULL) { 293 return 0; 294 } 295 if (!pPages->KeyExist(FX_BSTRC("Kids"))) { 296 return 1; 297 } 298 return _CountPages(pPages, 0); 299} 300FX_BOOL CPDF_Document::IsContentUsedElsewhere(FX_DWORD objnum, CPDF_Dictionary* pThisPageDict) 301{ 302 for (int i = 0; i < m_PageList.GetSize(); i ++) { 303 CPDF_Dictionary* pPageDict = GetPage(i); 304 if (pPageDict == pThisPageDict) { 305 continue; 306 } 307 CPDF_Object* pContents = pPageDict ? pPageDict->GetElement(FX_BSTRC("Contents")) : NULL; 308 if (pContents == NULL) { 309 continue; 310 } 311 if (pContents->GetDirectType() == PDFOBJ_ARRAY) { 312 CPDF_Array* pArray = (CPDF_Array*)pContents->GetDirect(); 313 for (FX_DWORD j = 0; j < pArray->GetCount(); j ++) { 314 CPDF_Object* pRef = pArray->GetElement(j); 315 if (pRef == NULL || pRef->GetType() != PDFOBJ_REFERENCE) { 316 continue; 317 } 318 if (((CPDF_Reference*) pRef)->GetRefObjNum() == objnum) { 319 return TRUE; 320 } 321 } 322 } else if (pContents->GetObjNum() == objnum) { 323 return TRUE; 324 } 325 } 326 return FALSE; 327} 328FX_DWORD CPDF_Document::GetUserPermissions(FX_BOOL bCheckRevision) const 329{ 330 if (m_pParser == NULL) { 331 return (FX_DWORD) - 1; 332 } 333 return m_pParser->GetPermissions(bCheckRevision); 334} 335FX_BOOL CPDF_Document::IsOwner() const 336{ 337 if (m_pParser == NULL) { 338 return TRUE; 339 } 340 return m_pParser->IsOwner(); 341} 342FX_BOOL CPDF_Document::IsFormStream(FX_DWORD objnum, FX_BOOL& bForm) const 343{ 344 { 345 CPDF_Object* pObj; 346 if (m_IndirectObjs.Lookup((FX_LPVOID)(FX_UINTPTR)objnum, (FX_LPVOID&)pObj)) { 347 bForm = pObj->GetType() == PDFOBJ_STREAM && 348 ((CPDF_Stream*)pObj)->GetDict()->GetString(FX_BSTRC("Subtype")) == FX_BSTRC("Form"); 349 return TRUE; 350 } 351 } 352 if (m_pParser == NULL) { 353 bForm = FALSE; 354 return TRUE; 355 } 356 return m_pParser->IsFormStream(objnum, bForm); 357} 358void CPDF_Document::ClearPageData() 359{ 360 if (m_pDocPage) { 361 CPDF_ModuleMgr::Get()->GetPageModule()->ClearDoc(this); 362 } 363} 364void CPDF_Document::ClearRenderData() 365{ 366 if (m_pDocRender) { 367 CPDF_ModuleMgr::Get()->GetRenderModule()->ClearDocData(m_pDocRender); 368 } 369} 370