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 // When this is called, m_pTreeTraversal[level] exists |
Lei Zhang
2016/11/04 01:38:52
Move documentation to the header, or make it an AS
npm
2016/11/04 19:33:33
Done.
| |
404 int iPage, | 405 CPDF_Dictionary* CPDF_Document::TraversePDFPages(int iPage, |
405 int nPagesToGo, | 406 int& nPagesToGo, |
406 int level) { | 407 int level) { |
408 if (nPagesToGo < 0) | |
409 return nullptr; | |
410 CPDF_Dictionary* pPages = m_pTreeTraversal[level].first; | |
407 CPDF_Array* pKidList = pPages->GetArrayFor("Kids"); | 411 CPDF_Array* pKidList = pPages->GetArrayFor("Kids"); |
408 if (!pKidList) | 412 if (!pKidList) { |
409 return nPagesToGo == 0 ? pPages : nullptr; | 413 if (nPagesToGo != 1) |
414 return nullptr; | |
415 m_PageList.SetAt(iPage, pPages->GetObjNum()); | |
416 return pPages; | |
417 } | |
410 | 418 |
411 if (level >= FX_MAX_PAGE_LEVEL) | 419 if (level >= FX_MAX_PAGE_LEVEL) { |
420 m_pTreeTraversal.pop_back(); | |
412 return nullptr; | 421 return nullptr; |
422 } | |
413 | 423 |
414 for (size_t i = 0; i < pKidList->GetCount(); i++) { | 424 CPDF_Dictionary* page = nullptr; |
425 for (size_t i = m_pTreeTraversal[level].second; i < pKidList->GetCount(); | |
426 i++) { | |
427 if (nPagesToGo == 0) | |
428 break; | |
415 CPDF_Dictionary* pKid = pKidList->GetDictAt(i); | 429 CPDF_Dictionary* pKid = pKidList->GetDictAt(i); |
416 if (!pKid) { | 430 if (!pKid) { |
417 nPagesToGo--; | 431 nPagesToGo--; |
432 m_pTreeTraversal[level].second++; | |
418 continue; | 433 continue; |
419 } | 434 } |
420 if (pKid == pPages) | 435 if (pKid == pPages) { |
436 m_pTreeTraversal[level].second++; | |
421 continue; | 437 continue; |
438 } | |
422 if (!pKid->KeyExist("Kids")) { | 439 if (!pKid->KeyExist("Kids")) { |
423 if (nPagesToGo == 0) | 440 m_PageList.SetAt(iPage - nPagesToGo + 1, pKid->GetObjNum()); |
424 return pKid; | |
425 | |
426 m_PageList.SetAt(iPage - nPagesToGo, pKid->GetObjNum()); | |
427 nPagesToGo--; | 441 nPagesToGo--; |
442 m_pTreeTraversal[level].second++; | |
443 if (nPagesToGo == 0) { | |
444 page = pKid; | |
445 break; | |
446 } | |
428 } else { | 447 } else { |
429 int nPages = pKid->GetIntegerFor("Count"); | 448 // If the vector has size level+1, the child is not in yet |
430 if (nPagesToGo < nPages) | 449 if (static_cast<int>(m_pTreeTraversal.size()) == level + 1) |
Lei Zhang
2016/11/04 01:38:52
Should |level| be a size_t since it's an index int
npm
2016/11/04 19:33:33
Yes, I remember I tried this and failed, maybe for
| |
431 return FindPDFPage(pKid, iPage, nPagesToGo, level + 1); | 450 m_pTreeTraversal.push_back(std::make_pair(pKid, 0)); |
432 | 451 // Now m_pTreeTraversal[level+1] should exist and be equal to pKid. |
433 nPagesToGo -= nPages; | 452 CPDF_Dictionary* pageKid = TraversePDFPages(iPage, nPagesToGo, level + 1); |
453 // Check if child was completely processed, i.e. it popped itself out | |
454 if (static_cast<int>(m_pTreeTraversal.size()) == level + 1) | |
455 m_pTreeTraversal[level].second++; | |
456 // If child did not finish or if no pages to go, we are done | |
457 if (static_cast<int>(m_pTreeTraversal.size()) != level + 1 || | |
npm
2016/11/03 22:37:57
Just noticed this 'if' might be causing confusion.
| |
458 nPagesToGo == 0) { | |
459 page = pageKid; | |
460 break; | |
461 } | |
434 } | 462 } |
435 } | 463 } |
436 return nullptr; | 464 if (m_pTreeTraversal[level].second == |
465 static_cast<int>(pKidList->GetCount())) { | |
466 m_pTreeTraversal.pop_back(); | |
467 } | |
468 return page; | |
437 } | 469 } |
438 | 470 |
439 CPDF_Dictionary* CPDF_Document::GetPagesDict() const { | 471 CPDF_Dictionary* CPDF_Document::GetPagesDict() const { |
440 CPDF_Dictionary* pRoot = GetRoot(); | 472 CPDF_Dictionary* pRoot = GetRoot(); |
441 return pRoot ? pRoot->GetDictFor("Pages") : nullptr; | 473 return pRoot ? pRoot->GetDictFor("Pages") : nullptr; |
442 } | 474 } |
443 | 475 |
444 bool CPDF_Document::IsPageLoaded(int iPage) const { | 476 bool CPDF_Document::IsPageLoaded(int iPage) const { |
445 return !!m_PageList.GetAt(iPage); | 477 return !!m_PageList.GetAt(iPage); |
446 } | 478 } |
447 | 479 |
448 CPDF_Dictionary* CPDF_Document::GetPage(int iPage) { | 480 CPDF_Dictionary* CPDF_Document::GetPage(int iPage) { |
449 if (iPage < 0 || iPage >= m_PageList.GetSize()) | 481 if (iPage < 0 || iPage >= m_PageList.GetSize()) |
450 return nullptr; | 482 return nullptr; |
451 | 483 |
452 if (m_bLinearized && (iPage == m_iFirstPageNo)) { | 484 if (m_bLinearized && (iPage == m_iFirstPageNo)) { |
453 if (CPDF_Dictionary* pDict = | 485 if (CPDF_Dictionary* pDict = |
454 ToDictionary(GetOrParseIndirectObject(m_dwFirstPageObjNum))) { | 486 ToDictionary(GetOrParseIndirectObject(m_dwFirstPageObjNum))) { |
455 return pDict; | 487 return pDict; |
456 } | 488 } |
457 } | 489 } |
458 | 490 |
459 int objnum = m_PageList.GetAt(iPage); | 491 int objnum = m_PageList.GetAt(iPage); |
460 if (objnum) { | 492 if (objnum) { |
461 if (CPDF_Dictionary* pDict = ToDictionary(GetOrParseIndirectObject(objnum))) | 493 if (CPDF_Dictionary* pDict = ToDictionary(GetOrParseIndirectObject(objnum))) |
462 return pDict; | 494 return pDict; |
495 return nullptr; | |
463 } | 496 } |
464 | 497 |
465 CPDF_Dictionary* pPages = GetPagesDict(); | 498 CPDF_Dictionary* pPages = GetPagesDict(); |
466 if (!pPages) | 499 if (!pPages) |
467 return nullptr; | 500 return nullptr; |
468 | 501 |
469 CPDF_Dictionary* pPage = FindPDFPage(pPages, iPage, iPage, 0); | 502 if (m_pTreeTraversal.empty()) |
470 if (!pPage) | 503 m_pTreeTraversal.push_back(std::make_pair(pPages, 0)); |
471 return nullptr; | 504 int nPagesToGo = iPage - m_iNextPageToTraverse + 1; |
472 | 505 CPDF_Dictionary* pPage = TraversePDFPages(iPage, nPagesToGo, 0); |
473 m_PageList.SetAt(iPage, pPage->GetObjNum()); | 506 m_iNextPageToTraverse = iPage + 1; |
474 return pPage; | 507 return pPage; |
475 } | 508 } |
476 | 509 |
477 void CPDF_Document::SetPageObjNum(int iPage, uint32_t objNum) { | 510 void CPDF_Document::SetPageObjNum(int iPage, uint32_t objNum) { |
478 m_PageList.SetAt(iPage, objNum); | 511 m_PageList.SetAt(iPage, objNum); |
479 } | 512 } |
480 | 513 |
481 int CPDF_Document::FindPageIndex(CPDF_Dictionary* pNode, | 514 int CPDF_Document::FindPageIndex(CPDF_Dictionary* pNode, |
482 uint32_t& skip_count, | 515 uint32_t& skip_count, |
483 uint32_t objnum, | 516 uint32_t objnum, |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
657 continue; | 690 continue; |
658 } | 691 } |
659 if (bInsert) { | 692 if (bInsert) { |
660 pKidList->InsertAt(i, new CPDF_Reference(this, pPageDict->GetObjNum())); | 693 pKidList->InsertAt(i, new CPDF_Reference(this, pPageDict->GetObjNum())); |
661 pPageDict->SetReferenceFor("Parent", this, pPages->GetObjNum()); | 694 pPageDict->SetReferenceFor("Parent", this, pPages->GetObjNum()); |
662 } else { | 695 } else { |
663 pKidList->RemoveAt(i); | 696 pKidList->RemoveAt(i); |
664 } | 697 } |
665 pPages->SetIntegerFor( | 698 pPages->SetIntegerFor( |
666 "Count", pPages->GetIntegerFor("Count") + (bInsert ? 1 : -1)); | 699 "Count", pPages->GetIntegerFor("Count") + (bInsert ? 1 : -1)); |
700 // Tree will change, so reset tree transversal variables | |
Tom Sepez
2016/11/03 22:31:00
nit: maybe a ResetTraversal() helper method that d
npm
2016/11/04 19:33:33
Done.
| |
701 m_iNextPageToTraverse = 0; | |
702 m_pTreeTraversal.clear(); | |
667 break; | 703 break; |
668 } | 704 } |
669 int nPages = pKid->GetIntegerFor("Count"); | 705 int nPages = pKid->GetIntegerFor("Count"); |
670 if (nPagesToGo >= nPages) { | 706 if (nPagesToGo >= nPages) { |
671 nPagesToGo -= nPages; | 707 nPagesToGo -= nPages; |
672 continue; | 708 continue; |
673 } | 709 } |
674 if (pdfium::ContainsKey(*pVisited, pKid)) | 710 if (pdfium::ContainsKey(*pVisited, pKid)) |
675 return false; | 711 return false; |
676 | 712 |
(...skipping 20 matching lines...) Expand all Loading... | |
697 | 733 |
698 if (iPage == nPages) { | 734 if (iPage == nPages) { |
699 CPDF_Array* pPagesList = pPages->GetArrayFor("Kids"); | 735 CPDF_Array* pPagesList = pPages->GetArrayFor("Kids"); |
700 if (!pPagesList) { | 736 if (!pPagesList) { |
701 pPagesList = new CPDF_Array; | 737 pPagesList = new CPDF_Array; |
702 pPages->SetFor("Kids", pPagesList); | 738 pPages->SetFor("Kids", pPagesList); |
703 } | 739 } |
704 pPagesList->Add(new CPDF_Reference(this, pPageDict->GetObjNum())); | 740 pPagesList->Add(new CPDF_Reference(this, pPageDict->GetObjNum())); |
705 pPages->SetIntegerFor("Count", nPages + 1); | 741 pPages->SetIntegerFor("Count", nPages + 1); |
706 pPageDict->SetReferenceFor("Parent", this, pPages->GetObjNum()); | 742 pPageDict->SetReferenceFor("Parent", this, pPages->GetObjNum()); |
743 // Reset tree transversal variables | |
744 m_iNextPageToTraverse = 0; | |
745 m_pTreeTraversal.clear(); | |
707 } else { | 746 } else { |
708 std::set<CPDF_Dictionary*> stack = {pPages}; | 747 std::set<CPDF_Dictionary*> stack = {pPages}; |
709 if (!InsertDeletePDFPage(pPages, iPage, pPageDict, true, &stack)) | 748 if (!InsertDeletePDFPage(pPages, iPage, pPageDict, true, &stack)) |
710 return false; | 749 return false; |
711 } | 750 } |
712 m_PageList.InsertAt(iPage, pPageDict->GetObjNum()); | 751 m_PageList.InsertAt(iPage, pPageDict->GetObjNum()); |
713 return true; | 752 return true; |
714 } | 753 } |
715 | 754 |
716 void CPDF_Document::DeletePage(int iPage) { | 755 void CPDF_Document::DeletePage(int iPage) { |
(...skipping 292 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1009 pBBox, pLogFont->lfWeight / 5); | 1048 pBBox, pLogFont->lfWeight / 5); |
1010 pFontDesc->SetIntegerFor("CapHeight", capheight); | 1049 pFontDesc->SetIntegerFor("CapHeight", capheight); |
1011 pFontDict->SetReferenceFor("FontDescriptor", this, | 1050 pFontDict->SetReferenceFor("FontDescriptor", this, |
1012 AddIndirectObject(pFontDesc)); | 1051 AddIndirectObject(pFontDesc)); |
1013 hFont = SelectObject(hDC, hFont); | 1052 hFont = SelectObject(hDC, hFont); |
1014 DeleteObject(hFont); | 1053 DeleteObject(hFont); |
1015 DeleteDC(hDC); | 1054 DeleteDC(hDC); |
1016 return LoadFont(pBaseDict); | 1055 return LoadFont(pBaseDict); |
1017 } | 1056 } |
1018 #endif // _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ | 1057 #endif // _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_ |
OLD | NEW |