Remove PageObject's m_Type and add As<Type> functions

For CPDF_PageObject and its subclasses, remove m_Type and use GetType() instead. Also, add As<Type> functions to avoid casting all over the places.

BUG=pdfium:397
R=thestig@chromium.org

Review URL: https://codereview.chromium.org/1709393002 .
diff --git a/core/include/fpdfapi/fpdf_pageobj.h b/core/include/fpdfapi/fpdf_pageobj.h
index 9190fd9..efb8e29 100644
--- a/core/include/fpdfapi/fpdf_pageobj.h
+++ b/core/include/fpdfapi/fpdf_pageobj.h
@@ -288,13 +288,29 @@
     FORM,
   };
 
-  static CPDF_PageObject* Create(int type);
+  static CPDF_PageObject* Create(Type type);
   virtual ~CPDF_PageObject();
 
   CPDF_PageObject* Clone() const;
   void Copy(const CPDF_PageObject* pSrcObject);
 
+  virtual Type GetType() const = 0;
   virtual void Transform(const CFX_Matrix& matrix) = 0;
+  virtual bool IsText() const { return false; }
+  virtual bool IsPath() const { return false; }
+  virtual bool IsImage() const { return false; }
+  virtual bool IsShading() const { return false; }
+  virtual bool IsForm() const { return false; }
+  virtual CPDF_TextObject* AsText() { return nullptr; }
+  virtual const CPDF_TextObject* AsText() const { return nullptr; }
+  virtual CPDF_PathObject* AsPath() { return nullptr; }
+  virtual const CPDF_PathObject* AsPath() const { return nullptr; }
+  virtual CPDF_ImageObject* AsImage() { return nullptr; }
+  virtual const CPDF_ImageObject* AsImage() const { return nullptr; }
+  virtual CPDF_ShadingObject* AsShading() { return nullptr; }
+  virtual const CPDF_ShadingObject* AsShading() const { return nullptr; }
+  virtual CPDF_FormObject* AsForm() { return nullptr; }
+  virtual const CPDF_FormObject* AsForm() const { return nullptr; }
 
   void RemoveClipPath();
   void AppendClipPath(CPDF_Path path, int type, FX_BOOL bAutoMerge);
@@ -304,7 +320,6 @@
   void SetColorState(CPDF_ColorState state) { m_ColorState = state; }
   FX_RECT GetBBox(const CFX_Matrix* pMatrix) const;
 
-  const Type m_Type;
   FX_FLOAT m_Left;
   FX_FLOAT m_Right;
   FX_FLOAT m_Top;
@@ -315,7 +330,6 @@
   virtual void CopyData(const CPDF_PageObject* pSrcObject) = 0;
 
   void RecalcBBox();
-  CPDF_PageObject(Type type) : m_Type(type) {}
 };
 
 struct CPDF_TextObjectItem {
@@ -329,6 +343,13 @@
   CPDF_TextObject();
   ~CPDF_TextObject() override;
 
+  // CPDF_PageObject:
+  Type GetType() const override { return TEXT; };
+  void Transform(const CFX_Matrix& matrix) override;
+  bool IsText() const override { return true; };
+  CPDF_TextObject* AsText() override { return this; };
+  const CPDF_TextObject* AsText() const override { return this; };
+
   int CountItems() const { return m_nChars; }
 
   void GetItemInfo(int index, CPDF_TextObjectItem* pInfo) const;
@@ -365,9 +386,6 @@
 
   void SetTextState(CPDF_TextState TextState);
 
-  // CPDF_PageObject:
-  void Transform(const CFX_Matrix& matrix) override;
-
   void CalcCharPos(FX_FLOAT* pPosArray) const;
 
   void SetData(int nChars,
@@ -411,10 +429,15 @@
 
 class CPDF_PathObject : public CPDF_PageObject {
  public:
-  CPDF_PathObject() : CPDF_PageObject(PATH) {}
+  CPDF_PathObject() {}
   ~CPDF_PathObject() override {}
 
+  // CPDF_PageObject:
+  Type GetType() const override { return PATH; };
   void Transform(const CFX_Matrix& maxtrix) override;
+  bool IsPath() const override { return true; };
+  CPDF_PathObject* AsPath() override { return this; };
+  const CPDF_PathObject* AsPath() const override { return this; };
 
   void SetGraphState(CPDF_GraphState GraphState);
 
@@ -437,7 +460,12 @@
   CPDF_ImageObject();
   ~CPDF_ImageObject() override;
 
+  // CPDF_PageObject:
+  Type GetType() const override { return IMAGE; };
   void Transform(const CFX_Matrix& matrix) override;
+  bool IsImage() const override { return true; };
+  CPDF_ImageObject* AsImage() override { return this; };
+  const CPDF_ImageObject* AsImage() const override { return this; };
 
   CPDF_Image* m_pImage;
 
@@ -454,24 +482,34 @@
   CPDF_ShadingObject();
   ~CPDF_ShadingObject() override;
 
-  CPDF_ShadingPattern* m_pShading;
-
-  CFX_Matrix m_Matrix;
-
+  // CPDF_PageObject:
+  Type GetType() const override { return SHADING; };
   void Transform(const CFX_Matrix& matrix) override;
+  bool IsShading() const override { return true; };
+  CPDF_ShadingObject* AsShading() override { return this; };
+  const CPDF_ShadingObject* AsShading() const override { return this; };
 
   void CalcBoundingBox();
 
+  CPDF_ShadingPattern* m_pShading;
+  CFX_Matrix m_Matrix;
+
  protected:
   void CopyData(const CPDF_PageObject* pSrcObject) override;
 };
 
 class CPDF_FormObject : public CPDF_PageObject {
  public:
-  CPDF_FormObject() : CPDF_PageObject(FORM), m_pForm(nullptr) {}
+  CPDF_FormObject() : m_pForm(nullptr) {}
   ~CPDF_FormObject() override;
 
+  // CPDF_PageObject:
+  Type GetType() const override { return FORM; };
   void Transform(const CFX_Matrix& matrix) override;
+  bool IsForm() const override { return true; };
+  CPDF_FormObject* AsForm() override { return this; };
+  const CPDF_FormObject* AsForm() const override { return this; };
+
   void CalcBoundingBox();
 
   CPDF_Form* m_pForm;
diff --git a/core/src/fpdfapi/fpdf_edit/fpdf_edit_content.cpp b/core/src/fpdfapi/fpdf_edit/fpdf_edit_content.cpp
index ef0344c..77c58f0 100644
--- a/core/src/fpdfapi/fpdf_edit/fpdf_edit_content.cpp
+++ b/core/src/fpdfapi/fpdf_edit/fpdf_edit_content.cpp
@@ -31,10 +31,10 @@
   CPDF_Dictionary* pPageDict = m_pPage->m_pFormDict;
   for (int i = 0; i < m_pageObjects.GetSize(); ++i) {
     CPDF_PageObject* pPageObj = m_pageObjects[i];
-    if (!pPageObj || pPageObj->m_Type != CPDF_PageObject::IMAGE) {
+    if (!pPageObj || !pPageObj->IsImage()) {
       continue;
     }
-    ProcessImage(buf, (CPDF_ImageObject*)pPageObj);
+    ProcessImage(buf, pPageObj->AsImage());
   }
   CPDF_Object* pContent =
       pPageDict ? pPageDict->GetElementValue("Contents") : NULL;
diff --git a/core/src/fpdfapi/fpdf_page/fpdf_page.cpp b/core/src/fpdfapi/fpdf_page/fpdf_page.cpp
index b1de6d6..0bcd15b 100644
--- a/core/src/fpdfapi/fpdf_page/fpdf_page.cpp
+++ b/core/src/fpdfapi/fpdf_page/fpdf_page.cpp
@@ -12,7 +12,7 @@
 #include "core/include/fpdfapi/fpdf_page.h"
 #include "third_party/base/stl_util.h"
 
-CPDF_PageObject* CPDF_PageObject::Create(int type) {
+CPDF_PageObject* CPDF_PageObject::Create(Type type) {
   switch (type) {
     case TEXT:
       return new CPDF_TextObject;
@@ -29,12 +29,12 @@
 }
 CPDF_PageObject::~CPDF_PageObject() {}
 CPDF_PageObject* CPDF_PageObject::Clone() const {
-  CPDF_PageObject* pObj = Create(m_Type);
+  CPDF_PageObject* pObj = Create(GetType());
   pObj->Copy(this);
   return pObj;
 }
 void CPDF_PageObject::Copy(const CPDF_PageObject* pSrc) {
-  if (m_Type != pSrc->m_Type) {
+  if (GetType() != pSrc->GetType()) {
     return;
   }
   CopyData(pSrc);
@@ -56,7 +56,7 @@
   m_ClipPath.SetNull();
 }
 void CPDF_PageObject::RecalcBBox() {
-  switch (m_Type) {
+  switch (GetType()) {
     case TEXT:
       ((CPDF_TextObject*)this)->RecalcPositionData();
       break;
@@ -93,8 +93,7 @@
 }
 
 CPDF_TextObject::CPDF_TextObject()
-    : CPDF_PageObject(TEXT),
-      m_PosX(0),
+    : m_PosX(0),
       m_PosY(0),
       m_nChars(0),
       m_pCharCodes(nullptr),
@@ -611,8 +610,7 @@
   CalcPositionData(nullptr, nullptr, 0);
 }
 
-CPDF_ShadingObject::CPDF_ShadingObject()
-    : CPDF_PageObject(SHADING), m_pShading(nullptr) {}
+CPDF_ShadingObject::CPDF_ShadingObject() : m_pShading(nullptr) {}
 
 CPDF_ShadingObject::~CPDF_ShadingObject() {}
 
diff --git a/core/src/fpdfapi/fpdf_page/fpdf_page_image.cpp b/core/src/fpdfapi/fpdf_page/fpdf_page_image.cpp
index 01322b5..93c0aca 100644
--- a/core/src/fpdfapi/fpdf_page/fpdf_page_image.cpp
+++ b/core/src/fpdfapi/fpdf_page/fpdf_page_image.cpp
@@ -9,8 +9,7 @@
 #include "core/include/fpdfapi/fpdf_page.h"
 #include "core/include/fpdfapi/fpdf_pageobj.h"
 
-CPDF_ImageObject::CPDF_ImageObject()
-    : CPDF_PageObject(IMAGE), m_pImage(nullptr) {}
+CPDF_ImageObject::CPDF_ImageObject() : m_pImage(nullptr) {}
 CPDF_ImageObject::~CPDF_ImageObject() {
   if (!m_pImage) {
     return;
diff --git a/core/src/fpdfapi/fpdf_page/fpdf_page_parser_old.cpp b/core/src/fpdfapi/fpdf_page/fpdf_page_parser_old.cpp
index 20f0c39..02e3617 100644
--- a/core/src/fpdfapi/fpdf_page/fpdf_page_parser_old.cpp
+++ b/core/src/fpdfapi/fpdf_page/fpdf_page_parser_old.cpp
@@ -853,7 +853,7 @@
           continue;
         }
         CPDF_Path ClipPath = pObj->m_ClipPath.GetPath(0);
-        if (!ClipPath.IsRect() || pObj->m_Type == CPDF_PageObject::SHADING) {
+        if (!ClipPath.IsRect() || pObj->IsShading()) {
           continue;
         }
         CFX_FloatRect old_rect(ClipPath.GetPointX(0), ClipPath.GetPointY(0),
diff --git a/core/src/fpdfapi/fpdf_render/fpdf_render.cpp b/core/src/fpdfapi/fpdf_render/fpdf_render.cpp
index 8e205df..a470e94 100644
--- a/core/src/fpdfapi/fpdf_render/fpdf_render.cpp
+++ b/core/src/fpdfapi/fpdf_render/fpdf_render.cpp
@@ -306,8 +306,8 @@
   if (ProcessTransparency(pObj, pObj2Device))
     return FALSE;
 
-  if (pObj->m_Type == CPDF_PageObject::IMAGE) {
-    m_pObjectRenderer.reset(IPDF_ObjectRenderer::Create(pObj->m_Type));
+  if (pObj->IsImage()) {
+    m_pObjectRenderer.reset(IPDF_ObjectRenderer::Create());
     if (!m_pObjectRenderer->Start(this, pObj, pObj2Device, FALSE)) {
       if (!m_pObjectRenderer->m_Result)
         DrawObjWithBackground(pObj, pObj2Device);
@@ -321,12 +321,10 @@
   return FALSE;
 }
 
-IPDF_ObjectRenderer* IPDF_ObjectRenderer::Create(int type) {
-  if (type != CPDF_PageObject::IMAGE) {
-    return NULL;
-  }
+IPDF_ObjectRenderer* IPDF_ObjectRenderer::Create() {
   return new CPDF_ImageRenderer;
 }
+
 FX_BOOL CPDF_RenderStatus::GetObjectClippedRect(const CPDF_PageObject* pObj,
                                                 const CFX_Matrix* pObj2Device,
                                                 FX_BOOL bLogical,
@@ -374,21 +372,21 @@
 void CPDF_RenderStatus::ProcessObjectNoClip(const CPDF_PageObject* pObj,
                                             const CFX_Matrix* pObj2Device) {
   FX_BOOL bRet = FALSE;
-  switch (pObj->m_Type) {
+  switch (pObj->GetType()) {
     case CPDF_PageObject::TEXT:
-      bRet = ProcessText((CPDF_TextObject*)pObj, pObj2Device, NULL);
+      bRet = ProcessText(pObj->AsText(), pObj2Device, NULL);
       break;
     case CPDF_PageObject::PATH:
-      bRet = ProcessPath((CPDF_PathObject*)pObj, pObj2Device);
+      bRet = ProcessPath(pObj->AsPath(), pObj2Device);
       break;
     case CPDF_PageObject::IMAGE:
-      bRet = ProcessImage((CPDF_ImageObject*)pObj, pObj2Device);
+      bRet = ProcessImage(pObj->AsImage(), pObj2Device);
       break;
     case CPDF_PageObject::SHADING:
-      bRet = ProcessShading((CPDF_ShadingObject*)pObj, pObj2Device);
+      bRet = ProcessShading(pObj->AsShading(), pObj2Device);
       break;
     case CPDF_PageObject::FORM:
-      bRet = ProcessForm((CPDF_FormObject*)pObj, pObj2Device);
+      bRet = ProcessForm(pObj->AsForm(), pObj2Device);
       break;
   }
   if (!bRet) {
@@ -398,15 +396,15 @@
 FX_BOOL CPDF_RenderStatus::DrawObjWithBlend(const CPDF_PageObject* pObj,
                                             const CFX_Matrix* pObj2Device) {
   FX_BOOL bRet = FALSE;
-  switch (pObj->m_Type) {
+  switch (pObj->GetType()) {
     case CPDF_PageObject::PATH:
-      bRet = ProcessPath((CPDF_PathObject*)pObj, pObj2Device);
+      bRet = ProcessPath(pObj->AsPath(), pObj2Device);
       break;
     case CPDF_PageObject::IMAGE:
-      bRet = ProcessImage((CPDF_ImageObject*)pObj, pObj2Device);
+      bRet = ProcessImage(pObj->AsImage(), pObj2Device);
       break;
     case CPDF_PageObject::FORM:
-      bRet = ProcessForm((CPDF_FormObject*)pObj, pObj2Device);
+      bRet = ProcessForm(pObj->AsForm(), pObj2Device);
       break;
     default:
       break;
@@ -425,7 +423,7 @@
     return;
   }
   int res = 300;
-  if (pObj->m_Type == CPDF_PageObject::IMAGE &&
+  if (pObj->IsImage() &&
       m_pDevice->GetDeviceCaps(FXDC_DEVICE_CLASS) == FXDC_PRINTER) {
     res = 0;
   }
@@ -437,8 +435,8 @@
   matrix.Concat(*buffer.GetMatrix());
   GetScaledMatrix(matrix);
   CPDF_Dictionary* pFormResource = NULL;
-  if (pObj->m_Type == CPDF_PageObject::FORM) {
-    CPDF_FormObject* pFormObj = (CPDF_FormObject*)pObj;
+  if (pObj->IsForm()) {
+    const CPDF_FormObject* pFormObj = pObj->AsForm();
     if (pFormObj->m_pForm && pFormObj->m_pForm->m_pFormDict) {
       pFormResource = pFormObj->m_pForm->m_pFormDict->GetDictBy("Resources");
     }
@@ -450,7 +448,7 @@
   status.RenderSingleObject(pObj, &matrix);
   buffer.OutputToDevice();
 }
-FX_BOOL CPDF_RenderStatus::ProcessForm(CPDF_FormObject* pFormObj,
+FX_BOOL CPDF_RenderStatus::ProcessForm(const CPDF_FormObject* pFormObj,
                                        const CFX_Matrix* pObj2Device) {
   CPDF_Dictionary* pOC = pFormObj->m_pForm->m_pFormDict->GetDictBy("OC");
   if (pOC && m_Options.m_pOCContext &&
@@ -483,7 +481,7 @@
   }
   return TRUE;
 }
-FX_BOOL CPDF_RenderStatus::ProcessPath(CPDF_PathObject* pPathObj,
+FX_BOOL CPDF_RenderStatus::ProcessPath(const CPDF_PathObject* pPathObj,
                                        const CFX_Matrix* pObj2Device) {
   int FillType = pPathObj->m_FillType;
   FX_BOOL bStroke = pPathObj->m_bStroke;
@@ -691,7 +689,7 @@
                         fill_mode);
   }
 }
-FX_BOOL CPDF_RenderStatus::SelectClipPath(CPDF_PathObject* pPathObj,
+FX_BOOL CPDF_RenderStatus::SelectClipPath(const CPDF_PathObject* pPathObj,
                                           const CFX_Matrix* pObj2Device,
                                           FX_BOOL bStroke) {
   CFX_Matrix path_matrix = pPathObj->m_Matrix;
@@ -721,8 +719,8 @@
   CPDF_Dictionary* pSMaskDict =
       pGeneralState ? ToDictionary(pGeneralState->m_pSoftMask) : NULL;
   if (pSMaskDict) {
-    if (pPageObj->m_Type == CPDF_PageObject::IMAGE &&
-        ((CPDF_ImageObject*)pPageObj)->m_pImage->GetDict()->KeyExist("SMask")) {
+    if (pPageObj->IsImage() &&
+        pPageObj->AsImage()->m_pImage->GetDict()->KeyExist("SMask")) {
       pSMaskDict = NULL;
     }
   }
@@ -730,8 +728,8 @@
   FX_FLOAT group_alpha = 1.0f;
   int Transparency = m_Transparency;
   FX_BOOL bGroupTransparent = FALSE;
-  if (pPageObj->m_Type == CPDF_PageObject::FORM) {
-    CPDF_FormObject* pFormObj = (CPDF_FormObject*)pPageObj;
+  if (pPageObj->IsForm()) {
+    const CPDF_FormObject* pFormObj = pPageObj->AsForm();
     const CPDF_GeneralStateData* pStateData =
         pFormObj->m_GeneralState.GetObject();
     if (pStateData) {
@@ -749,22 +747,20 @@
       !(m_pDevice->GetDeviceCaps(FXDC_RENDER_CAPS) & FXRC_SOFT_CLIP)) {
     bTextClip = TRUE;
   }
-  if ((m_Options.m_Flags & RENDER_OVERPRINT) &&
-      pPageObj->m_Type == CPDF_PageObject::IMAGE && pGeneralState &&
-      pGeneralState->m_FillOP && pGeneralState->m_StrokeOP) {
+  if ((m_Options.m_Flags & RENDER_OVERPRINT) && pPageObj->IsImage() &&
+      pGeneralState && pGeneralState->m_FillOP && pGeneralState->m_StrokeOP) {
     CPDF_Document* pDocument = NULL;
     CPDF_Page* pPage = NULL;
     if (m_pContext->GetPageCache()) {
       pPage = m_pContext->GetPageCache()->GetPage();
       pDocument = pPage->m_pDocument;
     } else {
-      pDocument = ((CPDF_ImageObject*)pPageObj)->m_pImage->GetDocument();
+      pDocument = pPageObj->AsImage()->m_pImage->GetDocument();
     }
     CPDF_Dictionary* pPageResources = pPage ? pPage->m_pPageResources : NULL;
-    CPDF_Object* pCSObj = ((CPDF_ImageObject*)pPageObj)
-                              ->m_pImage->GetStream()
-                              ->GetDict()
-                              ->GetElementValue("ColorSpace");
+    CPDF_Object* pCSObj =
+        pPageObj->AsImage()->m_pImage->GetStream()->GetDict()->GetElementValue(
+            "ColorSpace");
     CPDF_ColorSpace* pColorSpace =
         pDocument->LoadColorSpace(pCSObj, pPageResources);
     if (pColorSpace) {
@@ -870,7 +866,7 @@
     bitmap->MultiplyAlpha((int32_t)(group_alpha * 255));
   }
   Transparency = m_Transparency;
-  if (pPageObj->m_Type == CPDF_PageObject::FORM) {
+  if (pPageObj->IsForm()) {
     Transparency |= PDFTRANS_GROUP;
   }
   CompositeDIBitmap(bitmap, rect.left, rect.top, 0, 255, blend_type,
@@ -1088,13 +1084,12 @@
                 pCurObj, &m_pCurrentLayer->m_Matrix, pPause)) {
           return;
         }
-        if (pCurObj->m_Type == CPDF_PageObject::IMAGE &&
+        if (pCurObj->IsImage() &&
             m_pRenderStatus->m_Options.m_Flags & RENDER_LIMITEDIMAGECACHE) {
           m_pContext->GetPageCache()->CacheOptimization(
               m_pRenderStatus->m_Options.m_dwLimitCacheSize);
         }
-        if (pCurObj->m_Type == CPDF_PageObject::FORM ||
-            pCurObj->m_Type == CPDF_PageObject::SHADING) {
+        if (pCurObj->IsForm() || pCurObj->IsShading()) {
           nObjsToGo = 0;
         } else {
           --nObjsToGo;
diff --git a/core/src/fpdfapi/fpdf_render/fpdf_render_image.cpp b/core/src/fpdfapi/fpdf_render/fpdf_render_image.cpp
index 2bd3e91..acfc083 100644
--- a/core/src/fpdfapi/fpdf_render/fpdf_render_image.cpp
+++ b/core/src/fpdfapi/fpdf_render/fpdf_render_image.cpp
@@ -17,7 +17,7 @@
 #include "core/include/fxge/fx_ge.h"
 #include "core/src/fpdfapi/fpdf_page/pageint.h"
 
-FX_BOOL CPDF_RenderStatus::ProcessImage(CPDF_ImageObject* pImageObj,
+FX_BOOL CPDF_RenderStatus::ProcessImage(const CPDF_ImageObject* pImageObj,
                                         const CFX_Matrix* pObj2Device) {
   CPDF_ImageRenderer render;
   if (render.Start(this, pImageObj, pObj2Device, m_bStdCS, m_curBlend)) {
diff --git a/core/src/fpdfapi/fpdf_render/fpdf_render_pattern.cpp b/core/src/fpdfapi/fpdf_render/fpdf_render_pattern.cpp
index 7284b62..f4ade7d 100644
--- a/core/src/fpdfapi/fpdf_render/fpdf_render_pattern.cpp
+++ b/core/src/fpdfapi/fpdf_render/fpdf_render_pattern.cpp
@@ -912,19 +912,19 @@
   buffer.OutputToDevice();
 }
 void CPDF_RenderStatus::DrawShadingPattern(CPDF_ShadingPattern* pattern,
-                                           CPDF_PageObject* pPageObj,
+                                           const CPDF_PageObject* pPageObj,
                                            const CFX_Matrix* pObj2Device,
                                            FX_BOOL bStroke) {
   if (!pattern->Load()) {
     return;
   }
   m_pDevice->SaveState();
-  if (pPageObj->m_Type == CPDF_PageObject::PATH) {
-    if (!SelectClipPath((CPDF_PathObject*)pPageObj, pObj2Device, bStroke)) {
+  if (pPageObj->IsPath()) {
+    if (!SelectClipPath(pPageObj->AsPath(), pObj2Device, bStroke)) {
       m_pDevice->RestoreState();
       return;
     }
-  } else if (pPageObj->m_Type == CPDF_PageObject::IMAGE) {
+  } else if (pPageObj->IsImage()) {
     FX_RECT rect = pPageObj->GetBBox(pObj2Device);
     m_pDevice->SetClip_Rect(&rect);
   } else {
@@ -943,7 +943,7 @@
               m_Options.m_ColorMode == RENDER_COLOR_ALPHA);
   m_pDevice->RestoreState();
 }
-FX_BOOL CPDF_RenderStatus::ProcessShading(CPDF_ShadingObject* pShadingObj,
+FX_BOOL CPDF_RenderStatus::ProcessShading(const CPDF_ShadingObject* pShadingObj,
                                           const CFX_Matrix* pObj2Device) {
   FX_RECT rect = pShadingObj->GetBBox(pObj2Device);
   FX_RECT clip_box = m_pDevice->GetClipBox();
@@ -994,19 +994,19 @@
   return pBitmap;
 }
 void CPDF_RenderStatus::DrawTilingPattern(CPDF_TilingPattern* pPattern,
-                                          CPDF_PageObject* pPageObj,
+                                          const CPDF_PageObject* pPageObj,
                                           const CFX_Matrix* pObj2Device,
                                           FX_BOOL bStroke) {
   if (!pPattern->Load()) {
     return;
   }
   m_pDevice->SaveState();
-  if (pPageObj->m_Type == CPDF_PageObject::PATH) {
-    if (!SelectClipPath((CPDF_PathObject*)pPageObj, pObj2Device, bStroke)) {
+  if (pPageObj->IsPath()) {
+    if (!SelectClipPath(pPageObj->AsPath(), pObj2Device, bStroke)) {
       m_pDevice->RestoreState();
       return;
     }
-  } else if (pPageObj->m_Type == CPDF_PageObject::IMAGE) {
+  } else if (pPageObj->IsImage()) {
     FX_RECT rect = pPageObj->GetBBox(pObj2Device);
     m_pDevice->SetClip_Rect(&rect);
   } else {
@@ -1179,7 +1179,7 @@
   m_pDevice->RestoreState();
   delete pPatternBitmap;
 }
-void CPDF_RenderStatus::DrawPathWithPattern(CPDF_PathObject* pPathObj,
+void CPDF_RenderStatus::DrawPathWithPattern(const CPDF_PathObject* pPathObj,
                                             const CFX_Matrix* pObj2Device,
                                             CPDF_Color* pColor,
                                             FX_BOOL bStroke) {
@@ -1195,7 +1195,7 @@
                        pObj2Device, bStroke);
   }
 }
-void CPDF_RenderStatus::ProcessPathPattern(CPDF_PathObject* pPathObj,
+void CPDF_RenderStatus::ProcessPathPattern(const CPDF_PathObject* pPathObj,
                                            const CFX_Matrix* pObj2Device,
                                            int& filltype,
                                            FX_BOOL& bStroke) {
diff --git a/core/src/fpdfapi/fpdf_render/fpdf_render_text.cpp b/core/src/fpdfapi/fpdf_render/fpdf_render_text.cpp
index d2faac3..769ee05 100644
--- a/core/src/fpdfapi/fpdf_render/fpdf_render_text.cpp
+++ b/core/src/fpdfapi/fpdf_render/fpdf_render_text.cpp
@@ -318,10 +318,9 @@
   }
   if (m_pForm->GetPageObjectList()->size() == 1 && !m_bColored) {
     auto& pPageObj = m_pForm->GetPageObjectList()->front();
-    if (pPageObj->m_Type == CPDF_PageObject::IMAGE) {
-      CPDF_ImageObject* pImage = static_cast<CPDF_ImageObject*>(pPageObj.get());
-      m_ImageMatrix = pImage->m_Matrix;
-      const CFX_DIBSource* pSource = pImage->m_pImage->LoadDIBSource();
+    if (pPageObj->IsImage()) {
+      const CFX_DIBSource* pSource =
+          pPageObj->AsImage()->m_pImage->LoadDIBSource();
       if (pSource) {
         m_pBitmap = pSource->Clone();
         delete pSource;
diff --git a/core/src/fpdfapi/fpdf_render/render_int.h b/core/src/fpdfapi/fpdf_render/render_int.h
index 9a262ea..5af5909 100644
--- a/core/src/fpdfapi/fpdf_render/render_int.h
+++ b/core/src/fpdfapi/fpdf_render/render_int.h
@@ -94,7 +94,7 @@
 
 class IPDF_ObjectRenderer {
  public:
-  static IPDF_ObjectRenderer* Create(int type);
+  static IPDF_ObjectRenderer* Create();
   virtual ~IPDF_ObjectRenderer() {}
   virtual FX_BOOL Start(CPDF_RenderStatus* pRenderStatus,
                         const CPDF_PageObject* pObj,
@@ -151,27 +151,28 @@
                              const CFX_Matrix* pObj2Device);
   FX_BOOL DrawObjWithBlend(const CPDF_PageObject* pObj,
                            const CFX_Matrix* pObj2Device);
-  FX_BOOL ProcessPath(CPDF_PathObject* pPathObj, const CFX_Matrix* pObj2Device);
-  void ProcessPathPattern(CPDF_PathObject* pPathObj,
+  FX_BOOL ProcessPath(const CPDF_PathObject* pPathObj,
+                      const CFX_Matrix* pObj2Device);
+  void ProcessPathPattern(const CPDF_PathObject* pPathObj,
                           const CFX_Matrix* pObj2Device,
                           int& filltype,
                           FX_BOOL& bStroke);
-  void DrawPathWithPattern(CPDF_PathObject* pPathObj,
+  void DrawPathWithPattern(const CPDF_PathObject* pPathObj,
                            const CFX_Matrix* pObj2Device,
                            CPDF_Color* pColor,
                            FX_BOOL bStroke);
   void DrawTilingPattern(CPDF_TilingPattern* pPattern,
-                         CPDF_PageObject* pPageObj,
+                         const CPDF_PageObject* pPageObj,
                          const CFX_Matrix* pObj2Device,
                          FX_BOOL bStroke);
   void DrawShadingPattern(CPDF_ShadingPattern* pPattern,
-                          CPDF_PageObject* pPageObj,
+                          const CPDF_PageObject* pPageObj,
                           const CFX_Matrix* pObj2Device,
                           FX_BOOL bStroke);
-  FX_BOOL SelectClipPath(CPDF_PathObject* pPathObj,
+  FX_BOOL SelectClipPath(const CPDF_PathObject* pPathObj,
                          const CFX_Matrix* pObj2Device,
                          FX_BOOL bStroke);
-  FX_BOOL ProcessImage(CPDF_ImageObject* pImageObj,
+  FX_BOOL ProcessImage(const CPDF_ImageObject* pImageObj,
                        const CFX_Matrix* pObj2Device);
   FX_BOOL OutputBitmapAlpha(CPDF_ImageObject* pImageObj,
                             const CFX_Matrix* pImage2Device);
@@ -190,7 +191,7 @@
                          int bitmap_alpha,
                          int blend_mode,
                          int bIsolated);
-  FX_BOOL ProcessShading(CPDF_ShadingObject* pShadingObj,
+  FX_BOOL ProcessShading(const CPDF_ShadingObject* pShadingObj,
                          const CFX_Matrix* pObj2Device);
   void DrawShading(CPDF_ShadingPattern* pPattern,
                    CFX_Matrix* pMatrix,
@@ -209,7 +210,8 @@
                                const CFX_Matrix* pTextMatrix,
                                FX_BOOL bFill,
                                FX_BOOL bStroke);
-  FX_BOOL ProcessForm(CPDF_FormObject* pFormObj, const CFX_Matrix* pObj2Device);
+  FX_BOOL ProcessForm(const CPDF_FormObject* pFormObj,
+                      const CFX_Matrix* pObj2Device);
   CFX_DIBitmap* GetBackdrop(const CPDF_PageObject* pObj,
                             const FX_RECT& rect,
                             int& left,
diff --git a/core/src/fpdftext/fpdf_text_int.cpp b/core/src/fpdftext/fpdf_text_int.cpp
index 8972f84..7858fa0 100644
--- a/core/src/fpdftext/fpdf_text_int.cpp
+++ b/core/src/fpdftext/fpdf_text_int.cpp
@@ -765,7 +765,7 @@
     return -1;
 
   for (auto& pPageObj : *m_pPage->GetPageObjectList()) {
-    if (!pPageObj || pPageObj->m_Type != CPDF_PageObject::TEXT)
+    if (!pPageObj || !pPageObj->IsText())
       continue;
 
     int32_t minH =
@@ -846,13 +846,12 @@
   const CPDF_PageObjectList* pObjList = m_pPage->GetPageObjectList();
   for (auto it = pObjList->begin(); it != pObjList->end(); ++it) {
     if (CPDF_PageObject* pObj = it->get()) {
-      if (pObj->m_Type == CPDF_PageObject::TEXT) {
+      if (pObj->IsText()) {
         CFX_Matrix matrix;
-        ProcessTextObject(static_cast<CPDF_TextObject*>(pObj), matrix, pObjList,
-                          it);
-      } else if (pObj->m_Type == CPDF_PageObject::FORM) {
+        ProcessTextObject(pObj->AsText(), matrix, pObjList, it);
+      } else if (pObj->IsForm()) {
         CFX_Matrix formMatrix(1, 0, 0, 1, 0, 0);
-        ProcessFormObject(static_cast<CPDF_FormObject*>(pObj), formMatrix);
+        ProcessFormObject(pObj->AsForm(), formMatrix);
       }
     }
   }
@@ -875,12 +874,10 @@
 
   for (auto it = pObjectList->begin(); it != pObjectList->end(); ++it) {
     if (CPDF_PageObject* pPageObj = it->get()) {
-      if (pPageObj->m_Type == CPDF_PageObject::TEXT) {
-        ProcessTextObject(static_cast<CPDF_TextObject*>(pPageObj),
-                          curFormMatrix, pObjectList, it);
-      } else if (pPageObj->m_Type == CPDF_PageObject::FORM) {
-        ProcessFormObject(static_cast<CPDF_FormObject*>(pPageObj),
-                          curFormMatrix);
+      if (pPageObj->IsText()) {
+        ProcessTextObject(pPageObj->AsText(), curFormMatrix, pObjectList, it);
+      } else if (pPageObj->IsForm()) {
+        ProcessFormObject(pPageObj->AsForm(), curFormMatrix);
       }
     }
   }
@@ -1825,9 +1822,9 @@
   while (i < 5 && iter != pObjList->begin()) {
     --iter;
     CPDF_PageObject* pOtherObj = iter->get();
-    if (pOtherObj == pTextObj || pOtherObj->m_Type != CPDF_PageObject::TEXT)
+    if (pOtherObj == pTextObj || !pOtherObj->IsText())
       continue;
-    if (IsSameTextObject(static_cast<CPDF_TextObject*>(pOtherObj), pTextObj))
+    if (IsSameTextObject(pOtherObj->AsText(), pTextObj))
       return TRUE;
     ++i;
   }
diff --git a/fpdfsdk/src/fpdf_transformpage.cpp b/fpdfsdk/src/fpdf_transformpage.cpp
index 4664037..9f500b2 100644
--- a/fpdfsdk/src/fpdf_transformpage.cpp
+++ b/fpdfsdk/src/fpdf_transformpage.cpp
@@ -200,7 +200,7 @@
 
   // Special treatment to shading object, because the ClipPath for shading
   // object is already transformed.
-  if (pPageObj->m_Type != CPDF_PageObject::SHADING)
+  if (!pPageObj->IsShading())
     pPageObj->TransformClipPath(matrix);
   pPageObj->TransformGeneralState(matrix);
 }
diff --git a/fpdfsdk/src/fpdfeditpage.cpp b/fpdfsdk/src/fpdfeditpage.cpp
index 6c14079..b833a61 100644
--- a/fpdfsdk/src/fpdfeditpage.cpp
+++ b/fpdfsdk/src/fpdfeditpage.cpp
@@ -140,9 +140,9 @@
   pPage->GetPageObjectList()->push_back(
       std::unique_ptr<CPDF_PageObject>(pPageObj));
 
-  switch (pPageObj->m_Type) {
+  switch (pPageObj->GetType()) {
     case FPDF_PAGEOBJ_PATH: {
-      CPDF_PathObject* pPathObj = (CPDF_PathObject*)pPageObj;
+      CPDF_PathObject* pPathObj = pPageObj->AsPath();
       pPathObj->CalcBoundingBox();
       break;
     }
@@ -150,17 +150,17 @@
       break;
     }
     case FPDF_PAGEOBJ_IMAGE: {
-      CPDF_ImageObject* pImageObj = (CPDF_ImageObject*)pPageObj;
+      CPDF_ImageObject* pImageObj = pPageObj->AsImage();
       pImageObj->CalcBoundingBox();
       break;
     }
     case FPDF_PAGEOBJ_SHADING: {
-      CPDF_ShadingObject* pShadingObj = (CPDF_ShadingObject*)pPageObj;
+      CPDF_ShadingObject* pShadingObj = pPageObj->AsShading();
       pShadingObj->CalcBoundingBox();
       break;
     }
     case FPDF_PAGEOBJ_FORM: {
-      CPDF_FormObject* pFormObj = (CPDF_FormObject*)pPageObj;
+      CPDF_FormObject* pFormObj = pPageObj->AsForm();
       pFormObj->CalcBoundingBox();
       break;
     }
@@ -216,13 +216,13 @@
   if (pGeneralState && pGeneralState->m_FillAlpha != 1.0f)
     return TRUE;
 
-  if (pPageObj->m_Type == CPDF_PageObject::PATH) {
+  if (pPageObj->IsPath()) {
     if (pGeneralState && pGeneralState->m_StrokeAlpha != 1.0f)
       return TRUE;
   }
 
-  if (pPageObj->m_Type == CPDF_PageObject::FORM) {
-    CPDF_FormObject* pFormObj = (CPDF_FormObject*)pPageObj;
+  if (pPageObj->IsForm()) {
+    CPDF_FormObject* pFormObj = pPageObj->AsForm();
     if (pFormObj->m_pForm &&
         (pFormObj->m_pForm->m_Transparency & PDFTRANS_ISOLATED))
       return TRUE;
diff --git a/fpdfsdk/src/javascript/Document.cpp b/fpdfsdk/src/javascript/Document.cpp
index 733384a..c49524d 100644
--- a/fpdfsdk/src/javascript/Document.cpp
+++ b/fpdfsdk/src/javascript/Document.cpp
@@ -1383,8 +1383,8 @@
   int nWords = 0;
   CFX_WideString swRet;
   for (auto& pPageObj : *page.GetPageObjectList()) {
-    if (pPageObj->m_Type == CPDF_PageObject::TEXT) {
-      CPDF_TextObject* pTextObj = static_cast<CPDF_TextObject*>(pPageObj.get());
+    if (pPageObj->IsText()) {
+      CPDF_TextObject* pTextObj = pPageObj->AsText();
       int nObjWords = CountWords(pTextObj);
       if (nWords + nObjWords >= nWordNo) {
         swRet = GetObjWordStr(pTextObj, nWordNo - nWords);
@@ -1438,8 +1438,8 @@
 
   int nWords = 0;
   for (auto& pPageObj : *page.GetPageObjectList()) {
-    if (pPageObj->m_Type == CPDF_PageObject::TEXT)
-      nWords += CountWords(static_cast<CPDF_TextObject*>(pPageObj.get()));
+    if (pPageObj->IsText())
+      nWords += CountWords(pPageObj->AsText());
   }
 
   vRet = nWords;