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

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

Issue 2414423002: Traverse PDF page tree only once in CPDF_Document (Closed)
Patch Set: Nits Created 4 years, 2 months 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
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>
11 #include <utility>
11 #include <vector> 12 #include <vector>
12 13
13 #include "core/fpdfapi/cpdf_modulemgr.h" 14 #include "core/fpdfapi/cpdf_modulemgr.h"
14 #include "core/fpdfapi/font/cpdf_fontencoding.h" 15 #include "core/fpdfapi/font/cpdf_fontencoding.h"
15 #include "core/fpdfapi/page/cpdf_docpagedata.h" 16 #include "core/fpdfapi/page/cpdf_docpagedata.h"
16 #include "core/fpdfapi/page/cpdf_pagemodule.h" 17 #include "core/fpdfapi/page/cpdf_pagemodule.h"
17 #include "core/fpdfapi/page/pageint.h" 18 #include "core/fpdfapi/page/pageint.h"
18 #include "core/fpdfapi/parser/cpdf_array.h" 19 #include "core/fpdfapi/parser/cpdf_array.h"
19 #include "core/fpdfapi/parser/cpdf_dictionary.h" 20 #include "core/fpdfapi/parser/cpdf_dictionary.h"
20 #include "core/fpdfapi/parser/cpdf_number.h" 21 #include "core/fpdfapi/parser/cpdf_number.h"
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after
255 if (pKid->GetStringFor("Type") == "Page") { 256 if (pKid->GetStringFor("Type") == "Page") {
256 if (nPagesToGo == 0) { 257 if (nPagesToGo == 0) {
257 if (bInsert) { 258 if (bInsert) {
258 pKidList->InsertAt(i, new CPDF_Reference(pDoc, pPage->GetObjNum())); 259 pKidList->InsertAt(i, new CPDF_Reference(pDoc, pPage->GetObjNum()));
259 pPage->SetReferenceFor("Parent", pDoc, pPages->GetObjNum()); 260 pPage->SetReferenceFor("Parent", pDoc, pPages->GetObjNum());
260 } else { 261 } else {
261 pKidList->RemoveAt(i); 262 pKidList->RemoveAt(i);
262 } 263 }
263 pPages->SetIntegerFor( 264 pPages->SetIntegerFor(
264 "Count", pPages->GetIntegerFor("Count") + (bInsert ? 1 : -1)); 265 "Count", pPages->GetIntegerFor("Count") + (bInsert ? 1 : -1));
266 // Tree will change, so reset tree transversal variables
267 pDoc->m_iLastPageTraversed = -1;
268 pDoc->m_pTreeTraversal = std::stack<std::pair<CPDF_Dictionary*, int>>();
265 return 1; 269 return 1;
266 } 270 }
267 nPagesToGo--; 271 nPagesToGo--;
268 } else { 272 } else {
269 int nPages = pKid->GetIntegerFor("Count"); 273 int nPages = pKid->GetIntegerFor("Count");
270 if (nPagesToGo < nPages) { 274 if (nPagesToGo < nPages) {
271 if (pdfium::ContainsKey(*pVisited, pKid)) 275 if (pdfium::ContainsKey(*pVisited, pKid))
272 return -1; 276 return -1;
273 277
274 pdfium::ScopedSetInsertion<CPDF_Dictionary*> insertion(pVisited, pKid); 278 pdfium::ScopedSetInsertion<CPDF_Dictionary*> insertion(pVisited, pKid);
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after
403 pFontDesc->SetIntegerFor("Ascent", ascend); 407 pFontDesc->SetIntegerFor("Ascent", ascend);
404 pFontDesc->SetIntegerFor("Descent", descend); 408 pFontDesc->SetIntegerFor("Descent", descend);
405 pFontDesc->SetIntegerFor("StemV", stemV); 409 pFontDesc->SetIntegerFor("StemV", stemV);
406 return pFontDesc; 410 return pFontDesc;
407 } 411 }
408 412
409 } // namespace 413 } // namespace
410 414
411 CPDF_Document::CPDF_Document(std::unique_ptr<CPDF_Parser> pParser) 415 CPDF_Document::CPDF_Document(std::unique_ptr<CPDF_Parser> pParser)
412 : CPDF_IndirectObjectHolder(), 416 : CPDF_IndirectObjectHolder(),
417 m_iLastPageTraversed(-1),
413 m_pParser(std::move(pParser)), 418 m_pParser(std::move(pParser)),
414 m_pRootDict(nullptr), 419 m_pRootDict(nullptr),
415 m_pInfoDict(nullptr), 420 m_pInfoDict(nullptr),
416 m_bLinearized(false), 421 m_bLinearized(false),
417 m_iFirstPageNo(0), 422 m_iFirstPageNo(0),
418 m_dwFirstPageObjNum(0), 423 m_dwFirstPageObjNum(0),
419 m_pDocPage(new CPDF_DocPageData(this)), 424 m_pDocPage(new CPDF_DocPageData(this)),
420 m_pDocRender(new CPDF_DocRenderData(this)), 425 m_pDocRender(new CPDF_DocRenderData(this)),
421 m_pByteStringPool(pdfium::MakeUnique<CFX_ByteStringPool>()) { 426 m_pByteStringPool(pdfium::MakeUnique<CFX_ByteStringPool>()) {
422 if (pParser) 427 if (pParser)
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
470 475
471 CPDF_Object* pObjNum = pLinearizationParams->GetObjectFor("O"); 476 CPDF_Object* pObjNum = pLinearizationParams->GetObjectFor("O");
472 if (ToNumber(pObjNum)) 477 if (ToNumber(pObjNum))
473 m_dwFirstPageObjNum = pObjNum->GetInteger(); 478 m_dwFirstPageObjNum = pObjNum->GetInteger();
474 } 479 }
475 480
476 void CPDF_Document::LoadPages() { 481 void CPDF_Document::LoadPages() {
477 m_PageList.SetSize(RetrievePageCount()); 482 m_PageList.SetSize(RetrievePageCount());
478 } 483 }
479 484
480 CPDF_Dictionary* CPDF_Document::FindPDFPage(CPDF_Dictionary* pPages, 485 CPDF_Dictionary* CPDF_Document::TraversePDFPages(int iPage, int nPagesToGo) {
481 int iPage, 486 std::pair<CPDF_Dictionary*, int>* lastProc = &m_pTreeTraversal.top();
482 int nPagesToGo, 487 CPDF_Dictionary* pPages = lastProc->first;
483 int level) {
484 CPDF_Array* pKidList = pPages->GetArrayFor("Kids"); 488 CPDF_Array* pKidList = pPages->GetArrayFor("Kids");
485 if (!pKidList) 489 if (!pKidList) {
486 return nPagesToGo == 0 ? pPages : nullptr; 490 m_pTreeTraversal.pop();
491 if (nPagesToGo != 1)
npm 2016/10/17 21:10:23 Before nPagesToGo was the number of pages left min
dsinclair 2016/10/18 13:35:59 So, this is check if we're on the page we're looki
npm 2016/10/18 14:26:31 The if(!pKidList) will only be entered when the ro
492 return nullptr;
493 m_PageList.SetAt(iPage, pPages->GetObjNum());
494 return pPages;
495 }
487 496
488 if (level >= FX_MAX_PAGE_LEVEL) 497 if (m_pTreeTraversal.size() >= FX_MAX_PAGE_LEVEL) {
498 m_pTreeTraversal.pop();
489 return nullptr; 499 return nullptr;
500 }
490 501
491 for (size_t i = 0; i < pKidList->GetCount(); i++) { 502 bool shouldFinish = pPages->GetIntegerFor("Count") <= nPagesToGo;
npm 2016/10/17 21:10:23 This will make sure that the page is popped proper
503 CPDF_Dictionary* page = nullptr;
504 for (size_t i = lastProc->second + 1; i < pKidList->GetCount(); i++) {
npm 2016/10/17 21:10:23 lastProc->second is the index of the last complete
492 CPDF_Dictionary* pKid = pKidList->GetDictAt(i); 505 CPDF_Dictionary* pKid = pKidList->GetDictAt(i);
493 if (!pKid) { 506 if (!pKid) {
494 nPagesToGo--; 507 nPagesToGo--;
508 lastProc->second++;
495 continue; 509 continue;
496 } 510 }
497 if (pKid == pPages) 511 if (pKid == pPages) {
512 lastProc->second++;
498 continue; 513 continue;
514 }
499 if (!pKid->KeyExist("Kids")) { 515 if (!pKid->KeyExist("Kids")) {
500 if (nPagesToGo == 0) 516 m_PageList.SetAt(iPage - nPagesToGo + 1, pKid->GetObjNum());
501 return pKid;
502
503 m_PageList.SetAt(iPage - nPagesToGo, pKid->GetObjNum());
504 nPagesToGo--; 517 nPagesToGo--;
518 lastProc->second++;
519 if (nPagesToGo == 0) {
520 page = pKid;
521 break;
522 }
505 } else { 523 } else {
506 int nPages = pKid->GetIntegerFor("Count"); 524 int nPages = pKid->GetIntegerFor("Count");
507 if (nPagesToGo < nPages) 525 m_pTreeTraversal.push(std::make_pair(pKid, -1));
508 return FindPDFPage(pKid, iPage, nPagesToGo, level + 1); 526 CPDF_Dictionary* pageKid = TraversePDFPages(iPage, nPagesToGo);
509 527 // If the stack top is current element, kid was completely processed.
528 if (lastProc == &m_pTreeTraversal.top())
529 lastProc->second++;
530 if (nPagesToGo <= nPages) {
531 page = pageKid;
532 break;
533 }
510 nPagesToGo -= nPages; 534 nPagesToGo -= nPages;
511 } 535 }
512 } 536 }
513 return nullptr; 537 if (shouldFinish ||
538 lastProc->second == static_cast<int>(pKidList->GetCount() - 1)) {
539 m_pTreeTraversal.pop();
540 }
541 return page;
514 } 542 }
515 543
516 CPDF_Dictionary* CPDF_Document::GetPagesDict() const { 544 CPDF_Dictionary* CPDF_Document::GetPagesDict() const {
517 CPDF_Dictionary* pRoot = GetRoot(); 545 CPDF_Dictionary* pRoot = GetRoot();
518 return pRoot ? pRoot->GetDictFor("Pages") : nullptr; 546 return pRoot ? pRoot->GetDictFor("Pages") : nullptr;
519 } 547 }
520 548
521 bool CPDF_Document::IsPageLoaded(int iPage) const { 549 bool CPDF_Document::IsPageLoaded(int iPage) const {
522 return !!m_PageList.GetAt(iPage); 550 return !!m_PageList.GetAt(iPage);
523 } 551 }
524 552
525 CPDF_Dictionary* CPDF_Document::GetPage(int iPage) { 553 CPDF_Dictionary* CPDF_Document::GetPage(int iPage) {
526 if (iPage < 0 || iPage >= m_PageList.GetSize()) 554 if (iPage < 0 || iPage >= m_PageList.GetSize())
527 return nullptr; 555 return nullptr;
528 556
529 if (m_bLinearized && (iPage == m_iFirstPageNo)) { 557 if (m_bLinearized && (iPage == m_iFirstPageNo)) {
530 if (CPDF_Dictionary* pDict = 558 if (CPDF_Dictionary* pDict =
531 ToDictionary(GetOrParseIndirectObject(m_dwFirstPageObjNum))) { 559 ToDictionary(GetOrParseIndirectObject(m_dwFirstPageObjNum))) {
532 return pDict; 560 return pDict;
533 } 561 }
534 } 562 }
535 563
536 int objnum = m_PageList.GetAt(iPage); 564 int objnum = m_PageList.GetAt(iPage);
537 if (objnum) { 565 if (!objnum || m_iLastPageTraversed < iPage) {
538 if (CPDF_Dictionary* pDict = ToDictionary(GetOrParseIndirectObject(objnum))) 566 CPDF_Dictionary* pPages = GetPagesDict();
539 return pDict; 567 if (!pPages)
568 return nullptr;
569 if (m_pTreeTraversal.empty())
570 m_pTreeTraversal.push(std::make_pair(pPages, -1));
571 CPDF_Dictionary* page = TraversePDFPages(m_iLastPageTraversed + 1,
572 iPage - m_iLastPageTraversed);
573 m_iLastPageTraversed = iPage;
574 return page;
540 } 575 }
541 576 if (CPDF_Dictionary* pDict = ToDictionary(GetOrParseIndirectObject(objnum)))
542 CPDF_Dictionary* pPages = GetPagesDict(); 577 return pDict;
543 if (!pPages) 578 return nullptr;
544 return nullptr;
545
546 CPDF_Dictionary* pPage = FindPDFPage(pPages, iPage, iPage, 0);
547 if (!pPage)
548 return nullptr;
549
550 m_PageList.SetAt(iPage, pPage->GetObjNum());
551 return pPage;
552 } 579 }
553 580
554 void CPDF_Document::SetPageObjNum(int iPage, uint32_t objNum) { 581 void CPDF_Document::SetPageObjNum(int iPage, uint32_t objNum) {
555 m_PageList.SetAt(iPage, objNum); 582 m_PageList.SetAt(iPage, objNum);
556 } 583 }
557 584
558 int CPDF_Document::FindPageIndex(CPDF_Dictionary* pNode, 585 int CPDF_Document::FindPageIndex(CPDF_Dictionary* pNode,
559 uint32_t& skip_count, 586 uint32_t& skip_count,
560 uint32_t objnum, 587 uint32_t objnum,
561 int& index, 588 int& index,
(...skipping 451 matching lines...) Expand 10 before | Expand all | Expand 10 after
1013 pBBox, pLogFont->lfWeight / 5); 1040 pBBox, pLogFont->lfWeight / 5);
1014 pFontDesc->SetIntegerFor("CapHeight", capheight); 1041 pFontDesc->SetIntegerFor("CapHeight", capheight);
1015 pFontDict->SetReferenceFor("FontDescriptor", this, 1042 pFontDict->SetReferenceFor("FontDescriptor", this,
1016 AddIndirectObject(pFontDesc)); 1043 AddIndirectObject(pFontDesc));
1017 hFont = SelectObject(hDC, hFont); 1044 hFont = SelectObject(hDC, hFont);
1018 DeleteObject(hFont); 1045 DeleteObject(hFont);
1019 DeleteDC(hDC); 1046 DeleteDC(hDC);
1020 return LoadFont(pBaseDict); 1047 return LoadFont(pBaseDict);
1021 } 1048 }
1022 #endif // _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ 1049 #endif // _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
OLDNEW
« core/fpdfapi/parser/cpdf_document.h ('K') | « core/fpdfapi/parser/cpdf_document.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698