From f0d9d28a034fe3650c3c2d662090c1e8687ddb16 Mon Sep 17 00:00:00 2001 From: Tom Sepez Date: Wed, 30 May 2018 16:40:00 +0000 Subject: Make CPDF_Document cache CPDF_Pages We cache pages not by page number, which can bounce around as pages are inserted or removed, but by page dictionary's object number. Since the page may be created under one function and used under another, we can't take the shortcut of not instantiating a render cache nor not parsing the page. Change-Id: I9a325cda8b3141153544ac53e78a51a44e6b411a Reviewed-on: https://pdfium-review.googlesource.com/32830 Commit-Queue: Tom Sepez Reviewed-by: dsinclair --- core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp | 6 +++--- core/fpdfapi/page/cpdf_page.cpp | 4 ++-- core/fpdfapi/page/cpdf_page.h | 7 +++++-- core/fpdfapi/parser/cpdf_document.cpp | 13 +++++++++++++ core/fpdfapi/parser/cpdf_document.h | 10 +++++++++- 5 files changed, 32 insertions(+), 8 deletions(-) (limited to 'core') diff --git a/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp b/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp index 1244b12331..859f5b3991 100644 --- a/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp +++ b/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp @@ -129,7 +129,7 @@ TEST_F(CPDF_PageContentGeneratorTest, ProcessGraphics) { auto pDoc = pdfium::MakeUnique(nullptr); pDoc->CreateNewDoc(); CPDF_Dictionary* pPageDict = pDoc->CreateNewPage(0); - auto pTestPage = pdfium::MakeRetain(pDoc.get(), pPageDict, false); + RetainPtr pTestPage = pDoc->GetOrCreatePDFPage(pPageDict); CPDF_PageContentGenerator generator(pTestPage.Get()); std::ostringstream buf; TestProcessPath(&generator, &buf, pPathObj.get()); @@ -168,7 +168,7 @@ TEST_F(CPDF_PageContentGeneratorTest, ProcessStandardText) { auto pDoc = pdfium::MakeUnique(nullptr); pDoc->CreateNewDoc(); CPDF_Dictionary* pPageDict = pDoc->CreateNewPage(0); - auto pTestPage = pdfium::MakeRetain(pDoc.get(), pPageDict, false); + RetainPtr pTestPage = pDoc->GetOrCreatePDFPage(pPageDict); CPDF_PageContentGenerator generator(pTestPage.Get()); auto pTextObj = pdfium::MakeUnique(); CPDF_Font* pFont = CPDF_Font::GetStockFont(pDoc.get(), "Times-Roman"); @@ -231,7 +231,7 @@ TEST_F(CPDF_PageContentGeneratorTest, ProcessText) { auto pDoc = pdfium::MakeUnique(nullptr); pDoc->CreateNewDoc(); CPDF_Dictionary* pPageDict = pDoc->CreateNewPage(0); - auto pTestPage = pdfium::MakeRetain(pDoc.get(), pPageDict, false); + RetainPtr pTestPage = pDoc->GetOrCreatePDFPage(pPageDict); CPDF_PageContentGenerator generator(pTestPage.Get()); std::ostringstream buf; diff --git a/core/fpdfapi/page/cpdf_page.cpp b/core/fpdfapi/page/cpdf_page.cpp index 7c0a3234c9..c5c85635b2 100644 --- a/core/fpdfapi/page/cpdf_page.cpp +++ b/core/fpdfapi/page/cpdf_page.cpp @@ -21,11 +21,11 @@ CPDF_Page::CPDF_Page(CPDF_Document* pDocument, CPDF_Dictionary* pPageDict, - bool bPageCache) + bool bUseRenderCache) : CPDF_PageObjectHolder(pDocument, pPageDict), m_PageSize(100, 100), m_pPDFDocument(pDocument) { - if (bPageCache) + if (bUseRenderCache) m_pPageRender = pdfium::MakeUnique(this); if (!pPageDict) return; diff --git a/core/fpdfapi/page/cpdf_page.h b/core/fpdfapi/page/cpdf_page.h index 0bb99b73f1..b94326e47b 100644 --- a/core/fpdfapi/page/cpdf_page.h +++ b/core/fpdfapi/page/cpdf_page.h @@ -12,6 +12,7 @@ #include "core/fpdfapi/page/cpdf_pageobjectholder.h" #include "core/fxcrt/fx_coordinates.h" #include "core/fxcrt/fx_system.h" +#include "core/fxcrt/observable.h" #include "core/fxcrt/retain_ptr.h" #include "core/fxcrt/unowned_ptr.h" #include "third_party/base/optional.h" @@ -22,7 +23,9 @@ class CPDF_Object; class CPDF_PageRenderCache; class CPDF_PageRenderContext; -class CPDF_Page : public Retainable, public CPDF_PageObjectHolder { +class CPDF_Page : public Retainable, + public Observable, + public CPDF_PageObjectHolder { public: class View {}; // Caller implements as desired, empty here due to layering. class Extension : public Retainable {}; // XFA page parent class, layering. @@ -66,7 +69,7 @@ class CPDF_Page : public Retainable, public CPDF_PageObjectHolder { private: CPDF_Page(CPDF_Document* pDocument, CPDF_Dictionary* pPageDict, - bool bPageCache); + bool bUseRenderCache); ~CPDF_Page() override; void StartParse(); diff --git a/core/fpdfapi/parser/cpdf_document.cpp b/core/fpdfapi/parser/cpdf_document.cpp index 7968d1b019..2e4baabe91 100644 --- a/core/fpdfapi/parser/cpdf_document.cpp +++ b/core/fpdfapi/parser/cpdf_document.cpp @@ -602,6 +602,19 @@ bool CPDF_Document::InsertNewPage(int iPage, CPDF_Dictionary* pPageDict) { return true; } +RetainPtr CPDF_Document::GetOrCreatePDFPage( + CPDF_Dictionary* pPageDict) { + std::pair key = {pPageDict->GetObjNum(), + pPageDict->GetGenNum()}; + if (m_PageMap[key]) + return RetainPtr(m_PageMap[key].Get()); + + auto pPage = pdfium::MakeRetain(this, pPageDict, true); + pPage->ParseContent(); + m_PageMap[key].Reset(pPage.Get()); + return pPage; +} + void CPDF_Document::DeletePage(int iPage) { CPDF_Dictionary* pPages = GetPagesDict(); if (!pPages) diff --git a/core/fpdfapi/parser/cpdf_document.h b/core/fpdfapi/parser/cpdf_document.h index c2774b163a..c240e77567 100644 --- a/core/fpdfapi/parser/cpdf_document.h +++ b/core/fpdfapi/parser/cpdf_document.h @@ -8,6 +8,7 @@ #define CORE_FPDFAPI_PARSER_CPDF_DOCUMENT_H_ #include +#include #include #include #include @@ -64,6 +65,7 @@ class CPDF_Document : public CPDF_IndirectObjectHolder { const CPDF_Dictionary* GetInfo() const { return m_pInfoDict.Get(); } CPDF_Dictionary* GetInfo() { return m_pInfoDict.Get(); } + RetainPtr GetOrCreatePDFPage(CPDF_Dictionary* pPageDict); void DeletePage(int iPage); int GetPageCount() const; bool IsPageLoaded(int iPage) const; @@ -167,7 +169,13 @@ class CPDF_Document : public CPDF_IndirectObjectHolder { std::unique_ptr m_pDocRender; std::unique_ptr m_pCodecContext; std::unique_ptr m_pLinksContext; - std::vector m_PageList; // Page number to page's dict objnum. + + // Page number (index) to page's dict objnum. + std::vector m_PageList; + + // Dict {objnum, gennum} to page mapping. + std::map, CPDF_Page::ObservedPtr> m_PageMap; + UnownedPtr m_pExtension; }; -- cgit v1.2.3