Begin work to get fpdfapi/render layered above fpdfapi/page.

Introduce two interfaces for the objects that the render layer
needs to attach to the page (but are otherwise sparsely used
by the page itself). Put the implementations into the render/
directory.

Change-Id: Id2fa5dcd7ac5b30f86189b2f4d3f2383eff18b71
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/58090
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp b/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp
index 1518e2a..d997420 100644
--- a/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp
+++ b/core/fpdfapi/edit/cpdf_pagecontentgenerator_unittest.cpp
@@ -58,7 +58,7 @@
 
   auto dummy_page_dict = pdfium::MakeRetain<CPDF_Dictionary>();
   auto pTestPage =
-      pdfium::MakeRetain<CPDF_Page>(nullptr, dummy_page_dict.Get(), false);
+      pdfium::MakeRetain<CPDF_Page>(nullptr, dummy_page_dict.Get());
   CPDF_PageContentGenerator generator(pTestPage.Get());
   std::ostringstream buf;
   TestProcessPath(&generator, &buf, pPathObj.get());
@@ -94,7 +94,7 @@
 
     auto dummy_page_dict = pdfium::MakeRetain<CPDF_Dictionary>();
     auto pTestPage =
-        pdfium::MakeRetain<CPDF_Page>(nullptr, dummy_page_dict.Get(), false);
+        pdfium::MakeRetain<CPDF_Page>(nullptr, dummy_page_dict.Get());
     CPDF_PageContentGenerator generator(pTestPage.Get());
     std::ostringstream buf;
     TestProcessPath(&generator, &buf, pPathObj.get());
@@ -128,7 +128,7 @@
         FXPT_TYPE::BezierTo, true);
     auto dummy_page_dict = pdfium::MakeRetain<CPDF_Dictionary>();
     auto pTestPage =
-        pdfium::MakeRetain<CPDF_Page>(nullptr, dummy_page_dict.Get(), false);
+        pdfium::MakeRetain<CPDF_Page>(nullptr, dummy_page_dict.Get());
     CPDF_PageContentGenerator generator(pTestPage.Get());
     std::ostringstream buf;
 
@@ -167,7 +167,7 @@
 
   auto dummy_page_dict = pdfium::MakeRetain<CPDF_Dictionary>();
   auto pTestPage =
-      pdfium::MakeRetain<CPDF_Page>(nullptr, dummy_page_dict.Get(), false);
+      pdfium::MakeRetain<CPDF_Page>(nullptr, dummy_page_dict.Get());
   CPDF_PageContentGenerator generator(pTestPage.Get());
   std::ostringstream buf;
   TestProcessPath(&generator, &buf, pPathObj.get());
@@ -202,7 +202,7 @@
 
   pDoc->CreateNewDoc();
   CPDF_Dictionary* pPageDict = pDoc->CreateNewPage(0);
-  auto pTestPage = pdfium::MakeRetain<CPDF_Page>(pDoc.get(), pPageDict, false);
+  auto pTestPage = pdfium::MakeRetain<CPDF_Page>(pDoc.get(), pPageDict);
   CPDF_PageContentGenerator generator(pTestPage.Get());
   std::ostringstream buf;
   TestProcessPath(&generator, &buf, pPathObj.get());
@@ -244,7 +244,7 @@
 
   pDoc->CreateNewDoc();
   CPDF_Dictionary* pPageDict = pDoc->CreateNewPage(0);
-  auto pTestPage = pdfium::MakeRetain<CPDF_Page>(pDoc.get(), pPageDict, false);
+  auto pTestPage = pdfium::MakeRetain<CPDF_Page>(pDoc.get(), pPageDict);
   CPDF_PageContentGenerator generator(pTestPage.Get());
   auto pTextObj = pdfium::MakeUnique<CPDF_TextObject>();
   CPDF_Font* pFont = CPDF_Font::GetStockFont(pDoc.get(), "Times-Roman");
@@ -310,7 +310,7 @@
   pDoc->CreateNewDoc();
 
   CPDF_Dictionary* pPageDict = pDoc->CreateNewPage(0);
-  auto pTestPage = pdfium::MakeRetain<CPDF_Page>(pDoc.get(), pPageDict, false);
+  auto pTestPage = pdfium::MakeRetain<CPDF_Page>(pDoc.get(), pPageDict);
   CPDF_PageContentGenerator generator(pTestPage.Get());
 
   std::ostringstream buf;
diff --git a/core/fpdfapi/page/BUILD.gn b/core/fpdfapi/page/BUILD.gn
index 18082ad..992fd0b 100644
--- a/core/fpdfapi/page/BUILD.gn
+++ b/core/fpdfapi/page/BUILD.gn
@@ -59,8 +59,6 @@
     "cpdf_pageobject.h",
     "cpdf_pageobjectholder.cpp",
     "cpdf_pageobjectholder.h",
-    "cpdf_pagerendercontext.cpp",
-    "cpdf_pagerendercontext.h",
     "cpdf_path.cpp",
     "cpdf_path.h",
     "cpdf_pathobject.cpp",
diff --git a/core/fpdfapi/page/cpdf_image.cpp b/core/fpdfapi/page/cpdf_image.cpp
index d405113..c057966 100644
--- a/core/fpdfapi/page/cpdf_image.cpp
+++ b/core/fpdfapi/page/cpdf_image.cpp
@@ -23,7 +23,6 @@
 #include "core/fpdfapi/parser/cpdf_stream.h"
 #include "core/fpdfapi/parser/cpdf_string.h"
 #include "core/fpdfapi/render/cpdf_dibbase.h"
-#include "core/fpdfapi/render/cpdf_pagerendercache.h"
 #include "core/fxcodec/fx_codec.h"
 #include "core/fxcodec/jpeg/jpegmodule.h"
 #include "core/fxcrt/fx_stream.h"
@@ -337,7 +336,7 @@
 
 void CPDF_Image::ResetCache(CPDF_Page* pPage) {
   RetainPtr<CPDF_Image> pHolder(this);
-  pPage->GetRenderCache()->ResetBitmap(pHolder);
+  pPage->GetRenderCache()->ResetBitmapForImage(pHolder);
 }
 
 RetainPtr<CFX_DIBBase> CPDF_Image::LoadDIBBase() const {
diff --git a/core/fpdfapi/page/cpdf_page.cpp b/core/fpdfapi/page/cpdf_page.cpp
index d3adfec..86256d5 100644
--- a/core/fpdfapi/page/cpdf_page.cpp
+++ b/core/fpdfapi/page/cpdf_page.cpp
@@ -12,23 +12,17 @@
 #include "constants/page_object.h"
 #include "core/fpdfapi/page/cpdf_contentparser.h"
 #include "core/fpdfapi/page/cpdf_pageobject.h"
-#include "core/fpdfapi/page/cpdf_pagerendercontext.h"
 #include "core/fpdfapi/parser/cpdf_array.h"
 #include "core/fpdfapi/parser/cpdf_dictionary.h"
 #include "core/fpdfapi/parser/cpdf_object.h"
-#include "core/fpdfapi/render/cpdf_pagerendercache.h"
 #include "third_party/base/ptr_util.h"
 #include "third_party/base/stl_util.h"
 
-CPDF_Page::CPDF_Page(CPDF_Document* pDocument,
-                     CPDF_Dictionary* pPageDict,
-                     bool bPageCache)
+CPDF_Page::CPDF_Page(CPDF_Document* pDocument, CPDF_Dictionary* pPageDict)
     : CPDF_PageObjectHolder(pDocument, pPageDict, nullptr, nullptr),
       m_PageSize(100, 100),
       m_pPDFDocument(pDocument) {
   ASSERT(pPageDict);
-  if (bPageCache)
-    m_pPageRender = pdfium::MakeUnique<CPDF_PageRenderCache>(this);
 
   // Cannot initialize |m_pResources| and |m_pPageResources| via the
   // CPDF_PageObjectHolder ctor because GetPageAttr() requires
@@ -79,11 +73,6 @@
   ContinueParse(nullptr);
 }
 
-void CPDF_Page::SetRenderContext(
-    std::unique_ptr<CPDF_PageRenderContext> pContext) {
-  m_pRenderContext = std::move(pContext);
-}
-
 CPDF_Object* CPDF_Page::GetPageAttr(const ByteString& name) const {
   CPDF_Dictionary* pPageDict = GetDict();
   std::set<CPDF_Dictionary*> visited;
diff --git a/core/fpdfapi/page/cpdf_page.h b/core/fpdfapi/page/cpdf_page.h
index 1253227..3f64d94 100644
--- a/core/fpdfapi/page/cpdf_page.h
+++ b/core/fpdfapi/page/cpdf_page.h
@@ -8,6 +8,7 @@
 #define CORE_FPDFAPI_PAGE_CPDF_PAGE_H_
 
 #include <memory>
+#include <utility>
 
 #include "core/fpdfapi/page/cpdf_pageobjectholder.h"
 #include "core/fpdfapi/page/ipdf_page.h"
@@ -19,14 +20,26 @@
 
 class CPDF_Dictionary;
 class CPDF_Document;
+class CPDF_Image;
 class CPDF_Object;
-class CPDF_PageRenderCache;
-class CPDF_PageRenderContext;
 
 class CPDF_Page final : public IPDF_Page, public CPDF_PageObjectHolder {
  public:
   class View {};  // Caller implements as desired, empty here due to layering.
 
+  // Data for the render layer to attach to this page.
+  class RenderContextIface {
+   public:
+    virtual ~RenderContextIface() {}
+  };
+
+  // Cache for the render layer to attach to this page.
+  class RenderCacheIface {
+   public:
+    virtual ~RenderCacheIface() {}
+    virtual void ResetBitmapForImage(const RetainPtr<CPDF_Image>& pImage) = 0;
+  };
+
   template <typename T, typename... Args>
   friend RetainPtr<T> pdfium::MakeRetain(Args&&... args);
 
@@ -52,20 +65,25 @@
   void ParseContent();
   const CFX_SizeF& GetPageSize() const { return m_PageSize; }
   int GetPageRotation() const;
-  CPDF_PageRenderCache* GetRenderCache() const { return m_pPageRender.get(); }
-  CPDF_PageRenderContext* GetRenderContext() const {
+  RenderCacheIface* GetRenderCache() const { return m_pRenderCache.get(); }
+  void SetRenderCache(std::unique_ptr<RenderCacheIface> pCache) {
+    m_pRenderCache = std::move(pCache);
+  }
+
+  RenderContextIface* GetRenderContext() const {
     return m_pRenderContext.get();
   }
-  void SetRenderContext(std::unique_ptr<CPDF_PageRenderContext> pContext);
+  void SetRenderContext(std::unique_ptr<RenderContextIface> pContext) {
+    m_pRenderContext = std::move(pContext);
+  }
+
   CPDF_Document* GetPDFDocument() const { return m_pPDFDocument.Get(); }
   View* GetView() const { return m_pView.Get(); }
   void SetView(View* pView) { m_pView = pView; }
   void UpdateDimensions();
 
  private:
-  CPDF_Page(CPDF_Document* pDocument,
-            CPDF_Dictionary* pPageDict,
-            bool bPageCache);
+  CPDF_Page(CPDF_Document* pDocument, CPDF_Dictionary* pPageDict);
   ~CPDF_Page() override;
 
   CPDF_Object* GetPageAttr(const ByteString& name) const;
@@ -74,8 +92,8 @@
   CFX_SizeF m_PageSize;
   CFX_Matrix m_PageMatrix;
   UnownedPtr<CPDF_Document> m_pPDFDocument;
-  std::unique_ptr<CPDF_PageRenderCache> m_pPageRender;
-  std::unique_ptr<CPDF_PageRenderContext> m_pRenderContext;
+  std::unique_ptr<RenderCacheIface> m_pRenderCache;
+  std::unique_ptr<RenderContextIface> m_pRenderContext;
   UnownedPtr<View> m_pView;
 };
 
diff --git a/core/fpdfapi/render/BUILD.gn b/core/fpdfapi/render/BUILD.gn
index dd9370d..775cde6 100644
--- a/core/fpdfapi/render/BUILD.gn
+++ b/core/fpdfapi/render/BUILD.gn
@@ -26,6 +26,8 @@
     "cpdf_imagerenderer.h",
     "cpdf_pagerendercache.cpp",
     "cpdf_pagerendercache.h",
+    "cpdf_pagerendercontext.cpp",
+    "cpdf_pagerendercontext.h",
     "cpdf_progressiverenderer.cpp",
     "cpdf_progressiverenderer.h",
     "cpdf_rendercontext.cpp",
diff --git a/core/fpdfapi/render/cpdf_pagerendercache.cpp b/core/fpdfapi/render/cpdf_pagerendercache.cpp
index 4d1add1..0814215 100644
--- a/core/fpdfapi/render/cpdf_pagerendercache.cpp
+++ b/core/fpdfapi/render/cpdf_pagerendercache.cpp
@@ -118,7 +118,8 @@
   return false;
 }
 
-void CPDF_PageRenderCache::ResetBitmap(const RetainPtr<CPDF_Image>& pImage) {
+void CPDF_PageRenderCache::ResetBitmapForImage(
+    const RetainPtr<CPDF_Image>& pImage) {
   CPDF_ImageCacheEntry* pEntry;
   CPDF_Stream* pStream = pImage->GetStream();
   const auto it = m_ImageCache.find(pStream);
diff --git a/core/fpdfapi/render/cpdf_pagerendercache.h b/core/fpdfapi/render/cpdf_pagerendercache.h
index 5cfdebb..1fb2a61 100644
--- a/core/fpdfapi/render/cpdf_pagerendercache.h
+++ b/core/fpdfapi/render/cpdf_pagerendercache.h
@@ -10,6 +10,7 @@
 #include <map>
 #include <memory>
 
+#include "core/fpdfapi/page/cpdf_page.h"
 #include "core/fxcrt/fx_system.h"
 #include "core/fxcrt/maybe_owned.h"
 #include "core/fxcrt/retain_ptr.h"
@@ -22,14 +23,16 @@
 class CPDF_Stream;
 class PauseIndicatorIface;
 
-class CPDF_PageRenderCache {
+class CPDF_PageRenderCache : public CPDF_Page::RenderCacheIface {
  public:
   explicit CPDF_PageRenderCache(CPDF_Page* pPage);
-  ~CPDF_PageRenderCache();
+  ~CPDF_PageRenderCache() override;
+
+  // CPDF_Page::RenderCacheIface:
+  void ResetBitmapForImage(const RetainPtr<CPDF_Image>& pImage) override;
 
   void CacheOptimization(int32_t dwLimitCacheSize);
   uint32_t GetTimeCount() const { return m_nTimeCount; }
-  void ResetBitmap(const RetainPtr<CPDF_Image>& pImage);
   CPDF_Page* GetPage() const { return m_pPage.Get(); }
   CPDF_ImageCacheEntry* GetCurImageCacheEntry() const {
     return m_pCurImageCacheEntry.Get();
diff --git a/core/fpdfapi/page/cpdf_pagerendercontext.cpp b/core/fpdfapi/render/cpdf_pagerendercontext.cpp
similarity index 91%
rename from core/fpdfapi/page/cpdf_pagerendercontext.cpp
rename to core/fpdfapi/render/cpdf_pagerendercontext.cpp
index 0b768e6..8dd66c7 100644
--- a/core/fpdfapi/page/cpdf_pagerendercontext.cpp
+++ b/core/fpdfapi/render/cpdf_pagerendercontext.cpp
@@ -4,7 +4,7 @@
 
 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
 
-#include "core/fpdfapi/page/cpdf_pagerendercontext.h"
+#include "core/fpdfapi/render/cpdf_pagerendercontext.h"
 
 #include "core/fpdfapi/page/cpdf_occontext.h"
 #include "core/fpdfapi/render/cpdf_progressiverenderer.h"
diff --git a/core/fpdfapi/page/cpdf_pagerendercontext.h b/core/fpdfapi/render/cpdf_pagerendercontext.h
similarity index 73%
rename from core/fpdfapi/page/cpdf_pagerendercontext.h
rename to core/fpdfapi/render/cpdf_pagerendercontext.h
index f9c89a2..8a5a5eb 100644
--- a/core/fpdfapi/page/cpdf_pagerendercontext.h
+++ b/core/fpdfapi/render/cpdf_pagerendercontext.h
@@ -4,26 +4,29 @@
 
 // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
 
-#ifndef CORE_FPDFAPI_PAGE_CPDF_PAGERENDERCONTEXT_H_
-#define CORE_FPDFAPI_PAGE_CPDF_PAGERENDERCONTEXT_H_
+#ifndef CORE_FPDFAPI_RENDER_CPDF_PAGERENDERCONTEXT_H_
+#define CORE_FPDFAPI_RENDER_CPDF_PAGERENDERCONTEXT_H_
 
 #include <memory>
 
+#include "core/fpdfapi/page/cpdf_page.h"
+
 class CFX_RenderDevice;
 class CPDF_ProgressiveRenderer;
 class CPDF_RenderContext;
 class CPDF_RenderOptions;
 
 // Everything about rendering is put here: for OOM recovery
-class CPDF_PageRenderContext {
+class CPDF_PageRenderContext final : public CPDF_Page::RenderContextIface {
  public:
   // Context merely manages the lifetime for callers.
   class AnnotListIface {
    public:
     virtual ~AnnotListIface() {}
   };
+
   CPDF_PageRenderContext();
-  ~CPDF_PageRenderContext();
+  ~CPDF_PageRenderContext() override;
 
   // Specific destruction order required.
   std::unique_ptr<AnnotListIface> m_pAnnots;
@@ -33,4 +36,4 @@
   std::unique_ptr<CPDF_ProgressiveRenderer> m_pRenderer;
 };
 
-#endif  // CORE_FPDFAPI_PAGE_CPDF_PAGERENDERCONTEXT_H_
+#endif  // CORE_FPDFAPI_RENDER_CPDF_PAGERENDERCONTEXT_H_
diff --git a/core/fpdfapi/render/cpdf_rendercontext.cpp b/core/fpdfapi/render/cpdf_rendercontext.cpp
index aebb9cf..543eb62 100644
--- a/core/fpdfapi/render/cpdf_rendercontext.cpp
+++ b/core/fpdfapi/render/cpdf_rendercontext.cpp
@@ -24,7 +24,8 @@
 CPDF_RenderContext::CPDF_RenderContext(CPDF_Page* pPage)
     : m_pDocument(pPage->GetDocument()),
       m_pPageResources(pPage->m_pPageResources.Get()),
-      m_pPageCache(pPage->GetRenderCache()) {}
+      m_pPageCache(
+          static_cast<CPDF_PageRenderCache*>(pPage->GetRenderCache())) {}
 
 CPDF_RenderContext::CPDF_RenderContext(CPDF_Document* pDoc,
                                        CPDF_PageRenderCache* pPageCache)
diff --git a/core/fpdfdoc/cpdf_annotlist.h b/core/fpdfdoc/cpdf_annotlist.h
index 204d29b..85075cf 100644
--- a/core/fpdfdoc/cpdf_annotlist.h
+++ b/core/fpdfdoc/cpdf_annotlist.h
@@ -10,7 +10,7 @@
 #include <memory>
 #include <vector>
 
-#include "core/fpdfapi/page/cpdf_pagerendercontext.h"
+#include "core/fpdfapi/render/cpdf_pagerendercontext.h"
 #include "core/fxcrt/fx_coordinates.h"
 #include "core/fxcrt/fx_system.h"
 #include "core/fxcrt/unowned_ptr.h"
diff --git a/fpdfsdk/fpdf_editpage.cpp b/fpdfsdk/fpdf_editpage.cpp
index c9124dc..eaa88d9 100644
--- a/fpdfsdk/fpdf_editpage.cpp
+++ b/fpdfsdk/fpdf_editpage.cpp
@@ -28,6 +28,7 @@
 #include "core/fpdfapi/parser/cpdf_number.h"
 #include "core/fpdfapi/parser/cpdf_string.h"
 #include "core/fpdfapi/render/cpdf_docrenderdata.h"
+#include "core/fpdfapi/render/cpdf_pagerendercache.h"
 #include "core/fpdfdoc/cpdf_annot.h"
 #include "core/fpdfdoc/cpdf_annotlist.h"
 #include "core/fxcrt/fx_extension.h"
@@ -228,8 +229,10 @@
   }
 #endif  // PDF_ENABLE_XFA
 
-  auto pPage = pdfium::MakeRetain<CPDF_Page>(pDoc, pPageDict, true);
+  auto pPage = pdfium::MakeRetain<CPDF_Page>(pDoc, pPageDict);
+  pPage->SetRenderCache(pdfium::MakeUnique<CPDF_PageRenderCache>(pPage.Get()));
   pPage->ParseContent();
+
   return FPDFPageFromIPDFPage(pPage.Leak());  // Caller takes ownership.
 }
 
diff --git a/fpdfsdk/fpdf_flatten.cpp b/fpdfsdk/fpdf_flatten.cpp
index d1a6db7..fad2be3 100644
--- a/fpdfsdk/fpdf_flatten.cpp
+++ b/fpdfsdk/fpdf_flatten.cpp
@@ -51,7 +51,7 @@
 void GetContentsRect(CPDF_Document* pDoc,
                      CPDF_Dictionary* pDict,
                      std::vector<CFX_FloatRect>* pRectArray) {
-  auto pPDFPage = pdfium::MakeRetain<CPDF_Page>(pDoc, pDict, false);
+  auto pPDFPage = pdfium::MakeRetain<CPDF_Page>(pDoc, pDict);
   pPDFPage->ParseContent();
 
   for (const auto& pPageObject : *pPDFPage) {
diff --git a/fpdfsdk/fpdf_ppo.cpp b/fpdfsdk/fpdf_ppo.cpp
index e8261a2..13ef81d 100644
--- a/fpdfsdk/fpdf_ppo.cpp
+++ b/fpdfsdk/fpdf_ppo.cpp
@@ -25,6 +25,7 @@
 #include "core/fpdfapi/parser/cpdf_stream.h"
 #include "core/fpdfapi/parser/cpdf_stream_acc.h"
 #include "core/fpdfapi/parser/cpdf_string.h"
+#include "core/fpdfapi/render/cpdf_pagerendercache.h"
 #include "core/fxcrt/fx_safe_types.h"
 #include "core/fxcrt/retain_ptr.h"
 #include "core/fxcrt/unowned_ptr.h"
@@ -619,9 +620,11 @@
       if (!pSrcPageDict)
         return false;
 
-      auto srcPage = pdfium::MakeRetain<CPDF_Page>(src(), pSrcPageDict, true);
+      auto pSrcPage = pdfium::MakeRetain<CPDF_Page>(src(), pSrcPageDict);
+      pSrcPage->SetRenderCache(
+          pdfium::MakeUnique<CPDF_PageRenderCache>(pSrcPage.Get()));
       NupPageSettings settings =
-          nupState.CalculateNewPagePosition(srcPage->GetPageSize());
+          nupState.CalculateNewPagePosition(pSrcPage->GetPageSize());
       bsContent += AddSubPage(pSrcPageDict, settings);
     }
 
diff --git a/fpdfsdk/fpdf_progressive.cpp b/fpdfsdk/fpdf_progressive.cpp
index 6bf9f37..c151e7c 100644
--- a/fpdfsdk/fpdf_progressive.cpp
+++ b/fpdfsdk/fpdf_progressive.cpp
@@ -9,7 +9,7 @@
 #include <utility>
 
 #include "core/fpdfapi/page/cpdf_page.h"
-#include "core/fpdfapi/page/cpdf_pagerendercontext.h"
+#include "core/fpdfapi/render/cpdf_pagerendercontext.h"
 #include "core/fpdfapi/render/cpdf_progressiverenderer.h"
 #include "core/fxge/cfx_defaultrenderdevice.h"
 #include "core/fxge/cfx_renderdevice.h"
@@ -79,7 +79,8 @@
   if (!pPage)
     return FPDF_RENDER_FAILED;
 
-  CPDF_PageRenderContext* pContext = pPage->GetRenderContext();
+  auto* pContext =
+      static_cast<CPDF_PageRenderContext*>(pPage->GetRenderContext());
   if (pContext && pContext->m_pRenderer) {
     IPDFSDK_PauseAdapter IPauseAdapter(pause);
     pContext->m_pRenderer->Continue(&IPauseAdapter);
@@ -98,7 +99,8 @@
   CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
   if (pPage) {
 #ifdef _SKIA_SUPPORT_PATHS_
-    CPDF_PageRenderContext* pContext = pPage->GetRenderContext();
+    auto* pContext =
+        static_cast<CPDF_PageRenderContext*>(pPage->GetRenderContext());
     if (pContext && pContext->m_pRenderer) {
       CFX_RenderDevice* pDevice = pContext->m_pDevice.get();
       pDevice->Flush(true);
diff --git a/fpdfsdk/fpdf_view.cpp b/fpdfsdk/fpdf_view.cpp
index e695152..10a8467 100644
--- a/fpdfsdk/fpdf_view.cpp
+++ b/fpdfsdk/fpdf_view.cpp
@@ -15,7 +15,6 @@
 #include "core/fpdfapi/page/cpdf_docpagedata.h"
 #include "core/fpdfapi/page/cpdf_occontext.h"
 #include "core/fpdfapi/page/cpdf_page.h"
-#include "core/fpdfapi/page/cpdf_pagerendercontext.h"
 #include "core/fpdfapi/parser/cpdf_array.h"
 #include "core/fpdfapi/parser/cpdf_dictionary.h"
 #include "core/fpdfapi/parser/cpdf_document.h"
@@ -23,6 +22,8 @@
 #include "core/fpdfapi/parser/cpdf_parser.h"
 #include "core/fpdfapi/parser/fpdf_parser_decode.h"
 #include "core/fpdfapi/render/cpdf_docrenderdata.h"
+#include "core/fpdfapi/render/cpdf_pagerendercache.h"
+#include "core/fpdfapi/render/cpdf_pagerendercontext.h"
 #include "core/fpdfapi/render/cpdf_progressiverenderer.h"
 #include "core/fpdfapi/render/cpdf_rendercontext.h"
 #include "core/fpdfapi/render/cpdf_renderoptions.h"
@@ -356,7 +357,8 @@
   if (!pDict)
     return nullptr;
 
-  auto pPage = pdfium::MakeRetain<CPDF_Page>(pDoc, pDict, true);
+  auto pPage = pdfium::MakeRetain<CPDF_Page>(pDoc, pDict);
+  pPage->SetRenderCache(pdfium::MakeUnique<CPDF_PageRenderCache>(pPage.Get()));
   pPage->ParseContent();
   return FPDFPageFromIPDFPage(pPage.Leak());
 }
@@ -530,8 +532,10 @@
   CPDF_Page* pPage = CPDFPageFromFPDFPage(page);
   if (!pPage)
     return;
-  pPage->SetRenderContext(pdfium::MakeUnique<CPDF_PageRenderContext>());
-  CPDF_PageRenderContext* pContext = pPage->GetRenderContext();
+
+  auto pOwnedContext = pdfium::MakeUnique<CPDF_PageRenderContext>();
+  CPDF_PageRenderContext* pContext = pOwnedContext.get();
+  pPage->SetRenderContext(std::move(pOwnedContext));
 
   RetainPtr<CFX_DIBitmap> pBitmap;
   // Don't render the full page to bitmap for a mask unless there are a lot
@@ -585,8 +589,9 @@
 
     // Begin rendering to the printer. Add flag to indicate the renderer should
     // pause after each image mask.
-    pPage->SetRenderContext(pdfium::MakeUnique<CPDF_PageRenderContext>());
-    pContext = pPage->GetRenderContext();
+    pOwnedContext = pdfium::MakeUnique<CPDF_PageRenderContext>();
+    pContext = pOwnedContext.get();
+    pPage->SetRenderContext(std::move(pOwnedContext));
     pContext->m_pDevice =
         pdfium::MakeUnique<CFX_WindowsRenderDevice>(dc, &kEncoderIface);
     pContext->m_pOptions = pdfium::MakeUnique<CPDF_RenderOptions>();
@@ -953,7 +958,8 @@
   if (!pDict)
     return false;
 
-  auto page = pdfium::MakeRetain<CPDF_Page>(pDoc, pDict, true);
+  auto page = pdfium::MakeRetain<CPDF_Page>(pDoc, pDict);
+  page->SetRenderCache(pdfium::MakeUnique<CPDF_PageRenderCache>(page.Get()));
   *width = page->GetPageWidth();
   *height = page->GetPageHeight();
   return true;
diff --git a/fpdfsdk/fpdfxfa/BUILD.gn b/fpdfsdk/fpdfxfa/BUILD.gn
index 231ac96..a3025a6 100644
--- a/fpdfsdk/fpdfxfa/BUILD.gn
+++ b/fpdfsdk/fpdfxfa/BUILD.gn
@@ -23,6 +23,7 @@
     "../../:pdfium_public_headers",
     "../../core/fpdfapi/page",
     "../../core/fpdfapi/parser",
+    "../../core/fpdfapi/render",
     "../../core/fxcrt",
     "../../fxjs",
     "../../xfa/fgas",
diff --git a/fpdfsdk/fpdfxfa/cpdfxfa_page.cpp b/fpdfsdk/fpdfxfa/cpdfxfa_page.cpp
index d5fd665..c0f383c 100644
--- a/fpdfsdk/fpdfxfa/cpdfxfa_page.cpp
+++ b/fpdfsdk/fpdfxfa/cpdfxfa_page.cpp
@@ -8,6 +8,7 @@
 
 #include "core/fpdfapi/page/cpdf_page.h"
 #include "core/fpdfapi/parser/cpdf_document.h"
+#include "core/fpdfapi/render/cpdf_pagerendercache.h"
 #include "fpdfsdk/fpdfxfa/cpdfxfa_context.h"
 #include "fpdfsdk/fpdfxfa/cxfa_fwladaptertimermgr.h"
 #include "public/fpdf_formfill.h"
@@ -41,10 +42,9 @@
   if (!pDict)
     return false;
 
-  if (!m_pPDFPage || m_pPDFPage->GetDict() != pDict) {
-    m_pPDFPage = pdfium::MakeRetain<CPDF_Page>(pPDFDoc, pDict, true);
-    m_pPDFPage->ParseContent();
-  }
+  if (!m_pPDFPage || m_pPDFPage->GetDict() != pDict)
+    LoadPDFPageFromDict(pDict);
+
   return true;
 }
 
@@ -68,7 +68,9 @@
 
 void CPDFXFA_Page::LoadPDFPageFromDict(CPDF_Dictionary* pPageDict) {
   ASSERT(pPageDict);
-  m_pPDFPage = pdfium::MakeRetain<CPDF_Page>(GetDocument(), pPageDict, true);
+  m_pPDFPage = pdfium::MakeRetain<CPDF_Page>(GetDocument(), pPageDict);
+  m_pPDFPage->SetRenderCache(
+      pdfium::MakeUnique<CPDF_PageRenderCache>(m_pPDFPage.Get()));
   m_pPDFPage->ParseContent();
 }
 
diff --git a/fxjs/BUILD.gn b/fxjs/BUILD.gn
index aad637a..8d2e7b8 100644
--- a/fxjs/BUILD.gn
+++ b/fxjs/BUILD.gn
@@ -107,6 +107,7 @@
       "../core/fpdfapi/font",
       "../core/fpdfapi/page",
       "../core/fpdfapi/parser",
+      "../core/fpdfapi/render",
       "../core/fpdfdoc",
       "../core/fxge",
       "//v8",
diff --git a/fxjs/cjs_document.cpp b/fxjs/cjs_document.cpp
index cd9beeb..a9a9368 100644
--- a/fxjs/cjs_document.cpp
+++ b/fxjs/cjs_document.cpp
@@ -15,6 +15,7 @@
 #include "core/fpdfapi/parser/cpdf_dictionary.h"
 #include "core/fpdfapi/parser/cpdf_name.h"
 #include "core/fpdfapi/parser/cpdf_string.h"
+#include "core/fpdfapi/render/cpdf_pagerendercache.h"
 #include "core/fpdfdoc/cpdf_interactiveform.h"
 #include "core/fpdfdoc/cpdf_nametree.h"
 #include "fpdfsdk/cpdfsdk_annotiteration.h"
@@ -1309,7 +1310,8 @@
   if (!pPageDict)
     return CJS_Result::Failure(JSMessage::kBadObjectError);
 
-  auto page = pdfium::MakeRetain<CPDF_Page>(pDocument, pPageDict, true);
+  auto page = pdfium::MakeRetain<CPDF_Page>(pDocument, pPageDict);
+  page->SetRenderCache(pdfium::MakeUnique<CPDF_PageRenderCache>(page.Get()));
   page->ParseContent();
 
   int nWords = 0;
@@ -1358,7 +1360,8 @@
   if (!pPageDict)
     return CJS_Result::Failure(JSMessage::kBadObjectError);
 
-  auto page = pdfium::MakeRetain<CPDF_Page>(pDocument, pPageDict, true);
+  auto page = pdfium::MakeRetain<CPDF_Page>(pDocument, pPageDict);
+  page->SetRenderCache(pdfium::MakeUnique<CPDF_PageRenderCache>(page.Get()));
   page->ParseContent();
 
   int nWords = 0;