Clean up CPDF_Page.

- Merge CPDF_Page::Load() into ctor.
- Remove always nullptr param for CPDF_Page::ParseContent().
- Remove unneeded indirection in IPDF_RenderModule.
- Delete CPDF_ParseOptions.
- Fix up CPDF_Pattern.

Review URL: https://codereview.chromium.org/1918113002
diff --git a/BUILD.gn b/BUILD.gn
index a088c76..0a7c3b2 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -365,8 +365,6 @@
     "core/fpdfapi/fpdf_page/cpdf_pageobjectholder.cpp",
     "core/fpdfapi/fpdf_page/cpdf_pageobjectlist.cpp",
     "core/fpdfapi/fpdf_page/cpdf_pageobjectlist.h",
-    "core/fpdfapi/fpdf_page/cpdf_parseoptions.cpp",
-    "core/fpdfapi/fpdf_page/cpdf_parseoptions.h",
     "core/fpdfapi/fpdf_page/cpdf_pathobject.cpp",
     "core/fpdfapi/fpdf_page/cpdf_pattern.cpp",
     "core/fpdfapi/fpdf_page/cpdf_pattern.h",
diff --git a/core/fpdfapi/fpdf_edit/fpdf_edit_doc.cpp b/core/fpdfapi/fpdf_edit/fpdf_edit_doc.cpp
index ceca67c..addf9e2 100644
--- a/core/fpdfapi/fpdf_edit/fpdf_edit_doc.cpp
+++ b/core/fpdfapi/fpdf_edit/fpdf_edit_doc.cpp
@@ -1119,14 +1119,3 @@
 
   m_PageList.RemoveAt(iPage);
 }
-
-void FPDFAPI_FlatPageAttr(CPDF_Dictionary* pPageDict,
-                          const CFX_ByteStringC& name) {
-  if (pPageDict->KeyExist(name)) {
-    return;
-  }
-  CPDF_Object* pObj = FPDFAPI_GetPageAttr(pPageDict, name);
-  if (pObj) {
-    pPageDict->SetAt(name, pObj->Clone());
-  }
-}
diff --git a/core/fpdfapi/fpdf_font/cpdf_type3font.cpp b/core/fpdfapi/fpdf_font/cpdf_type3font.cpp
index 40fb54f..be28094 100644
--- a/core/fpdfapi/fpdf_font/cpdf_type3font.cpp
+++ b/core/fpdfapi/fpdf_font/cpdf_type3font.cpp
@@ -113,8 +113,7 @@
   // This can trigger recursion into this method. The content of |m_CacheMap|
   // can change as a result. Thus after it returns, check the cache again for
   // a cache hit.
-  pNewChar->m_pForm->ParseContent(nullptr, nullptr, pNewChar.get(), nullptr,
-                                  level + 1);
+  pNewChar->m_pForm->ParseContent(nullptr, nullptr, pNewChar.get(), level + 1);
   it = m_CacheMap.find(charcode);
   if (it != m_CacheMap.end())
     return it->second;
diff --git a/core/fpdfapi/fpdf_page/cpdf_color.cpp b/core/fpdfapi/fpdf_page/cpdf_color.cpp
index d174660..5536f71 100644
--- a/core/fpdfapi/fpdf_page/cpdf_color.cpp
+++ b/core/fpdfapi/fpdf_page/cpdf_color.cpp
@@ -37,10 +37,10 @@
     PatternValue* pvalue = (PatternValue*)m_pBuffer;
     CPDF_Pattern* pPattern =
         pvalue->m_pCountedPattern ? pvalue->m_pCountedPattern->get() : nullptr;
-    if (pPattern && pPattern->m_pDocument) {
-      CPDF_DocPageData* pPageData = pPattern->m_pDocument->GetPageData();
+    if (pPattern && pPattern->document()) {
+      CPDF_DocPageData* pPageData = pPattern->document()->GetPageData();
       if (pPageData)
-        pPageData->ReleasePattern(pPattern->m_pPatternObj);
+        pPageData->ReleasePattern(pPattern->pattern_obj());
     }
   }
   FX_Free(m_pBuffer);
@@ -92,10 +92,10 @@
 
   CPDF_DocPageData* pDocPageData = nullptr;
   PatternValue* pvalue = (PatternValue*)m_pBuffer;
-  if (pvalue->m_pPattern && pvalue->m_pPattern->m_pDocument) {
-    pDocPageData = pvalue->m_pPattern->m_pDocument->GetPageData();
+  if (pvalue->m_pPattern && pvalue->m_pPattern->document()) {
+    pDocPageData = pvalue->m_pPattern->document()->GetPageData();
     if (pDocPageData)
-      pDocPageData->ReleasePattern(pvalue->m_pPattern->m_pPatternObj);
+      pDocPageData->ReleasePattern(pvalue->m_pPattern->pattern_obj());
   }
   pvalue->m_nComps = ncomps;
   pvalue->m_pPattern = pPattern;
@@ -103,12 +103,12 @@
     FXSYS_memcpy(pvalue->m_Comps, comps, ncomps * sizeof(FX_FLOAT));
 
   pvalue->m_pCountedPattern = nullptr;
-  if (pPattern && pPattern->m_pDocument) {
+  if (pPattern && pPattern->document()) {
     if (!pDocPageData)
-      pDocPageData = pPattern->m_pDocument->GetPageData();
+      pDocPageData = pPattern->document()->GetPageData();
 
     pvalue->m_pCountedPattern =
-        pDocPageData->FindPatternPtr(pPattern->m_pPatternObj);
+        pDocPageData->FindPatternPtr(pPattern->pattern_obj());
   }
 }
 
@@ -127,14 +127,14 @@
 
   m_pBuffer = m_pCS->CreateBuf();
   FXSYS_memcpy(m_pBuffer, pSrc->m_pBuffer, m_pCS->GetBufSize());
-  if (m_pCS->GetFamily() == PDFCS_PATTERN) {
-    PatternValue* pvalue = (PatternValue*)m_pBuffer;
-    if (pvalue->m_pPattern && pvalue->m_pPattern->m_pDocument) {
-      pvalue->m_pPattern =
-          pvalue->m_pPattern->m_pDocument->GetPageData()->GetPattern(
-              pvalue->m_pPattern->m_pPatternObj, FALSE,
-              &pvalue->m_pPattern->m_ParentMatrix);
-    }
+  if (m_pCS->GetFamily() != PDFCS_PATTERN)
+    return;
+
+  PatternValue* pValue = reinterpret_cast<PatternValue*>(m_pBuffer);
+  CPDF_Pattern* pPattern = pValue->m_pPattern;
+  if (pPattern && pPattern->document()) {
+    pValue->m_pPattern = pPattern->document()->GetPageData()->GetPattern(
+        pPattern->pattern_obj(), FALSE, pPattern->parent_matrix());
   }
 }
 
diff --git a/core/fpdfapi/fpdf_page/cpdf_colorstate.cpp b/core/fpdfapi/fpdf_page/cpdf_colorstate.cpp
index 580b58a..88e9f56 100644
--- a/core/fpdfapi/fpdf_page/cpdf_colorstate.cpp
+++ b/core/fpdfapi/fpdf_page/cpdf_colorstate.cpp
@@ -49,10 +49,11 @@
   pData->m_FillColor.SetValue(pPattern, pValue, nValues);
   int R, G, B;
   FX_BOOL ret = pData->m_FillColor.GetRGB(R, G, B);
-  if (pPattern->m_PatternType == 1 &&
-      ((CPDF_TilingPattern*)pPattern)->m_bColored && !ret) {
-    pData->m_FillRGB = 0x00BFBFBF;
-    return;
+  if (CPDF_TilingPattern* pTilingPattern = pPattern->AsTilingPattern()) {
+    if (!ret && pTilingPattern->colored()) {
+      pData->m_FillRGB = 0x00BFBFBF;
+      return;
+    }
   }
   pData->m_FillRGB = ret ? FXSYS_RGB(R, G, B) : (uint32_t)-1;
 }
@@ -64,10 +65,11 @@
   pData->m_StrokeColor.SetValue(pPattern, pValue, nValues);
   int R, G, B;
   FX_BOOL ret = pData->m_StrokeColor.GetRGB(R, G, B);
-  if (pPattern->m_PatternType == 1 &&
-      ((CPDF_TilingPattern*)pPattern)->m_bColored && !ret) {
-    pData->m_StrokeRGB = 0x00BFBFBF;
-    return;
+  if (CPDF_TilingPattern* pTilingPattern = pPattern->AsTilingPattern()) {
+    if (!ret && pTilingPattern->colored()) {
+      pData->m_StrokeRGB = 0x00BFBFBF;
+      return;
+    }
   }
   pData->m_StrokeRGB =
       pData->m_StrokeColor.GetRGB(R, G, B) ? FXSYS_RGB(R, G, B) : (uint32_t)-1;
diff --git a/core/fpdfapi/fpdf_page/cpdf_form.cpp b/core/fpdfapi/fpdf_page/cpdf_form.cpp
index 403baa2..54698c6 100644
--- a/core/fpdfapi/fpdf_page/cpdf_form.cpp
+++ b/core/fpdfapi/fpdf_page/cpdf_form.cpp
@@ -36,23 +36,20 @@
 void CPDF_Form::StartParse(CPDF_AllStates* pGraphicStates,
                            CFX_Matrix* pParentMatrix,
                            CPDF_Type3Char* pType3Char,
-                           CPDF_ParseOptions* pOptions,
                            int level) {
   if (m_ParseState == CONTENT_PARSED || m_ParseState == CONTENT_PARSING) {
     return;
   }
   m_pParser.reset(new CPDF_ContentParser);
-  m_pParser->Start(this, pGraphicStates, pParentMatrix, pType3Char, pOptions,
-                   level);
+  m_pParser->Start(this, pGraphicStates, pParentMatrix, pType3Char, level);
   m_ParseState = CONTENT_PARSING;
 }
 
 void CPDF_Form::ParseContent(CPDF_AllStates* pGraphicStates,
                              CFX_Matrix* pParentMatrix,
                              CPDF_Type3Char* pType3Char,
-                             CPDF_ParseOptions* pOptions,
                              int level) {
-  StartParse(pGraphicStates, pParentMatrix, pType3Char, pOptions, level);
+  StartParse(pGraphicStates, pParentMatrix, pType3Char, level);
   ContinueParse(NULL);
 }
 
diff --git a/core/fpdfapi/fpdf_page/cpdf_page.cpp b/core/fpdfapi/fpdf_page/cpdf_page.cpp
index dd298f3..6b0609f 100644
--- a/core/fpdfapi/fpdf_page/cpdf_page.cpp
+++ b/core/fpdfapi/fpdf_page/cpdf_page.cpp
@@ -6,95 +6,59 @@
 
 #include "core/fpdfapi/fpdf_page/include/cpdf_page.h"
 
+#include <set>
+
 #include "core/fpdfapi/fpdf_page/include/cpdf_pageobject.h"
 #include "core/fpdfapi/fpdf_page/pageint.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_array.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_dictionary.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_object.h"
-#include "core/fpdfapi/include/cpdf_modulemgr.h"
-#include "core/fpdfapi/ipdf_rendermodule.h"
+#include "core/fpdfapi/fpdf_render/cpdf_pagerendercache.h"
+#include "third_party/base/stl_util.h"
 
-CPDF_Object* FPDFAPI_GetPageAttr(CPDF_Dictionary* pPageDict,
-                                 const CFX_ByteStringC& name) {
-  int level = 0;
-  while (1) {
-    CPDF_Object* pObj = pPageDict->GetDirectObjectBy(name);
-    if (pObj) {
-      return pObj;
-    }
-    CPDF_Dictionary* pParent = pPageDict->GetDictBy("Parent");
-    if (!pParent || pParent == pPageDict) {
-      return NULL;
-    }
-    pPageDict = pParent;
-    level++;
-    if (level == 1000) {
-      return NULL;
-    }
-  }
-}
-
-CPDF_Page::CPDF_Page() : m_pPageRender(nullptr) {}
-
-CPDF_Page::~CPDF_Page() {
-  if (m_pPageRender) {
-    IPDF_RenderModule* pModule = CPDF_ModuleMgr::Get()->GetRenderModule();
-    pModule->DestroyPageCache(m_pPageRender);
-  }
-}
-
-void CPDF_Page::Load(CPDF_Document* pDocument,
+CPDF_Page::CPDF_Page(CPDF_Document* pDocument,
                      CPDF_Dictionary* pPageDict,
-                     FX_BOOL bPageCache) {
-  m_pDocument = (CPDF_Document*)pDocument;
+                     bool bPageCache)
+    : m_PageWidth(100),
+      m_PageHeight(100),
+      m_pPageRender(bPageCache ? new CPDF_PageRenderCache(this) : nullptr) {
   m_pFormDict = pPageDict;
-  if (bPageCache) {
-    m_pPageRender =
-        CPDF_ModuleMgr::Get()->GetRenderModule()->CreatePageCache(this);
-  }
-  if (!pPageDict) {
-    m_PageWidth = m_PageHeight = 100 * 1.0f;
-    m_pPageResources = m_pResources = NULL;
+  m_pDocument = pDocument;
+  if (!pPageDict)
     return;
-  }
+
   CPDF_Object* pageAttr = GetPageAttr("Resources");
-  m_pResources = pageAttr ? pageAttr->GetDict() : NULL;
+  m_pResources = pageAttr ? pageAttr->GetDict() : nullptr;
   m_pPageResources = m_pResources;
   CPDF_Object* pRotate = GetPageAttr("Rotate");
-  int rotate = 0;
-  if (pRotate) {
-    rotate = pRotate->GetInteger() / 90 % 4;
-  }
-  if (rotate < 0) {
+  int rotate = pRotate ? pRotate->GetInteger() / 90 % 4 : 0;
+  if (rotate < 0)
     rotate += 4;
-  }
+
   CPDF_Array* pMediaBox = ToArray(GetPageAttr("MediaBox"));
   CFX_FloatRect mediabox;
   if (pMediaBox) {
     mediabox = pMediaBox->GetRect();
     mediabox.Normalize();
   }
-  if (mediabox.IsEmpty()) {
+  if (mediabox.IsEmpty())
     mediabox = CFX_FloatRect(0, 0, 612, 792);
-  }
 
   CPDF_Array* pCropBox = ToArray(GetPageAttr("CropBox"));
   if (pCropBox) {
     m_BBox = pCropBox->GetRect();
     m_BBox.Normalize();
   }
-  if (m_BBox.IsEmpty()) {
+  if (m_BBox.IsEmpty())
     m_BBox = mediabox;
-  } else {
+  else
     m_BBox.Intersect(mediabox);
-  }
-  if (rotate % 2) {
-    m_PageHeight = m_BBox.right - m_BBox.left;
-    m_PageWidth = m_BBox.top - m_BBox.bottom;
-  } else {
-    m_PageWidth = m_BBox.right - m_BBox.left;
-    m_PageHeight = m_BBox.top - m_BBox.bottom;
-  }
+
+  m_PageWidth = m_BBox.right - m_BBox.left;
+  m_PageHeight = m_BBox.top - m_BBox.bottom;
+  if (rotate % 2)
+    std::swap(m_PageWidth, m_PageHeight);
+
   switch (rotate) {
     case 0:
       m_PageMatrix.Set(1.0f, 0, 0, 1.0f, -m_BBox.left, -m_BBox.bottom);
@@ -109,26 +73,40 @@
       m_PageMatrix.Set(0, 1.0f, -1.0f, 0, m_BBox.top, -m_BBox.left);
       break;
   }
+
   m_Transparency = PDFTRANS_ISOLATED;
   LoadTransInfo();
 }
 
-void CPDF_Page::StartParse(CPDF_ParseOptions* pOptions) {
-  if (m_ParseState == CONTENT_PARSED || m_ParseState == CONTENT_PARSING) {
+CPDF_Page::~CPDF_Page() {}
+
+void CPDF_Page::StartParse() {
+  if (m_ParseState == CONTENT_PARSED || m_ParseState == CONTENT_PARSING)
     return;
-  }
+
   m_pParser.reset(new CPDF_ContentParser);
-  m_pParser->Start(this, pOptions);
+  m_pParser->Start(this);
   m_ParseState = CONTENT_PARSING;
 }
 
-void CPDF_Page::ParseContent(CPDF_ParseOptions* pOptions) {
-  StartParse(pOptions);
+void CPDF_Page::ParseContent() {
+  StartParse();
   ContinueParse(nullptr);
 }
 
-CPDF_Object* CPDF_Page::GetPageAttr(const CFX_ByteStringC& name) const {
-  return FPDFAPI_GetPageAttr(m_pFormDict, name);
+CPDF_Object* CPDF_Page::GetPageAttr(const CFX_ByteString& name) const {
+  CPDF_Dictionary* pPageDict = m_pFormDict;
+  std::set<CPDF_Dictionary*> visited;
+  while (1) {
+    visited.insert(pPageDict);
+    if (CPDF_Object* pObj = pPageDict->GetDirectObjectBy(name))
+      return pObj;
+
+    pPageDict = pPageDict->GetDictBy("Parent");
+    if (!pPageDict || pdfium::ContainsKey(visited, pPageDict))
+      break;
+  }
+  return nullptr;
 }
 
 void CPDF_Page::GetDisplayMatrix(CFX_Matrix& matrix,
diff --git a/core/fpdfapi/fpdf_page/cpdf_parseoptions.cpp b/core/fpdfapi/fpdf_page/cpdf_parseoptions.cpp
deleted file mode 100644
index d22b6f1..0000000
--- a/core/fpdfapi/fpdf_page/cpdf_parseoptions.cpp
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright 2016 PDFium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
-#include "core/fpdfapi/fpdf_page/cpdf_parseoptions.h"
-
-CPDF_ParseOptions::CPDF_ParseOptions()
-    : m_bTextOnly(FALSE),
-      m_bMarkedContent(TRUE),
-      m_bSeparateForm(TRUE),
-      m_bDecodeInlineImage(FALSE) {}
diff --git a/core/fpdfapi/fpdf_page/cpdf_parseoptions.h b/core/fpdfapi/fpdf_page/cpdf_parseoptions.h
deleted file mode 100644
index 3d091ab..0000000
--- a/core/fpdfapi/fpdf_page/cpdf_parseoptions.h
+++ /dev/null
@@ -1,22 +0,0 @@
-// Copyright 2016 PDFium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
-
-#ifndef CORE_FPDFAPI_FPDF_PAGE_CPDF_PARSEOPTIONS_H_
-#define CORE_FPDFAPI_FPDF_PAGE_CPDF_PARSEOPTIONS_H_
-
-#include "core/fxcrt/include/fx_system.h"
-
-class CPDF_ParseOptions {
- public:
-  CPDF_ParseOptions();
-
-  FX_BOOL m_bTextOnly;
-  FX_BOOL m_bMarkedContent;
-  FX_BOOL m_bSeparateForm;
-  FX_BOOL m_bDecodeInlineImage;
-};
-
-#endif  // CORE_FPDFAPI_FPDF_PAGE_CPDF_PARSEOPTIONS_H_
diff --git a/core/fpdfapi/fpdf_page/cpdf_pattern.cpp b/core/fpdfapi/fpdf_page/cpdf_pattern.cpp
index fc9d10e..838f4af 100644
--- a/core/fpdfapi/fpdf_page/cpdf_pattern.cpp
+++ b/core/fpdfapi/fpdf_page/cpdf_pattern.cpp
@@ -10,10 +10,7 @@
                            CPDF_Document* pDoc,
                            CPDF_Object* pObj,
                            const CFX_Matrix* pParentMatrix)
-    : m_PatternType(type),
-      m_pDocument(pDoc),
-      m_pPatternObj(pObj),
-      m_bForceClear(FALSE) {
+    : m_PatternType(type), m_pDocument(pDoc), m_pPatternObj(pObj) {
   if (pParentMatrix)
     m_ParentMatrix = *pParentMatrix;
 }
diff --git a/core/fpdfapi/fpdf_page/cpdf_pattern.h b/core/fpdfapi/fpdf_page/cpdf_pattern.h
index 7f9a33b..d6ef49c 100644
--- a/core/fpdfapi/fpdf_page/cpdf_pattern.h
+++ b/core/fpdfapi/fpdf_page/cpdf_pattern.h
@@ -12,6 +12,8 @@
 
 class CPDF_Document;
 class CPDF_Object;
+class CPDF_ShadingPattern;
+class CPDF_TilingPattern;
 
 class CPDF_Pattern {
  public:
@@ -19,13 +21,13 @@
 
   virtual ~CPDF_Pattern();
 
-  void SetForceClear(FX_BOOL bForceClear) { m_bForceClear = bForceClear; }
+  virtual CPDF_TilingPattern* AsTilingPattern() = 0;
+  virtual CPDF_ShadingPattern* AsShadingPattern() = 0;
 
-  const PatternType m_PatternType;
-  CPDF_Document* const m_pDocument;
-  CPDF_Object* const m_pPatternObj;
-  CFX_Matrix m_Pattern2Form;
-  CFX_Matrix m_ParentMatrix;
+  CPDF_Document* document() { return m_pDocument; }
+  CPDF_Object* pattern_obj() { return m_pPatternObj; }
+  CFX_Matrix* pattern_to_form() { return &m_Pattern2Form; }
+  CFX_Matrix* parent_matrix() { return &m_ParentMatrix; }
 
  protected:
   CPDF_Pattern(PatternType type,
@@ -33,7 +35,11 @@
                CPDF_Object* pObj,
                const CFX_Matrix* pParentMatrix);
 
-  FX_BOOL m_bForceClear;
+  const PatternType m_PatternType;
+  CPDF_Document* const m_pDocument;
+  CPDF_Object* const m_pPatternObj;
+  CFX_Matrix m_Pattern2Form;
+  CFX_Matrix m_ParentMatrix;
 };
 
 #endif  // CORE_FPDFAPI_FPDF_PAGE_CPDF_PATTERN_H_
diff --git a/core/fpdfapi/fpdf_page/cpdf_shadingobject.cpp b/core/fpdfapi/fpdf_page/cpdf_shadingobject.cpp
index 56dd6d4..0858132 100644
--- a/core/fpdfapi/fpdf_page/cpdf_shadingobject.cpp
+++ b/core/fpdfapi/fpdf_page/cpdf_shadingobject.cpp
@@ -19,12 +19,12 @@
   obj->CopyData(this);
 
   obj->m_pShading = m_pShading;
-  if (obj->m_pShading && obj->m_pShading->m_pDocument) {
-    CPDF_DocPageData* pDocPageData =
-        obj->m_pShading->m_pDocument->GetPageData();
-    obj->m_pShading = (CPDF_ShadingPattern*)pDocPageData->GetPattern(
+  if (obj->m_pShading && obj->m_pShading->document()) {
+    CPDF_DocPageData* pDocPageData = obj->m_pShading->document()->GetPageData();
+    CPDF_Pattern* pattern = pDocPageData->GetPattern(
         obj->m_pShading->m_pShadingObj, m_pShading->m_bShadingObj,
-        &obj->m_pShading->m_ParentMatrix);
+        obj->m_pShading->parent_matrix());
+    obj->m_pShading = pattern ? pattern->AsShadingPattern() : nullptr;
   }
   obj->m_Matrix = m_Matrix;
   return obj;
diff --git a/core/fpdfapi/fpdf_page/cpdf_shadingpattern.h b/core/fpdfapi/fpdf_page/cpdf_shadingpattern.h
index c9bbd07..7e5a24d 100644
--- a/core/fpdfapi/fpdf_page/cpdf_shadingpattern.h
+++ b/core/fpdfapi/fpdf_page/cpdf_shadingpattern.h
@@ -12,7 +12,7 @@
 #include "core/fpdfapi/fpdf_page/pageint.h"
 #include "core/fxcrt/include/fx_system.h"
 
-typedef enum {
+enum ShadingType {
   kInvalidShading = 0,
   kFunctionBasedShading = 1,
   kAxialShading = 2,
@@ -22,7 +22,7 @@
   kCoonsPatchMeshShading = 6,
   kTensorProductPatchMeshShading = 7,
   kMaxShading = 8
-} ShadingType;
+};
 
 class CFX_Matrix;
 class CPDF_ColorSpace;
@@ -38,6 +38,9 @@
 
   ~CPDF_ShadingPattern() override;
 
+  CPDF_TilingPattern* AsTilingPattern() override { return nullptr; }
+  CPDF_ShadingPattern* AsShadingPattern() override { return this; }
+
   bool IsMeshShading() const {
     return m_ShadingType == kFreeFormGouraudTriangleMeshShading ||
            m_ShadingType == kLatticeFormGouraudTriangleMeshShading ||
diff --git a/core/fpdfapi/fpdf_page/cpdf_tilingpattern.cpp b/core/fpdfapi/fpdf_page/cpdf_tilingpattern.cpp
index f49ad2b..3ace570 100644
--- a/core/fpdfapi/fpdf_page/cpdf_tilingpattern.cpp
+++ b/core/fpdfapi/fpdf_page/cpdf_tilingpattern.cpp
@@ -20,12 +20,9 @@
   m_bColored = pDict->GetIntegerBy("PaintType") == 1;
   if (parentMatrix)
     m_Pattern2Form.Concat(*parentMatrix);
-
-  m_pForm = nullptr;
 }
 
 CPDF_TilingPattern::~CPDF_TilingPattern() {
-  delete m_pForm;
 }
 
 FX_BOOL CPDF_TilingPattern::Load() {
@@ -44,8 +41,8 @@
   if (!pStream)
     return FALSE;
 
-  m_pForm = new CPDF_Form(m_pDocument, NULL, pStream);
-  m_pForm->ParseContent(NULL, &m_ParentMatrix, NULL, NULL);
+  m_pForm.reset(new CPDF_Form(m_pDocument, nullptr, pStream));
+  m_pForm->ParseContent(nullptr, &m_ParentMatrix, nullptr);
   m_BBox = pDict->GetRectBy("BBox");
   return TRUE;
 }
diff --git a/core/fpdfapi/fpdf_page/cpdf_tilingpattern.h b/core/fpdfapi/fpdf_page/cpdf_tilingpattern.h
index 44446ea..5936307 100644
--- a/core/fpdfapi/fpdf_page/cpdf_tilingpattern.h
+++ b/core/fpdfapi/fpdf_page/cpdf_tilingpattern.h
@@ -7,6 +7,8 @@
 #ifndef CORE_FPDFAPI_FPDF_PAGE_CPDF_TILINGPATTERN_H_
 #define CORE_FPDFAPI_FPDF_PAGE_CPDF_TILINGPATTERN_H_
 
+#include <memory>
+
 #include "core/fpdfapi/fpdf_page/cpdf_pattern.h"
 #include "core/fxcrt/include/fx_coordinates.h"
 #include "core/fxcrt/include/fx_system.h"
@@ -22,13 +24,23 @@
                      const CFX_Matrix* parentMatrix);
   ~CPDF_TilingPattern() override;
 
+  CPDF_TilingPattern* AsTilingPattern() override { return this; }
+  CPDF_ShadingPattern* AsShadingPattern() override { return nullptr; }
+
   FX_BOOL Load();
 
-  FX_BOOL m_bColored;
+  bool colored() const { return m_bColored; }
+  const CFX_FloatRect& bbox() const { return m_BBox; }
+  FX_FLOAT x_step() const { return m_XStep; }
+  FX_FLOAT y_step() const { return m_YStep; }
+  CPDF_Form* form() const { return m_pForm.get(); }
+
+ private:
+  bool m_bColored;
   CFX_FloatRect m_BBox;
   FX_FLOAT m_XStep;
   FX_FLOAT m_YStep;
-  CPDF_Form* m_pForm;
+  std::unique_ptr<CPDF_Form> m_pForm;
 };
 
 #endif  // CORE_FPDFAPI_FPDF_PAGE_CPDF_TILINGPATTERN_H_
diff --git a/core/fpdfapi/fpdf_page/fpdf_page_doc.cpp b/core/fpdfapi/fpdf_page/fpdf_page_doc.cpp
index b9019f8..aed6e1e 100644
--- a/core/fpdfapi/fpdf_page/fpdf_page_doc.cpp
+++ b/core/fpdfapi/fpdf_page/fpdf_page_doc.cpp
@@ -150,10 +150,8 @@
     if (!ptData->get())
       continue;
 
-    if (bForceRelease || ptData->use_count() < 2) {
-      ptData->get()->SetForceClear(bForceRelease);
+    if (bForceRelease || ptData->use_count() < 2)
       ptData->clear();
-    }
   }
 
   for (auto& it : m_FontMap) {
@@ -436,9 +434,9 @@
     CPDF_Dictionary* pDict = pPatternObj ? pPatternObj->GetDict() : nullptr;
     if (pDict) {
       int type = pDict->GetIntegerBy("PatternType");
-      if (type == 1) {
+      if (type == CPDF_Pattern::TILING) {
         pPattern = new CPDF_TilingPattern(m_pPDFDoc, pPatternObj, matrix);
-      } else if (type == 2) {
+      } else if (type == CPDF_Pattern::SHADING) {
         pPattern =
             new CPDF_ShadingPattern(m_pPDFDoc, pPatternObj, FALSE, matrix);
       }
diff --git a/core/fpdfapi/fpdf_page/fpdf_page_parser.cpp b/core/fpdfapi/fpdf_page/fpdf_page_parser.cpp
index d2889d8..1f10b4e 100644
--- a/core/fpdfapi/fpdf_page/fpdf_page_parser.cpp
+++ b/core/fpdfapi/fpdf_page/fpdf_page_parser.cpp
@@ -128,7 +128,6 @@
     CPDF_PageObjectHolder* pObjHolder,
     CPDF_Dictionary* pResources,
     CFX_FloatRect* pBBox,
-    CPDF_ParseOptions* pOptions,
     CPDF_AllStates* pStates,
     int level)
     : m_pDocument(pDocument),
@@ -154,21 +153,14 @@
       m_bReleaseLastDict(TRUE),
       m_bColored(FALSE),
       m_bResourceMissing(FALSE) {
-  if (pmtContentToUser) {
+  if (pmtContentToUser)
     m_mtContentToUser = *pmtContentToUser;
-  }
-  if (pOptions) {
-    m_Options = *pOptions;
-  }
-  if (!m_pResources) {
+  if (!m_pResources)
     m_pResources = m_pParentResources;
-  }
-  if (!m_pResources) {
+  if (!m_pResources)
     m_pResources = m_pPageResources;
-  }
-  if (pBBox) {
+  if (pBBox)
     m_BBox = *pBBox;
-  }
   if (pStates) {
     m_pCurStates->Copy(*pStates);
   } else {
@@ -492,39 +484,24 @@
 }
 
 void CPDF_StreamContentParser::Handle_CloseFillStrokePath() {
-  if (m_Options.m_bTextOnly) {
-    return;
-  }
   Handle_ClosePath();
   AddPathObject(FXFILL_WINDING, TRUE);
 }
 
 void CPDF_StreamContentParser::Handle_FillStrokePath() {
-  if (m_Options.m_bTextOnly) {
-    return;
-  }
   AddPathObject(FXFILL_WINDING, TRUE);
 }
 
 void CPDF_StreamContentParser::Handle_CloseEOFillStrokePath() {
-  if (m_Options.m_bTextOnly) {
-    return;
-  }
   AddPathPoint(m_PathStartX, m_PathStartY, FXPT_LINETO | FXPT_CLOSEFIGURE);
   AddPathObject(FXFILL_ALTERNATE, TRUE);
 }
 
 void CPDF_StreamContentParser::Handle_EOFillStrokePath() {
-  if (m_Options.m_bTextOnly) {
-    return;
-  }
   AddPathObject(FXFILL_ALTERNATE, TRUE);
 }
 
 void CPDF_StreamContentParser::Handle_BeginMarkedContent_Dictionary() {
-  if (!m_Options.m_bMarkedContent) {
-    return;
-  }
   CFX_ByteString tag = GetString(1);
   CPDF_Object* pProperty = GetObject(0);
   if (!pProperty) {
@@ -586,8 +563,8 @@
       }
     }
   }
-  CPDF_Stream* pStream = m_pSyntax->ReadInlineStream(
-      m_pDocument, pDict, pCSObj, m_Options.m_bDecodeInlineImage);
+  CPDF_Stream* pStream =
+      m_pSyntax->ReadInlineStream(m_pDocument, pDict, pCSObj);
   while (1) {
     CPDF_StreamParser::SyntaxType type = m_pSyntax->ParseNextElement();
     if (type == CPDF_StreamParser::EndOfData) {
@@ -601,14 +578,6 @@
       break;
     }
   }
-  if (m_Options.m_bTextOnly) {
-    if (pStream) {
-      pStream->Release();
-    } else {
-      pDict->Release();
-    }
-    return;
-  }
   pDict->SetAtName("Subtype", "Image");
   CPDF_ImageObject* pImgObj = AddImage(pStream, NULL, TRUE);
   if (!pImgObj) {
@@ -621,9 +590,6 @@
 }
 
 void CPDF_StreamContentParser::Handle_BeginMarkedContent() {
-  if (!m_Options.m_bMarkedContent) {
-    return;
-  }
   CFX_ByteString tag = GetString(0);
   m_CurContentMark.GetModify()->AddMark(tag, NULL, FALSE);
 }
@@ -638,9 +604,6 @@
 }
 
 void CPDF_StreamContentParser::Handle_CurveTo_123() {
-  if (m_Options.m_bTextOnly) {
-    return;
-  }
   AddPathPoint(GetNumber(5), GetNumber(4), FXPT_BEZIERTO);
   AddPathPoint(GetNumber(3), GetNumber(2), FXPT_BEZIERTO);
   AddPathPoint(GetNumber(1), GetNumber(0), FXPT_BEZIERTO);
@@ -657,9 +620,6 @@
 }
 
 void CPDF_StreamContentParser::Handle_SetColorSpace_Fill() {
-  if (m_Options.m_bTextOnly) {
-    return;
-  }
   CFX_ByteString csname = GetString(0);
   CPDF_ColorSpace* pCS = FindColorSpace(csname);
   if (!pCS) {
@@ -669,9 +629,6 @@
 }
 
 void CPDF_StreamContentParser::Handle_SetColorSpace_Stroke() {
-  if (m_Options.m_bTextOnly) {
-    return;
-  }
   CFX_ByteString csname = GetString(0);
   CPDF_ColorSpace* pCS = FindColorSpace(csname);
   if (!pCS) {
@@ -681,13 +638,10 @@
 }
 
 void CPDF_StreamContentParser::Handle_SetDash() {
-  if (m_Options.m_bTextOnly) {
+  CPDF_Array* pArray = GetObject(1) ? GetObject(1)->GetArray() : nullptr;
+  if (!pArray)
     return;
-  }
-  CPDF_Array* pArray = GetObject(1) ? GetObject(1)->GetArray() : NULL;
-  if (!pArray) {
-    return;
-  }
+
   m_pCurStates->SetLineDash(pArray, GetNumber(0), 1.0f);
 }
 
@@ -712,24 +666,6 @@
     return;
   }
 
-  if (m_Options.m_bTextOnly) {
-    if (!m_pResources)
-      return;
-
-    CPDF_Dictionary* pList = m_pResources->GetDictBy("XObject");
-    if (!pList && m_pPageResources && m_pResources != m_pPageResources)
-      pList = m_pPageResources->GetDictBy("XObject");
-    if (!pList)
-      return;
-    CPDF_Reference* pRes = ToReference(pList->GetObjectBy(name));
-    if (!pRes)
-      return;
-
-    FX_BOOL bForm;
-    if (m_pDocument->IsFormStream(pRes->GetRefObjNum(), bForm) && !bForm)
-      return;
-  }
-
   CPDF_Stream* pXObject = ToStream(FindResourceObj("XObject", name));
   if (!pXObject) {
     m_bResourceMissing = TRUE;
@@ -741,9 +677,6 @@
     type = pXObject->GetDict()->GetStringBy("Subtype");
 
   if (type == "Image") {
-    if (m_Options.m_bTextOnly) {
-      return;
-    }
     CPDF_ImageObject* pObj = AddImage(pXObject, NULL, FALSE);
     m_LastImageName = name;
     m_pLastImage = pObj->m_pImage;
@@ -751,44 +684,10 @@
       m_pObjectHolder->SetHasImageMask(m_pLastImage->IsMask());
   } else if (type == "Form") {
     AddForm(pXObject);
-  } else {
-    return;
   }
 }
 
 void CPDF_StreamContentParser::AddForm(CPDF_Stream* pStream) {
-  if (!m_Options.m_bSeparateForm) {
-    CPDF_Dictionary* pResources = pStream->GetDict()->GetDictBy("Resources");
-    CFX_Matrix form_matrix = pStream->GetDict()->GetMatrixBy("Matrix");
-    form_matrix.Concat(m_pCurStates->m_CTM);
-    CPDF_Array* pBBox = pStream->GetDict()->GetArrayBy("BBox");
-    CFX_FloatRect form_bbox;
-    CPDF_Path ClipPath;
-    if (pBBox) {
-      form_bbox = pStream->GetDict()->GetRectBy("BBox");
-      ClipPath.New();
-      ClipPath.AppendRect(form_bbox.left, form_bbox.bottom, form_bbox.right,
-                          form_bbox.top);
-      ClipPath.Transform(&form_matrix);
-      form_bbox.Transform(&form_matrix);
-    }
-    CPDF_StreamContentParser parser(m_pDocument, m_pPageResources, m_pResources,
-                                    &m_mtContentToUser, m_pObjectHolder,
-                                    pResources, &form_bbox, &m_Options,
-                                    m_pCurStates.get(), m_Level + 1);
-    parser.m_pCurStates->m_CTM = form_matrix;
-    if (ClipPath.NotNull()) {
-      parser.m_pCurStates->m_ClipPath.AppendPath(ClipPath, FXFILL_WINDING,
-                                                 TRUE);
-    }
-    CPDF_StreamAcc stream;
-    stream.LoadAllData(pStream, FALSE);
-    if (stream.GetSize() == 0) {
-      return;
-    }
-    parser.Parse(stream.GetData(), stream.GetSize(), 0);
-    return;
-  }
   std::unique_ptr<CPDF_FormObject> pFormObj(new CPDF_FormObject);
   pFormObj->m_pForm =
       new CPDF_Form(m_pDocument, m_pPageResources, pStream, m_pResources);
@@ -799,7 +698,7 @@
   status.m_GraphState = m_pCurStates->m_GraphState;
   status.m_ColorState = m_pCurStates->m_ColorState;
   status.m_TextState = m_pCurStates->m_TextState;
-  pFormObj->m_pForm->ParseContent(&status, NULL, NULL, &m_Options, m_Level + 1);
+  pFormObj->m_pForm->ParseContent(&status, nullptr, nullptr, m_Level + 1);
   if (!m_pObjectHolder->BackgroundAlphaNeeded() &&
       pFormObj->m_pForm->BackgroundAlphaNeeded()) {
     m_pObjectHolder->SetBackgroundAlphaNeeded(TRUE);
@@ -843,12 +742,9 @@
 void CPDF_StreamContentParser::Handle_EndImage() {}
 
 void CPDF_StreamContentParser::Handle_EndMarkedContent() {
-  if (!m_Options.m_bMarkedContent) {
+  if (m_CurContentMark.IsNull())
     return;
-  }
-  if (m_CurContentMark.IsNull()) {
-    return;
-  }
+
   int count = m_CurContentMark.GetObject()->CountItems();
   if (count == 1) {
     m_CurContentMark.SetNull();
@@ -873,23 +769,14 @@
 }
 
 void CPDF_StreamContentParser::Handle_FillPath() {
-  if (m_Options.m_bTextOnly) {
-    return;
-  }
   AddPathObject(FXFILL_WINDING, FALSE);
 }
 
 void CPDF_StreamContentParser::Handle_FillPathOld() {
-  if (m_Options.m_bTextOnly) {
-    return;
-  }
   AddPathObject(FXFILL_WINDING, FALSE);
 }
 
 void CPDF_StreamContentParser::Handle_EOFillPath() {
-  if (m_Options.m_bTextOnly) {
-    return;
-  }
   AddPathObject(FXFILL_ALTERNATE, FALSE);
 }
 
@@ -916,9 +803,6 @@
 }
 
 void CPDF_StreamContentParser::Handle_ClosePath() {
-  if (m_Options.m_bTextOnly) {
-    return;
-  }
   if (m_PathPointCount == 0) {
     return;
   }
@@ -973,9 +857,6 @@
   if (m_ParamCount != 2)
     return;
 
-  if (m_Options.m_bTextOnly) {
-    return;
-  }
   AddPathPoint(GetNumber(1), GetNumber(0), FXPT_LINETO);
 }
 
@@ -983,10 +864,6 @@
   if (m_ParamCount != 2)
     return;
 
-  if (m_Options.m_bTextOnly) {
-    m_pSyntax->SkipPathObject();
-    return;
-  }
   AddPathPoint(GetNumber(1), GetNumber(0), FXPT_MOVETO);
   ParsePathObject();
 }
@@ -998,9 +875,6 @@
 void CPDF_StreamContentParser::Handle_MarkPlace() {}
 
 void CPDF_StreamContentParser::Handle_EndPath() {
-  if (m_Options.m_bTextOnly) {
-    return;
-  }
   AddPathObject(0, FALSE);
 }
 
@@ -1019,9 +893,6 @@
 }
 
 void CPDF_StreamContentParser::Handle_Rectangle() {
-  if (m_Options.m_bTextOnly) {
-    return;
-  }
   FX_FLOAT x = GetNumber(3), y = GetNumber(2);
   FX_FLOAT w = GetNumber(1), h = GetNumber(0);
   AddPathRect(x, y, w, h);
@@ -1065,24 +936,15 @@
 void CPDF_StreamContentParser::Handle_SetRenderIntent() {}
 
 void CPDF_StreamContentParser::Handle_CloseStrokePath() {
-  if (m_Options.m_bTextOnly) {
-    return;
-  }
   Handle_ClosePath();
   AddPathObject(0, TRUE);
 }
 
 void CPDF_StreamContentParser::Handle_StrokePath() {
-  if (m_Options.m_bTextOnly) {
-    return;
-  }
   AddPathObject(0, TRUE);
 }
 
 void CPDF_StreamContentParser::Handle_SetColor_Fill() {
-  if (m_Options.m_bTextOnly) {
-    return;
-  }
   FX_FLOAT values[4];
   int nargs = m_ParamCount;
   if (nargs > 4) {
@@ -1095,9 +957,6 @@
 }
 
 void CPDF_StreamContentParser::Handle_SetColor_Stroke() {
-  if (m_Options.m_bTextOnly) {
-    return;
-  }
   FX_FLOAT values[4];
   int nargs = m_ParamCount;
   if (nargs > 4) {
@@ -1110,9 +969,6 @@
 }
 
 void CPDF_StreamContentParser::Handle_SetColorPS_Fill() {
-  if (m_Options.m_bTextOnly) {
-    return;
-  }
   CPDF_Object* pLastParam = GetObject(0);
   if (!pLastParam) {
     return;
@@ -1140,9 +996,6 @@
 }
 
 void CPDF_StreamContentParser::Handle_SetColorPS_Stroke() {
-  if (m_Options.m_bTextOnly) {
-    return;
-  }
   CPDF_Object* pLastParam = GetObject(0);
   if (!pLastParam) {
     return;
@@ -1178,34 +1031,24 @@
                              CPDF_ColorSpace* pCS);
 
 void CPDF_StreamContentParser::Handle_ShadeFill() {
-  if (m_Options.m_bTextOnly) {
-    return;
-  }
   CPDF_Pattern* pPattern = FindPattern(GetString(0), TRUE);
-  if (!pPattern) {
+  if (!pPattern)
     return;
-  }
-  if (pPattern->m_PatternType != CPDF_Pattern::SHADING) {
+
+  CPDF_ShadingPattern* pShading = pPattern->AsShadingPattern();
+  if (!pShading)
     return;
-  }
-  CPDF_ShadingPattern* pShading = static_cast<CPDF_ShadingPattern*>(pPattern);
-  if (!pShading->m_bShadingObj) {
+
+  if (!pShading->m_bShadingObj || !pShading->Load())
     return;
-  }
-  if (!pShading->Load()) {
-    return;
-  }
+
   std::unique_ptr<CPDF_ShadingObject> pObj(new CPDF_ShadingObject);
   pObj->m_pShading = pShading;
   SetGraphicStates(pObj.get(), FALSE, FALSE, FALSE);
   pObj->m_Matrix = m_pCurStates->m_CTM;
   pObj->m_Matrix.Concat(m_mtContentToUser);
-  CFX_FloatRect bbox;
-  if (!pObj->m_ClipPath.IsNull()) {
-    bbox = pObj->m_ClipPath.GetClipBox();
-  } else {
-    bbox = m_BBox;
-  }
+  CFX_FloatRect bbox =
+      pObj->m_ClipPath.IsNull() ? m_BBox : pObj->m_ClipPath.GetClipBox();
   if (pShading->IsMeshShading()) {
     bbox.Intersect(GetShadingBBox(ToStream(pShading->m_pShadingObj),
                                   pShading->m_ShadingType, &pObj->m_Matrix,
@@ -1518,9 +1361,6 @@
 }
 
 void CPDF_StreamContentParser::Handle_CurveTo_23() {
-  if (m_Options.m_bTextOnly) {
-    return;
-  }
   AddPathPoint(m_PathCurrentX, m_PathCurrentY, FXPT_BEZIERTO);
   AddPathPoint(GetNumber(3), GetNumber(2), FXPT_BEZIERTO);
   AddPathPoint(GetNumber(1), GetNumber(0), FXPT_BEZIERTO);
@@ -1540,9 +1380,6 @@
 }
 
 void CPDF_StreamContentParser::Handle_CurveTo_13() {
-  if (m_Options.m_bTextOnly) {
-    return;
-  }
   AddPathPoint(GetNumber(3), GetNumber(2), FXPT_BEZIERTO);
   AddPathPoint(GetNumber(1), GetNumber(0), FXPT_BEZIERTO);
   AddPathPoint(GetNumber(1), GetNumber(0), FXPT_BEZIERTO);
diff --git a/core/fpdfapi/fpdf_page/fpdf_page_parser_old.cpp b/core/fpdfapi/fpdf_page/fpdf_page_parser_old.cpp
index cf29aa2..dff4bb6 100644
--- a/core/fpdfapi/fpdf_page/fpdf_page_parser_old.cpp
+++ b/core/fpdfapi/fpdf_page/fpdf_page_parser_old.cpp
@@ -124,8 +124,7 @@
 
 CPDF_Stream* CPDF_StreamParser::ReadInlineStream(CPDF_Document* pDoc,
                                                  CPDF_Dictionary* pDict,
-                                                 CPDF_Object* pCSObj,
-                                                 FX_BOOL bDecode) {
+                                                 CPDF_Object* pCSObj) {
   if (m_Pos == m_Size)
     return nullptr;
 
@@ -199,48 +198,33 @@
     dwStreamSize =
         PDF_DecodeInlineStream(m_pBuf + m_Pos, m_Size - m_Pos, width, height,
                                Decoder, pParam, pData, dwDestSize);
-    if ((int)dwStreamSize < 0) {
-      FX_Free(pData);
+    FX_Free(pData);
+    if ((int)dwStreamSize < 0)
       return NULL;
-    }
-    if (bDecode) {
-      m_Pos += dwStreamSize;
-      dwStreamSize = dwDestSize;
-      if (CPDF_Array* pArray = pFilter->AsArray()) {
-        pArray->RemoveAt(0);
-        CPDF_Array* pParams = pDict->GetArrayBy("DecodeParms");
-        if (pParams)
-          pParams->RemoveAt(0);
-      } else {
-        pDict->RemoveAt("Filter");
-        pDict->RemoveAt("DecodeParms");
-      }
-    } else {
-      FX_Free(pData);
-      uint32_t dwSavePos = m_Pos;
-      m_Pos += dwStreamSize;
-      while (1) {
-        uint32_t dwPrevPos = m_Pos;
-        CPDF_StreamParser::SyntaxType type = ParseNextElement();
-        if (type == CPDF_StreamParser::EndOfData) {
-          break;
-        }
-        if (type != CPDF_StreamParser::Keyword) {
-          dwStreamSize += m_Pos - dwPrevPos;
-          continue;
-        }
-        if (GetWordSize() == 2 && GetWordBuf()[0] == 'E' &&
-            GetWordBuf()[1] == 'I') {
-          m_Pos = dwPrevPos;
-          break;
-        }
+
+    uint32_t dwSavePos = m_Pos;
+    m_Pos += dwStreamSize;
+    while (1) {
+      uint32_t dwPrevPos = m_Pos;
+      CPDF_StreamParser::SyntaxType type = ParseNextElement();
+      if (type == CPDF_StreamParser::EndOfData)
+        break;
+
+      if (type != CPDF_StreamParser::Keyword) {
         dwStreamSize += m_Pos - dwPrevPos;
+        continue;
       }
-      m_Pos = dwSavePos;
-      pData = FX_Alloc(uint8_t, dwStreamSize);
-      FXSYS_memcpy(pData, m_pBuf + m_Pos, dwStreamSize);
-      m_Pos += dwStreamSize;
+      if (GetWordSize() == 2 && GetWordBuf()[0] == 'E' &&
+          GetWordBuf()[1] == 'I') {
+        m_Pos = dwPrevPos;
+        break;
+      }
+      dwStreamSize += m_Pos - dwPrevPos;
     }
+    m_Pos = dwSavePos;
+    pData = FX_Alloc(uint8_t, dwStreamSize);
+    FXSYS_memcpy(pData, m_pBuf + m_Pos, dwStreamSize);
+    m_Pos += dwStreamSize;
   }
   pDict->SetAtInteger("Length", (int)dwStreamSize);
   return new CPDF_Stream(pData, dwStreamSize, pDict);
@@ -331,57 +315,6 @@
   return Keyword;
 }
 
-void CPDF_StreamParser::SkipPathObject() {
-  uint32_t command_startpos = m_Pos;
-  if (!PositionIsInBounds())
-    return;
-
-  int ch = m_pBuf[m_Pos++];
-  while (1) {
-    while (PDFCharIsWhitespace(ch)) {
-      if (!PositionIsInBounds())
-        return;
-      ch = m_pBuf[m_Pos++];
-    }
-
-    if (!PDFCharIsNumeric(ch)) {
-      m_Pos = command_startpos;
-      return;
-    }
-
-    while (1) {
-      while (!PDFCharIsWhitespace(ch)) {
-        if (!PositionIsInBounds())
-          return;
-        ch = m_pBuf[m_Pos++];
-      }
-
-      while (PDFCharIsWhitespace(ch)) {
-        if (!PositionIsInBounds())
-          return;
-        ch = m_pBuf[m_Pos++];
-      }
-
-      if (PDFCharIsNumeric(ch))
-        continue;
-
-      uint32_t op_startpos = m_Pos - 1;
-      while (!PDFCharIsWhitespace(ch) && !PDFCharIsDelimiter(ch)) {
-        if (!PositionIsInBounds())
-          return;
-        ch = m_pBuf[m_Pos++];
-      }
-
-      if (IsPathOperator(&m_pBuf[op_startpos], m_Pos - 1 - op_startpos)) {
-        command_startpos = m_Pos;
-        break;
-      }
-      m_Pos = command_startpos;
-      return;
-    }
-  }
-}
-
 CPDF_Object* CPDF_StreamParser::ReadNextObject(FX_BOOL bAllowNestedArray,
                                                FX_BOOL bInArray) {
   FX_BOOL bIsNumber;
@@ -697,7 +630,7 @@
     FX_Free(m_pData);
 }
 
-void CPDF_ContentParser::Start(CPDF_Page* pPage, CPDF_ParseOptions* pOptions) {
+void CPDF_ContentParser::Start(CPDF_Page* pPage) {
   if (m_Status != Ready || !pPage || !pPage->m_pDocument ||
       !pPage->m_pFormDict) {
     m_Status = Done;
@@ -705,9 +638,6 @@
   }
   m_pObjectHolder = pPage;
   m_bForm = FALSE;
-  if (pOptions) {
-    m_Options = *pOptions;
-  }
   m_Status = ToBeContinued;
   m_InternalStage = STAGE_GETCONTENT;
   m_CurrentOffset = 0;
@@ -736,7 +666,6 @@
                                CPDF_AllStates* pGraphicStates,
                                CFX_Matrix* pParentMatrix,
                                CPDF_Type3Char* pType3Char,
-                               CPDF_ParseOptions* pOptions,
                                int level) {
   m_pType3Char = pType3Char;
   m_pObjectHolder = pForm;
@@ -765,8 +694,7 @@
   CPDF_Dictionary* pResources = pForm->m_pFormDict->GetDictBy("Resources");
   m_pParser.reset(new CPDF_StreamContentParser(
       pForm->m_pDocument, pForm->m_pPageResources, pForm->m_pResources,
-      pParentMatrix, pForm, pResources, &form_bbox, pOptions, pGraphicStates,
-      level));
+      pParentMatrix, pForm, pResources, &form_bbox, pGraphicStates, level));
   m_pParser->GetCurStates()->m_CTM = form_matrix;
   m_pParser->GetCurStates()->m_ParentMatrix = form_matrix;
   if (ClipPath.NotNull()) {
@@ -836,7 +764,7 @@
         m_pParser.reset(new CPDF_StreamContentParser(
             m_pObjectHolder->m_pDocument, m_pObjectHolder->m_pPageResources,
             nullptr, nullptr, m_pObjectHolder, m_pObjectHolder->m_pResources,
-            &m_pObjectHolder->m_BBox, &m_Options, nullptr, 0));
+            &m_pObjectHolder->m_BBox, nullptr, 0));
         m_pParser->GetCurStates()->m_ColorState.GetModify()->Default();
       }
       if (m_CurrentOffset >= m_Size) {
diff --git a/core/fpdfapi/fpdf_page/include/cpdf_form.h b/core/fpdfapi/fpdf_page/include/cpdf_form.h
index 3b9f1cc..542ab49 100644
--- a/core/fpdfapi/fpdf_page/include/cpdf_form.h
+++ b/core/fpdfapi/fpdf_page/include/cpdf_form.h
@@ -15,7 +15,6 @@
 class CPDF_AllStates;
 class CFX_Matrix;
 class CPDF_Type3Char;
-class CPDF_ParseOptions;
 
 class CPDF_Form : public CPDF_PageObjectHolder {
  public:
@@ -29,13 +28,11 @@
   void StartParse(CPDF_AllStates* pGraphicStates,
                   CFX_Matrix* pParentMatrix,
                   CPDF_Type3Char* pType3Char,
-                  CPDF_ParseOptions* pOptions,
                   int level = 0);
 
   void ParseContent(CPDF_AllStates* pGraphicStates,
                     CFX_Matrix* pParentMatrix,
                     CPDF_Type3Char* pType3Char,
-                    CPDF_ParseOptions* pOptions,
                     int level = 0);
 
   CPDF_Form* Clone() const;
diff --git a/core/fpdfapi/fpdf_page/include/cpdf_page.h b/core/fpdfapi/fpdf_page/include/cpdf_page.h
index 3ede3c9..7f44301 100644
--- a/core/fpdfapi/fpdf_page/include/cpdf_page.h
+++ b/core/fpdfapi/fpdf_page/include/cpdf_page.h
@@ -7,30 +7,26 @@
 #ifndef CORE_FPDFAPI_FPDF_PAGE_INCLUDE_CPDF_PAGE_H_
 #define CORE_FPDFAPI_FPDF_PAGE_INCLUDE_CPDF_PAGE_H_
 
+#include <memory>
+
 #include "core/fpdfapi/fpdf_page/include/cpdf_pageobjectholder.h"
 #include "core/fxcrt/include/fx_basic.h"
 #include "core/fxcrt/include/fx_coordinates.h"
 #include "core/fxcrt/include/fx_system.h"
 
-class CPDF_Document;
 class CPDF_Dictionary;
+class CPDF_Document;
 class CPDF_Object;
 class CPDF_PageRenderCache;
-class CPDF_ParseOptions;
-
-CPDF_Object* FPDFAPI_GetPageAttr(CPDF_Dictionary* pPageDict,
-                                 const CFX_ByteStringC& name);
 
 class CPDF_Page : public CPDF_PageObjectHolder, public CFX_PrivateData {
  public:
-  CPDF_Page();
+  CPDF_Page(CPDF_Document* pDocument,
+            CPDF_Dictionary* pPageDict,
+            bool bPageCache);
   ~CPDF_Page();
 
-  void Load(CPDF_Document* pDocument,
-            CPDF_Dictionary* pPageDict,
-            FX_BOOL bPageCache = TRUE);
-
-  void ParseContent(CPDF_ParseOptions* pOptions);
+  void ParseContent();
 
   void GetDisplayMatrix(CFX_Matrix& matrix,
                         int xPos,
@@ -43,18 +39,18 @@
   FX_FLOAT GetPageHeight() const { return m_PageHeight; }
   CFX_FloatRect GetPageBBox() const { return m_BBox; }
   const CFX_Matrix& GetPageMatrix() const { return m_PageMatrix; }
-  CPDF_Object* GetPageAttr(const CFX_ByteStringC& name) const;
-  CPDF_PageRenderCache* GetRenderCache() const { return m_pPageRender; }
+  CPDF_Object* GetPageAttr(const CFX_ByteString& name) const;
+  CPDF_PageRenderCache* GetRenderCache() const { return m_pPageRender.get(); }
 
  protected:
   friend class CPDF_ContentParser;
 
-  void StartParse(CPDF_ParseOptions* pOptions);
+  void StartParse();
 
   FX_FLOAT m_PageWidth;
   FX_FLOAT m_PageHeight;
   CFX_Matrix m_PageMatrix;
-  CPDF_PageRenderCache* m_pPageRender;
+  std::unique_ptr<CPDF_PageRenderCache> m_pPageRender;
 };
 
 #endif  // CORE_FPDFAPI_FPDF_PAGE_INCLUDE_CPDF_PAGE_H_
diff --git a/core/fpdfapi/fpdf_page/pageint.h b/core/fpdfapi/fpdf_page/pageint.h
index 98a05d5..24ed226 100644
--- a/core/fpdfapi/fpdf_page/pageint.h
+++ b/core/fpdfapi/fpdf_page/pageint.h
@@ -14,7 +14,6 @@
 
 #include "core/fpdfapi/fpdf_page/cpdf_contentmark.h"
 #include "core/fpdfapi/fpdf_page/cpdf_countedobject.h"
-#include "core/fpdfapi/fpdf_page/cpdf_parseoptions.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_pageobjectholder.h"
 #include "core/fxge/include/fx_ge.h"
 
@@ -27,7 +26,6 @@
 class CPDF_Image;
 class CPDF_ImageObject;
 class CPDF_Page;
-class CPDF_ParseOptions;
 class CPDF_Pattern;
 class CPDF_StreamAcc;
 class CPDF_TextObject;
@@ -44,8 +42,7 @@
 
   CPDF_Stream* ReadInlineStream(CPDF_Document* pDoc,
                                 CPDF_Dictionary* pDict,
-                                CPDF_Object* pCSObj,
-                                FX_BOOL bDecode);
+                                CPDF_Object* pCSObj);
   SyntaxType ParseNextElement();
   uint8_t* GetWordBuf() { return m_WordBuffer; }
   uint32_t GetWordSize() const { return m_WordSize; }
@@ -58,7 +55,6 @@
   void SetPos(uint32_t pos) { m_Pos = pos; }
   CPDF_Object* ReadNextObject(FX_BOOL bAllowNestedArray = FALSE,
                               FX_BOOL bInArray = FALSE);
-  void SkipPathObject();
 
  protected:
   friend class fpdf_page_parser_old_ReadHexString_Test;
@@ -113,7 +109,6 @@
                            CPDF_PageObjectHolder* pObjectHolder,
                            CPDF_Dictionary* pResources,
                            CFX_FloatRect* pBBox,
-                           CPDF_ParseOptions* pOptions,
                            CPDF_AllStates* pAllStates,
                            int level);
   ~CPDF_StreamContentParser();
@@ -252,7 +247,6 @@
   int m_Level;
   CFX_Matrix m_mtContentToUser;
   CFX_FloatRect m_BBox;
-  CPDF_ParseOptions m_Options;
   ContentParam m_ParamBuf[PARAM_BUF_SIZE];
   uint32_t m_ParamStartPos;
   uint32_t m_ParamCount;
@@ -291,12 +285,11 @@
   ~CPDF_ContentParser();
 
   ParseStatus GetStatus() const { return m_Status; }
-  void Start(CPDF_Page* pPage, CPDF_ParseOptions* pOptions);
+  void Start(CPDF_Page* pPage);
   void Start(CPDF_Form* pForm,
              CPDF_AllStates* pGraphicStates,
              CFX_Matrix* pParentMatrix,
              CPDF_Type3Char* pType3Char,
-             CPDF_ParseOptions* pOptions,
              int level);
   void Continue(IFX_Pause* pPause);
 
@@ -311,7 +304,6 @@
   InternalStage m_InternalStage;
   CPDF_PageObjectHolder* m_pObjectHolder;
   FX_BOOL m_bForm;
-  CPDF_ParseOptions m_Options;
   CPDF_Type3Char* m_pType3Char;
   uint32_t m_nStreams;
   std::unique_ptr<CPDF_StreamAcc> m_pSingleStream;
diff --git a/core/fpdfapi/fpdf_render/fpdf_render.cpp b/core/fpdfapi/fpdf_render/fpdf_render.cpp
index 066d4eb..c8fa406 100644
--- a/core/fpdfapi/fpdf_render/fpdf_render.cpp
+++ b/core/fpdfapi/fpdf_render/fpdf_render.cpp
@@ -101,12 +101,6 @@
 
   CPDF_DocRenderData* GetRenderData() override { return &m_RenderData; }
 
-  CPDF_PageRenderCache* CreatePageCache(CPDF_Page* pPage) override {
-    return new CPDF_PageRenderCache(pPage);
-  }
-
-  void DestroyPageCache(CPDF_PageRenderCache* pCache) override;
-
   CPDF_DocRenderData m_RenderData;
 };
 
@@ -121,10 +115,6 @@
     p->Clear(FALSE);
   }
 }
-void CPDF_RenderModule::DestroyPageCache(CPDF_PageRenderCache* pCache) {
-  delete pCache;
-}
-
 void CPDF_ModuleMgr::InitRenderModule() {
   m_pRenderModule.reset(new CPDF_RenderModule);
 }
diff --git a/core/fpdfapi/fpdf_render/fpdf_render_cache.cpp b/core/fpdfapi/fpdf_render/fpdf_render_cache.cpp
index d95edd7..b0539a2 100644
--- a/core/fpdfapi/fpdf_render/fpdf_render_cache.cpp
+++ b/core/fpdfapi/fpdf_render/fpdf_render_cache.cpp
@@ -6,7 +6,6 @@
 
 #include "core/fpdfapi/fpdf_render/cpdf_pagerendercache.h"
 
-#include "core/fpdfapi/fpdf_page/cpdf_parseoptions.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_page.h"
 #include "core/fpdfapi/fpdf_page/pageint.h"
 #include "core/fpdfapi/fpdf_parser/include/cpdf_document.h"
diff --git a/core/fpdfapi/fpdf_render/fpdf_render_image.cpp b/core/fpdfapi/fpdf_render/fpdf_render_image.cpp
index ec8a784..aedf803 100644
--- a/core/fpdfapi/fpdf_render/fpdf_render_image.cpp
+++ b/core/fpdfapi/fpdf_render/fpdf_render_image.cpp
@@ -9,7 +9,6 @@
 #include <utility>
 #include <vector>
 
-#include "core/fpdfapi/fpdf_page/cpdf_parseoptions.h"
 #include "core/fpdfapi/fpdf_page/cpdf_shadingpattern.h"
 #include "core/fpdfapi/fpdf_page/cpdf_tilingpattern.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_form.h"
@@ -534,14 +533,13 @@
                              m_pRenderStatus->m_bDropObjects, NULL, TRUE);
     CFX_Matrix patternDevice = *pObj2Device;
     patternDevice.Translate((FX_FLOAT)-rect.left, (FX_FLOAT)-rect.top);
-    if (m_pPattern->m_PatternType == CPDF_Pattern::TILING) {
-      bitmap_render.DrawTilingPattern(
-          static_cast<CPDF_TilingPattern*>(m_pPattern), m_pImageObject,
-          &patternDevice, FALSE);
-    } else {
-      bitmap_render.DrawShadingPattern(
-          static_cast<CPDF_ShadingPattern*>(m_pPattern), m_pImageObject,
-          &patternDevice, FALSE);
+    if (CPDF_TilingPattern* pTilingPattern = m_pPattern->AsTilingPattern()) {
+      bitmap_render.DrawTilingPattern(pTilingPattern, m_pImageObject,
+                                      &patternDevice, FALSE);
+    } else if (CPDF_ShadingPattern* pShadingPattern =
+                   m_pPattern->AsShadingPattern()) {
+      bitmap_render.DrawShadingPattern(pShadingPattern, m_pImageObject,
+                                       &patternDevice, FALSE);
     }
   }
   {
@@ -894,7 +892,7 @@
 
   CPDF_Form form(m_pContext->GetDocument(), m_pContext->GetPageResources(),
                  pGroup);
-  form.ParseContent(NULL, NULL, NULL, NULL);
+  form.ParseContent(nullptr, nullptr, nullptr);
 
   CFX_FxgeDevice bitmap_device;
   FX_BOOL bLuminosity = pSMaskDict->GetStringBy("S") != "Alpha";
diff --git a/core/fpdfapi/fpdf_render/fpdf_render_loadimage.cpp b/core/fpdfapi/fpdf_render/fpdf_render_loadimage.cpp
index 44ac29f..19aeb71 100644
--- a/core/fpdfapi/fpdf_render/fpdf_render_loadimage.cpp
+++ b/core/fpdfapi/fpdf_render/fpdf_render_loadimage.cpp
@@ -10,7 +10,6 @@
 #include <memory>
 #include <vector>
 
-#include "core/fpdfapi/fpdf_page/cpdf_parseoptions.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_image.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_imageobject.h"
 #include "core/fpdfapi/fpdf_page/pageint.h"
diff --git a/core/fpdfapi/fpdf_render/fpdf_render_pattern.cpp b/core/fpdfapi/fpdf_render/fpdf_render_pattern.cpp
index c235fd9..0af1175 100644
--- a/core/fpdfapi/fpdf_render/fpdf_render_pattern.cpp
+++ b/core/fpdfapi/fpdf_render/fpdf_render_pattern.cpp
@@ -8,7 +8,6 @@
 
 #include "core/fpdfapi/fpdf_page/cpdf_graphicstates.h"
 #include "core/fpdfapi/fpdf_page/cpdf_meshstream.h"
-#include "core/fpdfapi/fpdf_page/cpdf_parseoptions.h"
 #include "core/fpdfapi/fpdf_page/cpdf_shadingpattern.h"
 #include "core/fpdfapi/fpdf_page/cpdf_tilingpattern.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_form.h"
@@ -947,7 +946,7 @@
     m_pDevice->RestoreState();
     return;
   }
-  CFX_Matrix matrix = pattern->m_Pattern2Form;
+  CFX_Matrix matrix = *pattern->pattern_to_form();
   matrix.Concat(*pObj2Device);
   GetScaledMatrix(matrix);
   int alpha = pPageObj->m_GeneralState.GetAlpha(bStroke);
@@ -979,15 +978,15 @@
                                        int flags) {
   CFX_DIBitmap* pBitmap = new CFX_DIBitmap;
   if (!pBitmap->Create(width, height,
-                       pPattern->m_bColored ? FXDIB_Argb : FXDIB_8bppMask)) {
+                       pPattern->colored() ? FXDIB_Argb : FXDIB_8bppMask)) {
     delete pBitmap;
     return NULL;
   }
   CFX_FxgeDevice bitmap_device;
   bitmap_device.Attach(pBitmap);
   pBitmap->Clear(0);
-  CFX_FloatRect cell_bbox = pPattern->m_BBox;
-  pPattern->m_Pattern2Form.TransformRect(cell_bbox);
+  CFX_FloatRect cell_bbox = pPattern->bbox();
+  pPattern->pattern_to_form()->TransformRect(cell_bbox);
   pObject2Device->TransformRect(cell_bbox);
   CFX_FloatRect bitmap_rect(0.0f, 0.0f, (FX_FLOAT)width, (FX_FLOAT)height);
   CFX_Matrix mtAdjust;
@@ -995,13 +994,13 @@
   CFX_Matrix mtPattern2Bitmap = *pObject2Device;
   mtPattern2Bitmap.Concat(mtAdjust);
   CPDF_RenderOptions options;
-  if (!pPattern->m_bColored) {
+  if (!pPattern->colored())
     options.m_ColorMode = RENDER_COLOR_ALPHA;
-  }
+
   flags |= RENDER_FORCE_HALFTONE;
   options.m_Flags = flags;
   CPDF_RenderContext context(pDoc, pCache);
-  context.AppendLayer(pPattern->m_pForm, &mtPattern2Bitmap);
+  context.AppendLayer(pPattern->form(), &mtPattern2Bitmap);
   context.Render(&bitmap_device, &options, nullptr);
   return pBitmap;
 }
@@ -1033,17 +1032,17 @@
   FX_FLOAT sd = FXSYS_fabs(dCTM.d);
   clip_box.right = clip_box.left + (int32_t)FXSYS_ceil(clip_box.Width() * sa);
   clip_box.bottom = clip_box.top + (int32_t)FXSYS_ceil(clip_box.Height() * sd);
-  CFX_Matrix mtPattern2Device = pPattern->m_Pattern2Form;
+  CFX_Matrix mtPattern2Device = *pPattern->pattern_to_form();
   mtPattern2Device.Concat(*pObj2Device);
   GetScaledMatrix(mtPattern2Device);
   FX_BOOL bAligned = FALSE;
-  if (pPattern->m_BBox.left == 0 && pPattern->m_BBox.bottom == 0 &&
-      pPattern->m_BBox.right == pPattern->m_XStep &&
-      pPattern->m_BBox.top == pPattern->m_YStep &&
+  if (pPattern->bbox().left == 0 && pPattern->bbox().bottom == 0 &&
+      pPattern->bbox().right == pPattern->x_step() &&
+      pPattern->bbox().top == pPattern->y_step() &&
       (mtPattern2Device.IsScaled() || mtPattern2Device.Is90Rotated())) {
     bAligned = TRUE;
   }
-  CFX_FloatRect cell_bbox = pPattern->m_BBox;
+  CFX_FloatRect cell_bbox = pPattern->bbox();
   mtPattern2Device.TransformRect(cell_bbox);
   int width = (int)FXSYS_ceil(cell_bbox.Width());
   int height = (int)FXSYS_ceil(cell_bbox.Height());
@@ -1059,40 +1058,40 @@
   CFX_FloatRect clip_box_p(clip_box);
   clip_box_p.Transform(&mtDevice2Pattern);
 
-  min_col = (int)FXSYS_ceil((clip_box_p.left - pPattern->m_BBox.right) /
-                            pPattern->m_XStep);
-  max_col = (int)FXSYS_floor((clip_box_p.right - pPattern->m_BBox.left) /
-                             pPattern->m_XStep);
-  min_row = (int)FXSYS_ceil((clip_box_p.bottom - pPattern->m_BBox.top) /
-                            pPattern->m_YStep);
-  max_row = (int)FXSYS_floor((clip_box_p.top - pPattern->m_BBox.bottom) /
-                             pPattern->m_YStep);
+  min_col = (int)FXSYS_ceil((clip_box_p.left - pPattern->bbox().right) /
+                            pPattern->x_step());
+  max_col = (int)FXSYS_floor((clip_box_p.right - pPattern->bbox().left) /
+                             pPattern->x_step());
+  min_row = (int)FXSYS_ceil((clip_box_p.bottom - pPattern->bbox().top) /
+                            pPattern->y_step());
+  max_row = (int)FXSYS_floor((clip_box_p.top - pPattern->bbox().bottom) /
+                             pPattern->y_step());
 
   if (width > clip_box.Width() || height > clip_box.Height() ||
       width * height > clip_box.Width() * clip_box.Height()) {
     CPDF_GraphicStates* pStates = NULL;
-    if (!pPattern->m_bColored) {
+    if (!pPattern->colored())
       pStates = CloneObjStates(pPageObj, bStroke);
-    }
-    CPDF_Dictionary* pFormResource = NULL;
-    if (pPattern->m_pForm->m_pFormDict) {
-      pFormResource = pPattern->m_pForm->m_pFormDict->GetDictBy("Resources");
-    }
+
+    CPDF_Dictionary* pFormResource = nullptr;
+    if (pPattern->form()->m_pFormDict)
+      pFormResource = pPattern->form()->m_pFormDict->GetDictBy("Resources");
+
     for (int col = min_col; col <= max_col; col++)
       for (int row = min_row; row <= max_row; row++) {
         FX_FLOAT orig_x, orig_y;
-        orig_x = col * pPattern->m_XStep;
-        orig_y = row * pPattern->m_YStep;
+        orig_x = col * pPattern->x_step();
+        orig_y = row * pPattern->y_step();
         mtPattern2Device.Transform(orig_x, orig_y);
         CFX_Matrix matrix = *pObj2Device;
         matrix.Translate(orig_x - mtPattern2Device.e,
                          orig_y - mtPattern2Device.f);
         m_pDevice->SaveState();
         CPDF_RenderStatus status;
-        status.Initialize(m_pContext, m_pDevice, NULL, NULL, this, pStates,
-                          &m_Options, pPattern->m_pForm->m_Transparency,
+        status.Initialize(m_pContext, m_pDevice, nullptr, nullptr, this,
+                          pStates, &m_Options, pPattern->form()->m_Transparency,
                           m_bDropObjects, pFormResource);
-        status.RenderObjectList(pPattern->m_pForm, &matrix);
+        status.RenderObjectList(pPattern->form(), &matrix);
         m_pDevice->RestoreState();
       }
     m_pDevice->RestoreState();
@@ -1157,8 +1156,8 @@
         start_x = FXSYS_round(mtPattern2Device.e) + col * width - clip_box.left;
         start_y = FXSYS_round(mtPattern2Device.f) + row * height - clip_box.top;
       } else {
-        FX_FLOAT orig_x = col * pPattern->m_XStep;
-        FX_FLOAT orig_y = row * pPattern->m_YStep;
+        FX_FLOAT orig_x = col * pPattern->x_step();
+        FX_FLOAT orig_y = row * pPattern->y_step();
         mtPattern2Device.Transform(orig_x, orig_y);
         start_x = FXSYS_round(orig_x + left_offset) - clip_box.left;
         start_y = FXSYS_round(orig_y + top_offset) - clip_box.top;
@@ -1171,13 +1170,12 @@
         uint32_t* dest_buf =
             (uint32_t*)(screen.GetBuffer() + screen.GetPitch() * start_y +
                         start_x * 4);
-        if (pPattern->m_bColored) {
+        if (pPattern->colored())
           *dest_buf = *src_buf;
-        } else {
+        else
           *dest_buf = (*(uint8_t*)src_buf << 24) | (fill_argb & 0xffffff);
-        }
       } else {
-        if (pPattern->m_bColored) {
+        if (pPattern->colored()) {
           screen.CompositeBitmap(start_x, start_y, width, height,
                                  pPatternBitmap, 0, 0);
         } else {
@@ -1192,22 +1190,21 @@
   m_pDevice->RestoreState();
   delete pPatternBitmap;
 }
+
 void CPDF_RenderStatus::DrawPathWithPattern(const CPDF_PathObject* pPathObj,
                                             const CFX_Matrix* pObj2Device,
                                             CPDF_Color* pColor,
                                             FX_BOOL bStroke) {
   CPDF_Pattern* pattern = pColor->GetPattern();
-  if (!pattern) {
+  if (!pattern)
     return;
-  }
-  if (pattern->m_PatternType == CPDF_Pattern::TILING) {
-    DrawTilingPattern(static_cast<CPDF_TilingPattern*>(pattern), pPathObj,
-                      pObj2Device, bStroke);
-  } else {
-    DrawShadingPattern(static_cast<CPDF_ShadingPattern*>(pattern), pPathObj,
-                       pObj2Device, bStroke);
-  }
+
+  if (CPDF_TilingPattern* pTilingPattern = pattern->AsTilingPattern())
+    DrawTilingPattern(pTilingPattern, pPathObj, pObj2Device, bStroke);
+  else if (CPDF_ShadingPattern* pShadingPattern = pattern->AsShadingPattern())
+    DrawShadingPattern(pShadingPattern, pPathObj, pObj2Device, bStroke);
 }
+
 void CPDF_RenderStatus::ProcessPathPattern(const CPDF_PathObject* pPathObj,
                                            const CFX_Matrix* pObj2Device,
                                            int& filltype,
diff --git a/core/fpdfapi/fpdf_render/fpdf_render_text.cpp b/core/fpdfapi/fpdf_render/fpdf_render_text.cpp
index ff8df76..acc70c0 100644
--- a/core/fpdfapi/fpdf_render/fpdf_render_text.cpp
+++ b/core/fpdfapi/fpdf_render/fpdf_render_text.cpp
@@ -10,7 +10,6 @@
 #include "core/fpdfapi/fpdf_font/cpdf_type3char.h"
 #include "core/fpdfapi/fpdf_font/cpdf_type3font.h"
 #include "core/fpdfapi/fpdf_font/include/cpdf_font.h"
-#include "core/fpdfapi/fpdf_page/cpdf_parseoptions.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_form.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_imageobject.h"
 #include "core/fpdfapi/fpdf_page/include/cpdf_pageobject.h"
diff --git a/core/fpdfapi/ipdf_rendermodule.h b/core/fpdfapi/ipdf_rendermodule.h
index 5082b19..b871c36 100644
--- a/core/fpdfapi/ipdf_rendermodule.h
+++ b/core/fpdfapi/ipdf_rendermodule.h
@@ -21,9 +21,6 @@
   virtual void ClearDocData(CPDF_DocRenderData* pDocRenderData) = 0;
 
   virtual CPDF_DocRenderData* GetRenderData() = 0;
-
-  virtual CPDF_PageRenderCache* CreatePageCache(CPDF_Page* pPage) = 0;
-  virtual void DestroyPageCache(CPDF_PageRenderCache* pCache) = 0;
 };
 
 #endif  // CORE_FPDFAPI_IPDF_RENDERMODULE_H_
diff --git a/core/fpdfdoc/doc_annot.cpp b/core/fpdfdoc/doc_annot.cpp
index 42d4a66..576c8b7 100644
--- a/core/fpdfdoc/doc_annot.cpp
+++ b/core/fpdfdoc/doc_annot.cpp
@@ -204,7 +204,7 @@
 
   CPDF_Form* pNewForm =
       new CPDF_Form(m_pList->GetDocument(), pPage->m_pResources, pStream);
-  pNewForm->ParseContent(nullptr, nullptr, nullptr, nullptr);
+  pNewForm->ParseContent(nullptr, nullptr, nullptr);
   m_APMap[pStream] = pNewForm;
   return pNewForm;
 }
diff --git a/core/fpdfdoc/doc_formcontrol.cpp b/core/fpdfdoc/doc_formcontrol.cpp
index 18e7330..aa6cf98 100644
--- a/core/fpdfdoc/doc_formcontrol.cpp
+++ b/core/fpdfdoc/doc_formcontrol.cpp
@@ -176,7 +176,7 @@
   matrix.Concat(*pMatrix);
   CPDF_Form form(m_pField->m_pForm->m_pDocument,
                  m_pField->m_pForm->m_pFormDict->GetDictBy("DR"), pStream);
-  form.ParseContent(NULL, NULL, NULL, NULL);
+  form.ParseContent(nullptr, nullptr, nullptr);
   CPDF_RenderContext context(pPage);
   context.AppendLayer(&form, &matrix);
   context.Render(pDevice, pOptions, nullptr);
diff --git a/fpdfsdk/fpdf_flatten.cpp b/fpdfsdk/fpdf_flatten.cpp
index e445d9a..fe81246 100644
--- a/fpdfsdk/fpdf_flatten.cpp
+++ b/fpdfsdk/fpdf_flatten.cpp
@@ -45,9 +45,8 @@
 void GetContentsRect(CPDF_Document* pDoc,
                      CPDF_Dictionary* pDict,
                      CPDF_RectArray* pRectArray) {
-  std::unique_ptr<CPDF_Page> pPDFPage(new CPDF_Page);
-  pPDFPage->Load(pDoc, pDict, FALSE);
-  pPDFPage->ParseContent(nullptr);
+  std::unique_ptr<CPDF_Page> pPDFPage(new CPDF_Page(pDoc, pDict, false));
+  pPDFPage->ParseContent();
 
   for (auto& pPageObject : *pPDFPage->GetPageObjectList()) {
     if (!pPageObject)
diff --git a/fpdfsdk/fpdfeditpage.cpp b/fpdfsdk/fpdfeditpage.cpp
index acd259c..c4273fe 100644
--- a/fpdfsdk/fpdfeditpage.cpp
+++ b/fpdfsdk/fpdfeditpage.cpp
@@ -100,9 +100,8 @@
       new CPDFXFA_Page((CPDFXFA_Document*)document, page_index);
   pPage->LoadPDFPage(pPageDict);
 #else   // PDF_ENABLE_XFA
-  CPDF_Page* pPage = new CPDF_Page;
-  pPage->Load(pDoc, pPageDict);
-  pPage->ParseContent(nullptr);
+  CPDF_Page* pPage = new CPDF_Page(pDoc, pPageDict, true);
+  pPage->ParseContent();
 #endif  // PDF_ENABLE_XFA
 
   return pPage;
diff --git a/fpdfsdk/fpdfview.cpp b/fpdfsdk/fpdfview.cpp
index dec1059..2283e94 100644
--- a/fpdfsdk/fpdfview.cpp
+++ b/fpdfsdk/fpdfview.cpp
@@ -502,10 +502,10 @@
 #else   // PDF_ENABLE_XFA
   CPDF_Dictionary* pDict = pDoc->GetPage(page_index);
   if (!pDict)
-    return NULL;
-  CPDF_Page* pPage = new CPDF_Page;
-  pPage->Load(pDoc, pDict);
-  pPage->ParseContent(nullptr);
+    return nullptr;
+
+  CPDF_Page* pPage = new CPDF_Page(pDoc, pDict, true);
+  pPage->ParseContent();
   return pPage;
 #endif  // PDF_ENABLE_XFA
 }
@@ -958,8 +958,8 @@
   CPDF_Dictionary* pDict = pDoc->GetPage(page_index);
   if (!pDict)
     return FALSE;
-  CPDF_Page page;
-  page.Load(pDoc, pDict);
+
+  CPDF_Page page(pDoc, pDict, true);
   *width = page.GetPageWidth();
   *height = page.GetPageHeight();
 #endif  // PDF_ENABLE_XFA
diff --git a/fpdfsdk/fpdfxfa/fpdfxfa_page.cpp b/fpdfsdk/fpdfxfa/fpdfxfa_page.cpp
index 8c0d6bb..22c8f99 100644
--- a/fpdfsdk/fpdfxfa/fpdfxfa_page.cpp
+++ b/fpdfsdk/fpdfxfa/fpdfxfa_page.cpp
@@ -46,9 +46,8 @@
     return FALSE;
 
   if (!m_pPDFPage || m_pPDFPage->m_pFormDict != pDict) {
-    m_pPDFPage.reset(new CPDF_Page);
-    m_pPDFPage->Load(pPDFDoc, pDict);
-    m_pPDFPage->ParseContent(nullptr);
+    m_pPDFPage.reset(new CPDF_Page(pPDFDoc, pDict, true));
+    m_pPDFPage->ParseContent();
   }
   return TRUE;
 }
@@ -95,9 +94,8 @@
   if (!m_pDocument || m_iPageIndex < 0 || !pageDict)
     return FALSE;
 
-  m_pPDFPage.reset(new CPDF_Page());
-  m_pPDFPage->Load(m_pDocument->GetPDFDoc(), pageDict);
-  m_pPDFPage->ParseContent(nullptr);
+  m_pPDFPage.reset(new CPDF_Page(m_pDocument->GetPDFDoc(), pageDict, true));
+  m_pPDFPage->ParseContent();
   return TRUE;
 }
 
diff --git a/fpdfsdk/javascript/Document.cpp b/fpdfsdk/javascript/Document.cpp
index fa2f7ae..12d8c2d 100644
--- a/fpdfsdk/javascript/Document.cpp
+++ b/fpdfsdk/javascript/Document.cpp
@@ -1348,9 +1348,8 @@
   if (!pPageDict)
     return FALSE;
 
-  CPDF_Page page;
-  page.Load(pDocument, pPageDict);
-  page.ParseContent(nullptr);
+  CPDF_Page page(pDocument, pPageDict, true);
+  page.ParseContent();
 
   int nWords = 0;
   CFX_WideString swRet;
@@ -1404,9 +1403,8 @@
   if (!pPageDict)
     return FALSE;
 
-  CPDF_Page page;
-  page.Load(pDocument, pPageDict);
-  page.ParseContent(nullptr);
+  CPDF_Page page(pDocument, pPageDict, true);
+  page.ParseContent();
 
   int nWords = 0;
   for (auto& pPageObj : *page.GetPageObjectList()) {
diff --git a/pdfium.gyp b/pdfium.gyp
index 48bc82d..2890c30 100644
--- a/pdfium.gyp
+++ b/pdfium.gyp
@@ -392,8 +392,6 @@
         'core/fpdfapi/fpdf_page/cpdf_pageobjectholder.cpp',
         'core/fpdfapi/fpdf_page/cpdf_pageobjectlist.cpp',
         'core/fpdfapi/fpdf_page/cpdf_pageobjectlist.h',
-        'core/fpdfapi/fpdf_page/cpdf_parseoptions.cpp',
-        'core/fpdfapi/fpdf_page/cpdf_parseoptions.h',
         'core/fpdfapi/fpdf_page/cpdf_pathobject.cpp',
         'core/fpdfapi/fpdf_page/cpdf_pattern.cpp',
         'core/fpdfapi/fpdf_page/cpdf_pattern.h',