Chromium Code Reviews| 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 |