Introduce CPDF_Type3Char::FormIface to avoid some layering issues

Allows the removal of some otherwise circular includes.

Change-Id: I0a4102d0c4461422ae2ff8935acb728c038e1d8d
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/57811
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/font/cpdf_type3char.cpp b/core/fpdfapi/font/cpdf_type3char.cpp
index 96c9b30..44ca22b 100644
--- a/core/fpdfapi/font/cpdf_type3char.cpp
+++ b/core/fpdfapi/font/cpdf_type3char.cpp
@@ -8,10 +8,7 @@
 
 #include <utility>
 
-#include "core/fpdfapi/page/cpdf_form.h"
-#include "core/fpdfapi/page/cpdf_image.h"
 #include "core/fpdfapi/page/cpdf_imageobject.h"
-#include "core/fpdfapi/page/cpdf_pageobject.h"
 #include "core/fxge/dib/cfx_dibitmap.h"
 #include "core/fxge/fx_dib.h"
 #include "third_party/base/ptr_util.h"
@@ -63,7 +60,7 @@
   m_BBox.top = FXSYS_round(TextUnitToGlyphUnit(pData[5]));
 }
 
-void CPDF_Type3Char::Transform(CPDF_Form* pForm, const CFX_Matrix& matrix) {
+void CPDF_Type3Char::Transform(FormIface* pForm, const CFX_Matrix& matrix) {
   m_Width = m_Width * matrix.GetXUnit() + 0.5f;
 
   CFX_FloatRect char_rect;
@@ -77,7 +74,7 @@
   m_BBox = matrix.TransformRect(char_rect).ToRoundedFxRect();
 }
 
-void CPDF_Type3Char::SetForm(std::unique_ptr<CPDF_Form> pForm) {
+void CPDF_Type3Char::SetForm(std::unique_ptr<FormIface> pForm) {
   m_pForm = std::move(pForm);
 }
 
diff --git a/core/fpdfapi/font/cpdf_type3char.h b/core/fpdfapi/font/cpdf_type3char.h
index bcf94da..a7d855e 100644
--- a/core/fpdfapi/font/cpdf_type3char.h
+++ b/core/fpdfapi/font/cpdf_type3char.h
@@ -14,10 +14,19 @@
 #include "core/fxcrt/retain_ptr.h"
 
 class CFX_DIBitmap;
-class CPDF_Form;
+class CPDF_ImageObject;
 
 class CPDF_Type3Char {
  public:
+  class FormIface {
+   public:
+    virtual ~FormIface() {}
+
+    virtual void ParseContentForType3Char(CPDF_Type3Char* pChar) = 0;
+    virtual const CPDF_ImageObject* GetSoleImageOfForm() const = 0;
+    virtual CFX_FloatRect CalcBoundingBox() const = 0;
+  };
+
   CPDF_Type3Char();
   ~CPDF_Type3Char();
 
@@ -26,7 +35,7 @@
 
   bool LoadBitmapFromSoleImageOfForm();
   void InitializeFromStreamData(bool bColored, const float* pData);
-  void Transform(CPDF_Form* pForm, const CFX_Matrix& matrix);
+  void Transform(FormIface* pForm, const CFX_Matrix& matrix);
 
   RetainPtr<CFX_DIBitmap> GetBitmap();
   const RetainPtr<CFX_DIBitmap>& GetBitmap() const;
@@ -36,12 +45,11 @@
   const CFX_Matrix& matrix() const { return m_ImageMatrix; }
   const FX_RECT& bbox() const { return m_BBox; }
 
-  const CPDF_Form* form() const { return m_pForm.get(); }
-  CPDF_Form* form() { return m_pForm.get(); }
-  void SetForm(std::unique_ptr<CPDF_Form> pForm);
+  const FormIface* form() const { return m_pForm.get(); }
+  void SetForm(std::unique_ptr<FormIface> pForm);
 
  private:
-  std::unique_ptr<CPDF_Form> m_pForm;
+  std::unique_ptr<FormIface> m_pForm;
   RetainPtr<CFX_DIBitmap> m_pBitmap;
   bool m_bColored = false;
   uint32_t m_Width = 0;
diff --git a/core/fpdfapi/font/cpdf_type3font.cpp b/core/fpdfapi/font/cpdf_type3font.cpp
index 2c9d815..5787dc9 100644
--- a/core/fpdfapi/font/cpdf_type3font.cpp
+++ b/core/fpdfapi/font/cpdf_type3font.cpp
@@ -103,8 +103,10 @@
   if (!name)
     return nullptr;
 
-  CPDF_Stream* pStream =
-      ToStream(m_pCharProcs ? m_pCharProcs->GetDirectObjectFor(name) : nullptr);
+  if (!m_pCharProcs)
+    return nullptr;
+
+  CPDF_Stream* pStream = ToStream(m_pCharProcs->GetDirectObjectFor(name));
   if (!pStream)
     return nullptr;
 
diff --git a/core/fpdfapi/page/cpdf_form.h b/core/fpdfapi/page/cpdf_form.h
index 68f92d5..f9b2e2e 100644
--- a/core/fpdfapi/page/cpdf_form.h
+++ b/core/fpdfapi/page/cpdf_form.h
@@ -10,6 +10,7 @@
 #include <memory>
 #include <set>
 
+#include "core/fpdfapi/font/cpdf_type3char.h"
 #include "core/fpdfapi/page/cpdf_pageobjectholder.h"
 
 class CFX_Matrix;
@@ -20,7 +21,8 @@
 class CPDF_Stream;
 class CPDF_Type3Char;
 
-class CPDF_Form final : public CPDF_PageObjectHolder {
+class CPDF_Form final : public CPDF_PageObjectHolder,
+                        public CPDF_Type3Char::FormIface {
  public:
   // Helper method to choose the first non-null resources dictionary.
   static CPDF_Dictionary* ChooseResourcesDict(CPDF_Dictionary* pResources,
@@ -36,18 +38,18 @@
             CPDF_Dictionary* pParentResources);
   ~CPDF_Form() override;
 
+  // CPDF_Type3Char::FormIface:
+  void ParseContentForType3Char(CPDF_Type3Char* pType3Char) override;
+  const CPDF_ImageObject* GetSoleImageOfForm() const override;
+  CFX_FloatRect CalcBoundingBox() const override;
+
   void ParseContent();
   void ParseContent(const CPDF_AllStates* pGraphicStates,
                     const CFX_Matrix* pParentMatrix,
                     std::set<const uint8_t*>* pParsedSet);
-  void ParseContentForType3Char(CPDF_Type3Char* pType3Char);
 
-  CFX_FloatRect CalcBoundingBox() const;
   const CPDF_Stream* GetStream() const;
 
-  // Fast path helper for avoiding a full rendering of form.
-  const CPDF_ImageObject* GetSoleImageOfForm() const;
-
  private:
   void ParseContentInternal(const CPDF_AllStates* pGraphicStates,
                             const CFX_Matrix* pParentMatrix,
diff --git a/core/fpdfapi/render/cpdf_renderstatus.cpp b/core/fpdfapi/render/cpdf_renderstatus.cpp
index b32c995..ef23876 100644
--- a/core/fpdfapi/render/cpdf_renderstatus.cpp
+++ b/core/fpdfapi/render/cpdf_renderstatus.cpp
@@ -1850,13 +1850,14 @@
       options.GetOptions().bForceDownsample = false;
 
       const CPDF_Dictionary* pFormResource = nullptr;
-      if (pType3Char->form() && pType3Char->form()->GetDict()) {
-        pFormResource = pType3Char->form()->GetDict()->GetDictFor("Resources");
-      }
+      auto* pForm = static_cast<const CPDF_Form*>(pType3Char->form());
+      if (pForm->GetDict())
+        pFormResource = pForm->GetDict()->GetDictFor("Resources");
+
       if (fill_alpha == 255) {
         CPDF_RenderStatus status(m_pContext.Get(), m_pDevice);
         status.SetOptions(options);
-        status.SetTransparency(pType3Char->form()->GetTransparency());
+        status.SetTransparency(pForm->GetTransparency());
         status.SetType3Char(pType3Char);
         status.SetFillColor(fill_argb);
         status.SetDropObjects(m_bDropObjects);
@@ -1866,11 +1867,10 @@
         status.m_Type3FontCache.push_back(pType3Font);
 
         CFX_RenderDevice::StateRestorer restorer(m_pDevice);
-        status.RenderObjectList(pType3Char->form(), matrix);
+        status.RenderObjectList(pForm, matrix);
       } else {
         FX_RECT rect =
-            matrix.TransformRect(pType3Char->form()->CalcBoundingBox())
-                .GetOuterRect();
+            matrix.TransformRect(pForm->CalcBoundingBox()).GetOuterRect();
         if (!rect.Valid())
           continue;
 
@@ -1882,7 +1882,7 @@
         bitmap_device.GetBitmap()->Clear(0);
         CPDF_RenderStatus status(m_pContext.Get(), &bitmap_device);
         status.SetOptions(options);
-        status.SetTransparency(pType3Char->form()->GetTransparency());
+        status.SetTransparency(pForm->GetTransparency());
         status.SetType3Char(pType3Char);
         status.SetFillColor(fill_argb);
         status.SetDropObjects(m_bDropObjects);
@@ -1891,7 +1891,7 @@
         status.m_Type3FontCache = m_Type3FontCache;
         status.m_Type3FontCache.push_back(pType3Font);
         matrix.Translate(-rect.left, -rect.top);
-        status.RenderObjectList(pType3Char->form(), matrix);
+        status.RenderObjectList(pForm, matrix);
         m_pDevice->SetDIBits(bitmap_device.GetBitmap(), rect.left, rect.top);
       }
     } else if (pType3Char->GetBitmap()) {