Stop inheriting from CPDF_GraphicStates

Change CPDF_AllStates and CPDF_PageObject to have a CPDF_GraphicStates
member, instead of inheriting from it. Add many pass-through methods to
these classes to avoid having to rewrite all the CPDF_GraphicStates
method calls.

As a result, CPDF_GraphicStates no longer needs a virtual destructor,
considering it has no virtual methods. CL is based on the discussion in
https://pdfium-review.googlesource.com/113490.

Change-Id: Icd77cb8ba1a76f3c0e4fd5d825b064980be0546c
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/113550
Reviewed-by: Tom Sepez <tsepez@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/page/cpdf_allstates.cpp b/core/fpdfapi/page/cpdf_allstates.cpp
index fee8d22..8174af4 100644
--- a/core/fpdfapi/page/cpdf_allstates.cpp
+++ b/core/fpdfapi/page/cpdf_allstates.cpp
@@ -24,7 +24,7 @@
 CPDF_AllStates::~CPDF_AllStates() = default;
 
 void CPDF_AllStates::Copy(const CPDF_AllStates& src) {
-  CopyStates(src);
+  m_GraphicStates.CopyStates(src.graphic_states());
   m_TextMatrix = src.m_TextMatrix;
   m_ParentMatrix = src.m_ParentMatrix;
   m_CTM = src.m_CTM;
@@ -35,6 +35,10 @@
   m_TextHorzScale = src.m_TextHorzScale;
 }
 
+void CPDF_AllStates::DefaultStates() {
+  m_GraphicStates.DefaultStates();
+}
+
 void CPDF_AllStates::SetLineDash(const CPDF_Array* pArray,
                                  float phase,
                                  float scale) {
diff --git a/core/fpdfapi/page/cpdf_allstates.h b/core/fpdfapi/page/cpdf_allstates.h
index 4bdc1d9..3c0f0f6 100644
--- a/core/fpdfapi/page/cpdf_allstates.h
+++ b/core/fpdfapi/page/cpdf_allstates.h
@@ -14,12 +14,14 @@
 class CPDF_Dictionary;
 class CPDF_StreamContentParser;
 
-class CPDF_AllStates final : public CPDF_GraphicStates {
+class CPDF_AllStates {
  public:
   CPDF_AllStates();
-  ~CPDF_AllStates() override;
+  ~CPDF_AllStates();
 
   void Copy(const CPDF_AllStates& src);
+  void DefaultStates();
+
   void ProcessExtGS(const CPDF_Dictionary* pGS,
                     CPDF_StreamContentParser* pParser);
   void SetLineDash(const CPDF_Array* pArray, float phase, float scale);
@@ -52,7 +54,43 @@
   float text_horz_scale() const { return m_TextHorzScale; }
   void set_text_horz_scale(float value) { m_TextHorzScale = value; }
 
+  const CPDF_ClipPath& clip_path() const { return m_GraphicStates.clip_path(); }
+  CPDF_ClipPath& mutable_clip_path() {
+    return m_GraphicStates.mutable_clip_path();
+  }
+
+  const CFX_GraphState& graph_state() const {
+    return m_GraphicStates.graph_state();
+  }
+  CFX_GraphState& mutable_graph_state() {
+    return m_GraphicStates.mutable_graph_state();
+  }
+
+  const CPDF_ColorState& color_state() const {
+    return m_GraphicStates.color_state();
+  }
+  CPDF_ColorState& mutable_color_state() {
+    return m_GraphicStates.mutable_color_state();
+  }
+
+  const CPDF_TextState& text_state() const {
+    return m_GraphicStates.text_state();
+  }
+  CPDF_TextState& mutable_text_state() {
+    return m_GraphicStates.mutable_text_state();
+  }
+
+  const CPDF_GeneralState& general_state() const {
+    return m_GraphicStates.general_state();
+  }
+  CPDF_GeneralState& mutable_general_state() {
+    return m_GraphicStates.mutable_general_state();
+  }
+
+  const CPDF_GraphicStates& graphic_states() const { return m_GraphicStates; }
+
  private:
+  CPDF_GraphicStates m_GraphicStates;
   CFX_Matrix m_TextMatrix;
   CFX_Matrix m_CTM;
   CFX_Matrix m_ParentMatrix;
diff --git a/core/fpdfapi/page/cpdf_graphicstates.h b/core/fpdfapi/page/cpdf_graphicstates.h
index e1b35d7..1072b47 100644
--- a/core/fpdfapi/page/cpdf_graphicstates.h
+++ b/core/fpdfapi/page/cpdf_graphicstates.h
@@ -16,7 +16,7 @@
 class CPDF_GraphicStates {
  public:
   CPDF_GraphicStates();
-  virtual ~CPDF_GraphicStates();
+  ~CPDF_GraphicStates();
 
   void CopyStates(const CPDF_GraphicStates& src);
   void DefaultStates();
diff --git a/core/fpdfapi/page/cpdf_pageobject.cpp b/core/fpdfapi/page/cpdf_pageobject.cpp
index 68f2bcd..0782d18 100644
--- a/core/fpdfapi/page/cpdf_pageobject.cpp
+++ b/core/fpdfapi/page/cpdf_pageobject.cpp
@@ -80,8 +80,12 @@
   return general_state().GetGraphicsResourceNames();
 }
 
+void CPDF_PageObject::DefaultStates() {
+  m_GraphicStates.DefaultStates();
+}
+
 void CPDF_PageObject::CopyData(const CPDF_PageObject* pSrc) {
-  CopyStates(*pSrc);
+  m_GraphicStates.CopyStates(pSrc->graphic_states());
   m_Rect = pSrc->m_Rect;
   m_bDirty = true;
 }
diff --git a/core/fpdfapi/page/cpdf_pageobject.h b/core/fpdfapi/page/cpdf_pageobject.h
index 9ff4a88..e2f15be 100644
--- a/core/fpdfapi/page/cpdf_pageobject.h
+++ b/core/fpdfapi/page/cpdf_pageobject.h
@@ -24,7 +24,7 @@
 // Represents an object within the page, like a form or image. Not to be
 // confused with the PDF spec's page object that lives in a page tree, which is
 // represented by CPDF_Page.
-class CPDF_PageObject : public CPDF_GraphicStates {
+class CPDF_PageObject {
  public:
   // Values must match corresponding values in //public.
   enum class Type {
@@ -40,7 +40,7 @@
   explicit CPDF_PageObject(int32_t content_stream);
   CPDF_PageObject(const CPDF_PageObject& src) = delete;
   CPDF_PageObject& operator=(const CPDF_PageObject& src) = delete;
-  ~CPDF_PageObject() override;
+  virtual ~CPDF_PageObject();
 
   virtual Type GetType() const = 0;
   virtual void Transform(const CFX_Matrix& matrix) = 0;
@@ -97,10 +97,48 @@
 
   pdfium::span<const ByteString> GetGraphicsResourceNames() const;
 
+  const CPDF_ClipPath& clip_path() const { return m_GraphicStates.clip_path(); }
+  CPDF_ClipPath& mutable_clip_path() {
+    return m_GraphicStates.mutable_clip_path();
+  }
+
+  const CFX_GraphState& graph_state() const {
+    return m_GraphicStates.graph_state();
+  }
+  CFX_GraphState& mutable_graph_state() {
+    return m_GraphicStates.mutable_graph_state();
+  }
+
+  const CPDF_ColorState& color_state() const {
+    return m_GraphicStates.color_state();
+  }
+  CPDF_ColorState& mutable_color_state() {
+    return m_GraphicStates.mutable_color_state();
+  }
+
+  const CPDF_TextState& text_state() const {
+    return m_GraphicStates.text_state();
+  }
+  CPDF_TextState& mutable_text_state() {
+    return m_GraphicStates.mutable_text_state();
+  }
+
+  const CPDF_GeneralState& general_state() const {
+    return m_GraphicStates.general_state();
+  }
+  CPDF_GeneralState& mutable_general_state() {
+    return m_GraphicStates.mutable_general_state();
+  }
+
+  const CPDF_GraphicStates& graphic_states() const { return m_GraphicStates; }
+
+  void DefaultStates();
+
  protected:
   void CopyData(const CPDF_PageObject* pSrcObject);
 
  private:
+  CPDF_GraphicStates m_GraphicStates;
   CFX_FloatRect m_Rect;
   CFX_FloatRect m_OriginalRect;
   CPDF_ContentMarks m_ContentMarks;
diff --git a/core/fpdfapi/render/cpdf_renderstatus.cpp b/core/fpdfapi/render/cpdf_renderstatus.cpp
index 8da0af6..282ed31 100644
--- a/core/fpdfapi/render/cpdf_renderstatus.cpp
+++ b/core/fpdfapi/render/cpdf_renderstatus.cpp
@@ -366,7 +366,7 @@
   status.SetTransparency(m_Transparency);
   status.SetDropObjects(m_bDropObjects);
   status.SetFormResource(std::move(pResources));
-  status.Initialize(this, pFormObj);
+  status.Initialize(this, &pFormObj->graphic_states());
   status.m_curBlend = m_curBlend;
   {
     CFX_RenderDevice::StateRestorer restorer(m_pDevice);
@@ -924,7 +924,7 @@
       }
 
       std::unique_ptr<CPDF_GraphicStates> pStates =
-          CloneObjStates(textobj, false);
+          CloneObjStates(&textobj->graphic_states(), false);
       CPDF_RenderOptions options = m_Options;
       options.GetOptions().bForceHalftone = true;
       options.GetOptions().bRectAA = true;
diff --git a/core/fpdfapi/render/cpdf_rendertiling.cpp b/core/fpdfapi/render/cpdf_rendertiling.cpp
index 64b7acc..47a7c42 100644
--- a/core/fpdfapi/render/cpdf_rendertiling.cpp
+++ b/core/fpdfapi/render/cpdf_rendertiling.cpp
@@ -121,7 +121,8 @@
       width * height > clip_box.Width() * clip_box.Height()) {
     std::unique_ptr<CPDF_GraphicStates> pStates;
     if (!pPattern->colored())
-      pStates = CPDF_RenderStatus::CloneObjStates(pPageObj, bStroke);
+      pStates = CPDF_RenderStatus::CloneObjStates(&pPageObj->graphic_states(),
+                                                  bStroke);
 
     RetainPtr<const CPDF_Dictionary> pFormResource =
         pPatternForm->GetDict()->GetDictFor("Resources");