OLD | NEW |
1 // Copyright 2014 PDFium Authors. All rights reserved. | 1 // Copyright 2014 PDFium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com | 5 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com |
6 | 6 |
7 #include "core/fpdfapi/parser/cpdf_document.h" | 7 #include "core/fpdfapi/parser/cpdf_document.h" |
8 | 8 |
9 #include <memory> | 9 #include <memory> |
10 #include <set> | 10 #include <set> |
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
329 return pFontDesc; | 329 return pFontDesc; |
330 } | 330 } |
331 | 331 |
332 } // namespace | 332 } // namespace |
333 | 333 |
334 CPDF_Document::CPDF_Document(std::unique_ptr<CPDF_Parser> pParser) | 334 CPDF_Document::CPDF_Document(std::unique_ptr<CPDF_Parser> pParser) |
335 : CPDF_IndirectObjectHolder(), | 335 : CPDF_IndirectObjectHolder(), |
336 m_pParser(std::move(pParser)), | 336 m_pParser(std::move(pParser)), |
337 m_pRootDict(nullptr), | 337 m_pRootDict(nullptr), |
338 m_pInfoDict(nullptr), | 338 m_pInfoDict(nullptr), |
| 339 m_iNextPageToTraverse(0), |
339 m_bLinearized(false), | 340 m_bLinearized(false), |
340 m_iFirstPageNo(0), | 341 m_iFirstPageNo(0), |
341 m_dwFirstPageObjNum(0), | 342 m_dwFirstPageObjNum(0), |
342 m_pDocPage(new CPDF_DocPageData(this)), | 343 m_pDocPage(new CPDF_DocPageData(this)), |
343 m_pDocRender(new CPDF_DocRenderData(this)), | 344 m_pDocRender(new CPDF_DocRenderData(this)), |
344 m_pByteStringPool(pdfium::MakeUnique<CFX_ByteStringPool>()) { | 345 m_pByteStringPool(pdfium::MakeUnique<CFX_ByteStringPool>()) { |
345 if (pParser) | 346 if (pParser) |
346 SetLastObjNum(m_pParser->GetLastObjNum()); | 347 SetLastObjNum(m_pParser->GetLastObjNum()); |
347 } | 348 } |
348 | 349 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
393 | 394 |
394 CPDF_Object* pObjNum = pLinearizationParams->GetObjectFor("O"); | 395 CPDF_Object* pObjNum = pLinearizationParams->GetObjectFor("O"); |
395 if (ToNumber(pObjNum)) | 396 if (ToNumber(pObjNum)) |
396 m_dwFirstPageObjNum = pObjNum->GetInteger(); | 397 m_dwFirstPageObjNum = pObjNum->GetInteger(); |
397 } | 398 } |
398 | 399 |
399 void CPDF_Document::LoadPages() { | 400 void CPDF_Document::LoadPages() { |
400 m_PageList.SetSize(RetrievePageCount()); | 401 m_PageList.SetSize(RetrievePageCount()); |
401 } | 402 } |
402 | 403 |
403 CPDF_Dictionary* CPDF_Document::FindPDFPage(CPDF_Dictionary* pPages, | 404 CPDF_Dictionary* CPDF_Document::TraversePDFPages(int iPage, |
404 int iPage, | 405 int* nPagesToGo, |
405 int nPagesToGo, | 406 size_t level) { |
406 int level) { | 407 if (*nPagesToGo < 0) |
| 408 return nullptr; |
| 409 CPDF_Dictionary* pPages = m_pTreeTraversal[level].first; |
407 CPDF_Array* pKidList = pPages->GetArrayFor("Kids"); | 410 CPDF_Array* pKidList = pPages->GetArrayFor("Kids"); |
408 if (!pKidList) | 411 if (!pKidList) { |
409 return nPagesToGo == 0 ? pPages : nullptr; | 412 if (*nPagesToGo != 1) |
| 413 return nullptr; |
| 414 m_PageList.SetAt(iPage, pPages->GetObjNum()); |
| 415 return pPages; |
| 416 } |
410 | 417 |
411 if (level >= FX_MAX_PAGE_LEVEL) | 418 if (level >= FX_MAX_PAGE_LEVEL) { |
| 419 m_pTreeTraversal.pop_back(); |
412 return nullptr; | 420 return nullptr; |
| 421 } |
413 | 422 |
414 for (size_t i = 0; i < pKidList->GetCount(); i++) { | 423 CPDF_Dictionary* page = nullptr; |
| 424 for (size_t i = m_pTreeTraversal[level].second; i < pKidList->GetCount(); |
| 425 i++) { |
| 426 if (*nPagesToGo == 0) |
| 427 break; |
415 CPDF_Dictionary* pKid = pKidList->GetDictAt(i); | 428 CPDF_Dictionary* pKid = pKidList->GetDictAt(i); |
416 if (!pKid) { | 429 if (!pKid) { |
417 nPagesToGo--; | 430 (*nPagesToGo)--; |
| 431 m_pTreeTraversal[level].second++; |
418 continue; | 432 continue; |
419 } | 433 } |
420 if (pKid == pPages) | 434 if (pKid == pPages) { |
| 435 m_pTreeTraversal[level].second++; |
421 continue; | 436 continue; |
| 437 } |
422 if (!pKid->KeyExist("Kids")) { | 438 if (!pKid->KeyExist("Kids")) { |
423 if (nPagesToGo == 0) | 439 m_PageList.SetAt(iPage - (*nPagesToGo) + 1, pKid->GetObjNum()); |
424 return pKid; | 440 (*nPagesToGo)--; |
425 | 441 m_pTreeTraversal[level].second++; |
426 m_PageList.SetAt(iPage - nPagesToGo, pKid->GetObjNum()); | 442 if (*nPagesToGo == 0) { |
427 nPagesToGo--; | 443 page = pKid; |
| 444 break; |
| 445 } |
428 } else { | 446 } else { |
429 int nPages = pKid->GetIntegerFor("Count"); | 447 // If the vector has size level+1, the child is not in yet |
430 if (nPagesToGo < nPages) | 448 if (m_pTreeTraversal.size() == level + 1) |
431 return FindPDFPage(pKid, iPage, nPagesToGo, level + 1); | 449 m_pTreeTraversal.push_back(std::make_pair(pKid, 0)); |
432 | 450 // Now m_pTreeTraversal[level+1] should exist and be equal to pKid. |
433 nPagesToGo -= nPages; | 451 CPDF_Dictionary* pageKid = TraversePDFPages(iPage, nPagesToGo, level + 1); |
| 452 // Check if child was completely processed, i.e. it popped itself out |
| 453 if (m_pTreeTraversal.size() == level + 1) |
| 454 m_pTreeTraversal[level].second++; |
| 455 // If child did not finish or if no pages to go, we are done |
| 456 if (m_pTreeTraversal.size() != level + 1 || *nPagesToGo == 0) { |
| 457 page = pageKid; |
| 458 break; |
| 459 } |
434 } | 460 } |
435 } | 461 } |
436 return nullptr; | 462 if (m_pTreeTraversal[level].second == pKidList->GetCount()) |
| 463 m_pTreeTraversal.pop_back(); |
| 464 return page; |
| 465 } |
| 466 |
| 467 void CPDF_Document::ResetTraversal() { |
| 468 m_iNextPageToTraverse = 0; |
| 469 m_pTreeTraversal.clear(); |
437 } | 470 } |
438 | 471 |
439 CPDF_Dictionary* CPDF_Document::GetPagesDict() const { | 472 CPDF_Dictionary* CPDF_Document::GetPagesDict() const { |
440 CPDF_Dictionary* pRoot = GetRoot(); | 473 CPDF_Dictionary* pRoot = GetRoot(); |
441 return pRoot ? pRoot->GetDictFor("Pages") : nullptr; | 474 return pRoot ? pRoot->GetDictFor("Pages") : nullptr; |
442 } | 475 } |
443 | 476 |
444 bool CPDF_Document::IsPageLoaded(int iPage) const { | 477 bool CPDF_Document::IsPageLoaded(int iPage) const { |
445 return !!m_PageList.GetAt(iPage); | 478 return !!m_PageList.GetAt(iPage); |
446 } | 479 } |
447 | 480 |
448 CPDF_Dictionary* CPDF_Document::GetPage(int iPage) { | 481 CPDF_Dictionary* CPDF_Document::GetPage(int iPage) { |
449 if (iPage < 0 || iPage >= m_PageList.GetSize()) | 482 if (iPage < 0 || iPage >= m_PageList.GetSize()) |
450 return nullptr; | 483 return nullptr; |
451 | 484 |
452 if (m_bLinearized && (iPage == m_iFirstPageNo)) { | 485 if (m_bLinearized && (iPage == m_iFirstPageNo)) { |
453 if (CPDF_Dictionary* pDict = | 486 if (CPDF_Dictionary* pDict = |
454 ToDictionary(GetOrParseIndirectObject(m_dwFirstPageObjNum))) { | 487 ToDictionary(GetOrParseIndirectObject(m_dwFirstPageObjNum))) { |
455 return pDict; | 488 return pDict; |
456 } | 489 } |
457 } | 490 } |
458 | 491 |
459 int objnum = m_PageList.GetAt(iPage); | 492 int objnum = m_PageList.GetAt(iPage); |
460 if (objnum) { | 493 if (objnum) { |
461 if (CPDF_Dictionary* pDict = ToDictionary(GetOrParseIndirectObject(objnum))) | 494 if (CPDF_Dictionary* pDict = ToDictionary(GetOrParseIndirectObject(objnum))) |
462 return pDict; | 495 return pDict; |
| 496 return nullptr; |
463 } | 497 } |
464 | 498 |
465 CPDF_Dictionary* pPages = GetPagesDict(); | 499 CPDF_Dictionary* pPages = GetPagesDict(); |
466 if (!pPages) | 500 if (!pPages) |
467 return nullptr; | 501 return nullptr; |
468 | 502 |
469 CPDF_Dictionary* pPage = FindPDFPage(pPages, iPage, iPage, 0); | 503 if (m_pTreeTraversal.empty()) |
470 if (!pPage) | 504 m_pTreeTraversal.push_back(std::make_pair(pPages, 0)); |
471 return nullptr; | 505 int nPagesToGo = iPage - m_iNextPageToTraverse + 1; |
472 | 506 CPDF_Dictionary* pPage = TraversePDFPages(iPage, &nPagesToGo, 0); |
473 m_PageList.SetAt(iPage, pPage->GetObjNum()); | 507 m_iNextPageToTraverse = iPage + 1; |
474 return pPage; | 508 return pPage; |
475 } | 509 } |
476 | 510 |
477 void CPDF_Document::SetPageObjNum(int iPage, uint32_t objNum) { | 511 void CPDF_Document::SetPageObjNum(int iPage, uint32_t objNum) { |
478 m_PageList.SetAt(iPage, objNum); | 512 m_PageList.SetAt(iPage, objNum); |
479 } | 513 } |
480 | 514 |
481 int CPDF_Document::FindPageIndex(CPDF_Dictionary* pNode, | 515 int CPDF_Document::FindPageIndex(CPDF_Dictionary* pNode, |
482 uint32_t& skip_count, | 516 uint32_t& skip_count, |
483 uint32_t objnum, | 517 uint32_t objnum, |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
657 continue; | 691 continue; |
658 } | 692 } |
659 if (bInsert) { | 693 if (bInsert) { |
660 pKidList->InsertAt(i, new CPDF_Reference(this, pPageDict->GetObjNum())); | 694 pKidList->InsertAt(i, new CPDF_Reference(this, pPageDict->GetObjNum())); |
661 pPageDict->SetReferenceFor("Parent", this, pPages->GetObjNum()); | 695 pPageDict->SetReferenceFor("Parent", this, pPages->GetObjNum()); |
662 } else { | 696 } else { |
663 pKidList->RemoveAt(i); | 697 pKidList->RemoveAt(i); |
664 } | 698 } |
665 pPages->SetIntegerFor( | 699 pPages->SetIntegerFor( |
666 "Count", pPages->GetIntegerFor("Count") + (bInsert ? 1 : -1)); | 700 "Count", pPages->GetIntegerFor("Count") + (bInsert ? 1 : -1)); |
| 701 ResetTraversal(); |
667 break; | 702 break; |
668 } | 703 } |
669 int nPages = pKid->GetIntegerFor("Count"); | 704 int nPages = pKid->GetIntegerFor("Count"); |
670 if (nPagesToGo >= nPages) { | 705 if (nPagesToGo >= nPages) { |
671 nPagesToGo -= nPages; | 706 nPagesToGo -= nPages; |
672 continue; | 707 continue; |
673 } | 708 } |
674 if (pdfium::ContainsKey(*pVisited, pKid)) | 709 if (pdfium::ContainsKey(*pVisited, pKid)) |
675 return false; | 710 return false; |
676 | 711 |
(...skipping 20 matching lines...) Expand all Loading... |
697 | 732 |
698 if (iPage == nPages) { | 733 if (iPage == nPages) { |
699 CPDF_Array* pPagesList = pPages->GetArrayFor("Kids"); | 734 CPDF_Array* pPagesList = pPages->GetArrayFor("Kids"); |
700 if (!pPagesList) { | 735 if (!pPagesList) { |
701 pPagesList = new CPDF_Array; | 736 pPagesList = new CPDF_Array; |
702 pPages->SetFor("Kids", pPagesList); | 737 pPages->SetFor("Kids", pPagesList); |
703 } | 738 } |
704 pPagesList->Add(new CPDF_Reference(this, pPageDict->GetObjNum())); | 739 pPagesList->Add(new CPDF_Reference(this, pPageDict->GetObjNum())); |
705 pPages->SetIntegerFor("Count", nPages + 1); | 740 pPages->SetIntegerFor("Count", nPages + 1); |
706 pPageDict->SetReferenceFor("Parent", this, pPages->GetObjNum()); | 741 pPageDict->SetReferenceFor("Parent", this, pPages->GetObjNum()); |
| 742 ResetTraversal(); |
707 } else { | 743 } else { |
708 std::set<CPDF_Dictionary*> stack = {pPages}; | 744 std::set<CPDF_Dictionary*> stack = {pPages}; |
709 if (!InsertDeletePDFPage(pPages, iPage, pPageDict, true, &stack)) | 745 if (!InsertDeletePDFPage(pPages, iPage, pPageDict, true, &stack)) |
710 return false; | 746 return false; |
711 } | 747 } |
712 m_PageList.InsertAt(iPage, pPageDict->GetObjNum()); | 748 m_PageList.InsertAt(iPage, pPageDict->GetObjNum()); |
713 return true; | 749 return true; |
714 } | 750 } |
715 | 751 |
716 void CPDF_Document::DeletePage(int iPage) { | 752 void CPDF_Document::DeletePage(int iPage) { |
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1009 pBBox, pLogFont->lfWeight / 5); | 1045 pBBox, pLogFont->lfWeight / 5); |
1010 pFontDesc->SetIntegerFor("CapHeight", capheight); | 1046 pFontDesc->SetIntegerFor("CapHeight", capheight); |
1011 pFontDict->SetReferenceFor("FontDescriptor", this, | 1047 pFontDict->SetReferenceFor("FontDescriptor", this, |
1012 AddIndirectObject(pFontDesc)); | 1048 AddIndirectObject(pFontDesc)); |
1013 hFont = SelectObject(hDC, hFont); | 1049 hFont = SelectObject(hDC, hFont); |
1014 DeleteObject(hFont); | 1050 DeleteObject(hFont); |
1015 DeleteDC(hDC); | 1051 DeleteDC(hDC); |
1016 return LoadFont(pBaseDict); | 1052 return LoadFont(pBaseDict); |
1017 } | 1053 } |
1018 #endif // _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ | 1054 #endif // _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ |
OLD | NEW |