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> |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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 Loading... | |
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_ |
OLD | NEW |