Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(371)

Side by Side Diff: core/fpdfapi/parser/cpdf_document.cpp

Issue 2470803003: Traverse PDF page tree only once in CPDF_Document Try 3 (Closed)
Patch Set: Comments Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « core/fpdfapi/parser/cpdf_document.h ('k') | core/fpdfapi/parser/cpdf_document_unittest.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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_
OLDNEW
« no previous file with comments | « core/fpdfapi/parser/cpdf_document.h ('k') | core/fpdfapi/parser/cpdf_document_unittest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698