Introduce CFX_GEModule::PlatformIface pure virtual class.

This replaces a void* pointer in the CFX_GEModule, and allows platform
destruction order to be controlled by the member order, rather than an
explicit call in the destructor.

Each of the platforms implements its own platform-specific subclass.

In the future, it seems likely that CFX_FontCache/CFX_FontMgr members
will not get to outlive the PlatformIface, and this makes that change
easier to accomplish.

Change-Id: If278f79b66fa8a7d6b2f9be089c31b37c308ae26
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/54810
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/font/cpdf_type1font.cpp b/core/fpdfapi/font/cpdf_type1font.cpp
index b78922d..0cb8d19 100644
--- a/core/fpdfapi/font/cpdf_type1font.cpp
+++ b/core/fpdfapi/font/cpdf_type1font.cpp
@@ -126,7 +126,7 @@
 #if defined(OS_MACOSX)
   bool bCoreText = true;
   CQuartz2D& quartz2d =
-      static_cast<CApplePlatform*>(CFX_GEModule::Get()->GetPlatformData())
+      static_cast<CApplePlatform*>(CFX_GEModule::Get()->GetPlatform())
           ->m_quartz2d;
   if (!m_Font.GetPlatformFont()) {
     if (m_Font.GetPsName() == "DFHeiStd-W5")
diff --git a/core/fxge/android/fx_android_imp.cpp b/core/fxge/android/fx_android_imp.cpp
index db2f3ef..147011c 100644
--- a/core/fxge/android/fx_android_imp.cpp
+++ b/core/fxge/android/fx_android_imp.cpp
@@ -14,21 +14,31 @@
 #include "core/fxge/cfx_fontmgr.h"
 #include "third_party/base/ptr_util.h"
 
-void CFX_GEModule::InitPlatform() {
-  CFPF_SkiaDeviceModule* pDeviceModule = CFPF_GetSkiaDeviceModule();
-  if (!pDeviceModule)
-    return;
+class CAndroidPlatform : public CFX_GEModule::PlatformIface {
+ public:
+  CAndroidPlatform() = default;
+  ~CAndroidPlatform() override {
+    if (m_pDeviceModule)
+      m_pDeviceModule->Destroy();
+  }
 
-  CFPF_SkiaFontMgr* pFontMgr = pDeviceModule->GetFontMgr();
-  if (pFontMgr) {
+  void Init() override {
+    m_pDeviceModule = CFPF_GetSkiaDeviceModule();
+    CFPF_SkiaFontMgr* pFontMgr = m_pDeviceModule->GetFontMgr();
+    if (!pFontMgr)
+      return;
+
     auto pFontInfo = pdfium::MakeUnique<CFX_AndroidFontInfo>();
     pFontInfo->Init(pFontMgr);
-    m_pFontMgr->SetSystemFontInfo(std::move(pFontInfo));
+    CFX_GEModule::Get()->GetFontMgr()->SetSystemFontInfo(std::move(pFontInfo));
   }
-  m_pPlatformData = pDeviceModule;
-}
 
-void CFX_GEModule::DestroyPlatform() {
-  if (m_pPlatformData)
-    static_cast<CFPF_SkiaDeviceModule*>(m_pPlatformData)->Destroy();
+ private:
+  CFPF_SkiaDeviceModule* m_pDeviceModule = nullptr;
+};
+
+// static
+std::unique_ptr<CFX_GEModule::PlatformIface>
+CFX_GEModule::PlatformIface::Create() {
+  return pdfium::MakeUnique<CAndroidPlatform>();
 }
diff --git a/core/fxge/apple/apple_int.h b/core/fxge/apple/apple_int.h
index e91b1e1..cbf3464 100644
--- a/core/fxge/apple/apple_int.h
+++ b/core/fxge/apple/apple_int.h
@@ -11,6 +11,7 @@
 
 #include <Carbon/Carbon.h>
 
+#include "core/fxge/cfx_gemodule.h"
 #include "core/fxge/cfx_graphstatedata.h"
 #include "core/fxge/cfx_pathdata.h"
 #include "core/fxge/fx_dib.h"
@@ -35,10 +36,13 @@
   void restoreGraphicsState(void* graphics);
 };
 
-class CApplePlatform {
+class CApplePlatform : public CFX_GEModule::PlatformIface {
  public:
-  CApplePlatform() {}
-  ~CApplePlatform() {}
+  CApplePlatform();
+  ~CApplePlatform() override;
+
+  // CFX_GEModule::PlatformIface:
+  void Init() override;
 
   CQuartz2D m_quartz2d;
 };
diff --git a/core/fxge/apple/fx_apple_platform.cpp b/core/fxge/apple/fx_apple_platform.cpp
index ad2bdaf..c8c55a8 100644
--- a/core/fxge/apple/fx_apple_platform.cpp
+++ b/core/fxge/apple/fx_apple_platform.cpp
@@ -50,7 +50,7 @@
     new_matrix.Concat(*pObject2Device);
 
   CQuartz2D& quartz2d =
-      static_cast<CApplePlatform*>(CFX_GEModule::Get()->GetPlatformData())
+      static_cast<CApplePlatform*>(CFX_GEModule::Get()->GetPlatform())
           ->m_quartz2d;
   if (!pFont->GetPlatformFont()) {
     if (pFont->GetPsName() == "DFHeiStd-W5")
@@ -89,14 +89,14 @@
 
 void CFX_AggDeviceDriver::InitPlatform() {
   CQuartz2D& quartz2d =
-      static_cast<CApplePlatform*>(CFX_GEModule::Get()->GetPlatformData())
+      static_cast<CApplePlatform*>(CFX_GEModule::Get()->GetPlatform())
           ->m_quartz2d;
   m_pPlatformGraphics = quartz2d.createGraphics(m_pBitmap);
 }
 
 void CFX_AggDeviceDriver::DestroyPlatform() {
   CQuartz2D& quartz2d =
-      static_cast<CApplePlatform*>(CFX_GEModule::Get()->GetPlatformData())
+      static_cast<CApplePlatform*>(CFX_GEModule::Get()->GetPlatform())
           ->m_quartz2d;
   if (m_pPlatformGraphics) {
     quartz2d.destroyGraphics(m_pPlatformGraphics);
@@ -181,7 +181,7 @@
 void CFX_Font::ReleasePlatformResource() {
   if (m_pPlatformFont) {
     CQuartz2D& quartz2d =
-        static_cast<CApplePlatform*>(CFX_GEModule::Get()->GetPlatformData())
+        static_cast<CApplePlatform*>(CFX_GEModule::Get()->GetPlatform())
             ->m_quartz2d;
     quartz2d.DestroyFont(m_pPlatformFont);
     m_pPlatformFont = nullptr;
diff --git a/core/fxge/apple/fx_mac_imp.cpp b/core/fxge/apple/fx_mac_imp.cpp
index bf8e4f6..64e50cc 100644
--- a/core/fxge/apple/fx_mac_imp.cpp
+++ b/core/fxge/apple/fx_mac_imp.cpp
@@ -142,13 +142,18 @@
   return std::move(pInfo);
 }
 
-void CFX_GEModule::InitPlatform() {
-  m_pPlatformData = new CApplePlatform;
-  m_pFontMgr->SetSystemFontInfo(
-      SystemFontInfoIface::CreateDefault(m_pUserFontPaths));
+CApplePlatform::CApplePlatform() = default;
+
+CApplePlatform::~CApplePlatform() = default;
+
+void CApplePlatform::Init() {
+  CFX_GEModule* pModule = CFX_GEModule::Get();
+  pModule->GetFontMgr()->SetSystemFontInfo(
+      SystemFontInfoIface::CreateDefault(pModule->GetUserFontPaths()));
 }
 
-void CFX_GEModule::DestroyPlatform() {
-  delete reinterpret_cast<CApplePlatform*>(m_pPlatformData);
-  m_pPlatformData = nullptr;
+// static
+std::unique_ptr<CFX_GEModule::PlatformIface>
+CFX_GEModule::PlatformIface::Create() {
+  return pdfium::MakeUnique<CApplePlatform>();
 }
diff --git a/core/fxge/cfx_gemodule.cpp b/core/fxge/cfx_gemodule.cpp
index cbc66c3..b9b232d 100644
--- a/core/fxge/cfx_gemodule.cpp
+++ b/core/fxge/cfx_gemodule.cpp
@@ -19,12 +19,9 @@
 
 CFX_GEModule::CFX_GEModule()
     : m_pFontMgr(pdfium::MakeUnique<CFX_FontMgr>()),
-      m_pPlatformData(nullptr),
-      m_pUserFontPaths(nullptr) {}
+      m_pPlatform(PlatformIface::Create()) {}
 
-CFX_GEModule::~CFX_GEModule() {
-  DestroyPlatform();
-}
+CFX_GEModule::~CFX_GEModule() = default;
 
 // static
 CFX_GEModule* CFX_GEModule::Get() {
@@ -43,7 +40,7 @@
 void CFX_GEModule::Init(const char** userFontPaths) {
   ASSERT(g_pGEModule);
   m_pUserFontPaths = userFontPaths;
-  InitPlatform();
+  m_pPlatform->Init();
 }
 
 CFX_FontCache* CFX_GEModule::GetFontCache() {
diff --git a/core/fxge/cfx_gemodule.h b/core/fxge/cfx_gemodule.h
index f48d065..afcbff4 100644
--- a/core/fxge/cfx_gemodule.h
+++ b/core/fxge/cfx_gemodule.h
@@ -14,26 +14,31 @@
 
 class CFX_GEModule {
  public:
+  class PlatformIface {
+   public:
+    static std::unique_ptr<PlatformIface> Create();
+    virtual ~PlatformIface() {}
+
+    virtual void Init() = 0;
+  };
+
   static CFX_GEModule* Get();
   static void Destroy();
 
   void Init(const char** pUserFontPaths);
   CFX_FontCache* GetFontCache();
-  CFX_FontMgr* GetFontMgr() { return m_pFontMgr.get(); }
-
-  void* GetPlatformData() { return m_pPlatformData; }
+  CFX_FontMgr* GetFontMgr() const { return m_pFontMgr.get(); }
+  PlatformIface* GetPlatform() const { return m_pPlatform.get(); }
+  const char** GetUserFontPaths() const { return m_pUserFontPaths; }
 
  private:
   CFX_GEModule();
   ~CFX_GEModule();
 
-  void InitPlatform();
-  void DestroyPlatform();
-
   std::unique_ptr<CFX_FontCache> m_pFontCache;
   std::unique_ptr<CFX_FontMgr> m_pFontMgr;
-  void* m_pPlatformData;
-  const char** m_pUserFontPaths;
+  std::unique_ptr<PlatformIface> m_pPlatform;
+  const char** m_pUserFontPaths = nullptr;
 };
 
 #endif  // CORE_FXGE_CFX_GEMODULE_H_
diff --git a/core/fxge/fx_ge_linux.cpp b/core/fxge/fx_ge_linux.cpp
index d3af1b7..ddde4a6 100644
--- a/core/fxge/fx_ge_linux.cpp
+++ b/core/fxge/fx_ge_linux.cpp
@@ -159,10 +159,21 @@
   return std::move(pInfo);
 }
 
-void CFX_GEModule::InitPlatform() {
-  m_pFontMgr->SetSystemFontInfo(
-      SystemFontInfoIface::CreateDefault(m_pUserFontPaths));
-}
+class CLinuxPlatform : public CFX_GEModule::PlatformIface {
+ public:
+  CLinuxPlatform() = default;
+  ~CLinuxPlatform() override = default;
 
-void CFX_GEModule::DestroyPlatform() {}
+  void Init() override {
+    CFX_GEModule* pModule = CFX_GEModule::Get();
+    pModule->GetFontMgr()->SetSystemFontInfo(
+        SystemFontInfoIface::CreateDefault(pModule->GetUserFontPaths()));
+  }
+};
+
+// static
+std::unique_ptr<CFX_GEModule::PlatformIface>
+CFX_GEModule::PlatformIface::Create() {
+  return pdfium::MakeUnique<CLinuxPlatform>();
+}
 #endif  // _FX_PLATFORM_ == _FX_PLATFORM_LINUX_
diff --git a/core/fxge/win32/fx_win32_device.cpp b/core/fxge/win32/fx_win32_device.cpp
index 3361e7c..c4e4576 100644
--- a/core/fxge/win32/fx_win32_device.cpp
+++ b/core/fxge/win32/fx_win32_device.cpp
@@ -683,28 +683,32 @@
   return std::unique_ptr<SystemFontInfoIface>(pInfoFallback);
 }
 
-void CFX_GEModule::InitPlatform() {
-  CWin32Platform* pPlatformData = new CWin32Platform;
+CWin32Platform::CWin32Platform() = default;
+
+CWin32Platform::~CWin32Platform() = default;
+
+void CWin32Platform::Init() {
   OSVERSIONINFO ver;
   ver.dwOSVersionInfoSize = sizeof(ver);
   GetVersionEx(&ver);
-  pPlatformData->m_bHalfTone = ver.dwMajorVersion >= 5;
+  m_bHalfTone = ver.dwMajorVersion >= 5;
   if (pdfium::base::win::IsUser32AndGdi32Available())
-    pPlatformData->m_GdiplusExt.Load();
-  m_pPlatformData = pPlatformData;
-  m_pFontMgr->SetSystemFontInfo(SystemFontInfoIface::CreateDefault(nullptr));
+    m_GdiplusExt.Load();
+  CFX_GEModule::Get()->GetFontMgr()->SetSystemFontInfo(
+      SystemFontInfoIface::CreateDefault(nullptr));
 }
 
-void CFX_GEModule::DestroyPlatform() {
-  delete (CWin32Platform*)m_pPlatformData;
-  m_pPlatformData = nullptr;
+// static
+std::unique_ptr<CFX_GEModule::PlatformIface>
+CFX_GEModule::PlatformIface::Create() {
+  return pdfium::MakeUnique<CWin32Platform>();
 }
 
 CGdiDeviceDriver::CGdiDeviceDriver(HDC hDC, int device_class) {
   m_hDC = hDC;
   m_DeviceClass = device_class;
-  CWin32Platform* pPlatform =
-      (CWin32Platform*)CFX_GEModule::Get()->GetPlatformData();
+  auto* pPlatform =
+      static_cast<CWin32Platform*>(CFX_GEModule::Get()->GetPlatform());
   SetStretchBltMode(hDC, pPlatform->m_bHalfTone ? HALFTONE : COLORONCOLOR);
   DWORD obj_type = GetObjectType(m_hDC);
   m_bMetafileDCType = obj_type == OBJ_ENHMETADC || obj_type == OBJ_ENHMETAFILE;
@@ -954,8 +958,8 @@
   if (blend_type != BlendMode::kNormal)
     return false;
 
-  CWin32Platform* pPlatform =
-      (CWin32Platform*)CFX_GEModule::Get()->GetPlatformData();
+  auto* pPlatform =
+      static_cast<CWin32Platform*>(CFX_GEModule::Get()->GetPlatform());
   if (!(pGraphState || stroke_color == 0) &&
       !pPlatform->m_GdiplusExt.IsAvailable()) {
     CFX_FloatRect bbox_f = pPathData->GetBoundingBox();
@@ -1128,8 +1132,8 @@
 
 CGdiDisplayDriver::CGdiDisplayDriver(HDC hDC)
     : CGdiDeviceDriver(hDC, FXDC_DISPLAY) {
-  CWin32Platform* pPlatform =
-      (CWin32Platform*)CFX_GEModule::Get()->GetPlatformData();
+  auto* pPlatform =
+      static_cast<CWin32Platform*>(CFX_GEModule::Get()->GetPlatform());
   if (pPlatform->m_GdiplusExt.IsAvailable()) {
     m_RenderCaps |= FXRC_ALPHA_PATH | FXRC_ALPHA_IMAGE;
   }
@@ -1300,8 +1304,8 @@
                      image_rect.top + clip_rect.top, BlendMode::kNormal);
   }
   if (pSource->HasAlpha()) {
-    CWin32Platform* pPlatform =
-        (CWin32Platform*)CFX_GEModule::Get()->GetPlatformData();
+    auto* pPlatform =
+        static_cast<CWin32Platform*>(CFX_GEModule::Get()->GetPlatform());
     if (pPlatform->m_GdiplusExt.IsAvailable() && !pSource->IsCmykImage()) {
       CFX_DIBExtractor temp(pSource);
       RetainPtr<CFX_DIBitmap> pBitmap = temp.GetBitmap();
diff --git a/core/fxge/win32/fx_win32_dib.cpp b/core/fxge/win32/fx_win32_dib.cpp
index 1a7cd45..6c9d394 100644
--- a/core/fxge/win32/fx_win32_dib.cpp
+++ b/core/fxge/win32/fx_win32_dib.cpp
@@ -120,8 +120,8 @@
 }
 
 RetainPtr<CFX_DIBitmap> CFX_WindowsDIB::LoadFromFile(const wchar_t* filename) {
-  CWin32Platform* pPlatform =
-      (CWin32Platform*)CFX_GEModule::Get()->GetPlatformData();
+  auto* pPlatform =
+      static_cast<CWin32Platform*>(CFX_GEModule::Get()->GetPlatform());
   if (pPlatform->m_GdiplusExt.IsAvailable()) {
     WINDIB_Open_Args_ args;
     args.flags = WINDIB_OPEN_PATHNAME;
@@ -156,8 +156,8 @@
 }
 
 RetainPtr<CFX_DIBitmap> CFX_WindowsDIB::LoadDIBitmap(WINDIB_Open_Args_ args) {
-  CWin32Platform* pPlatform =
-      (CWin32Platform*)CFX_GEModule::Get()->GetPlatformData();
+  auto* pPlatform =
+      static_cast<CWin32Platform*>(CFX_GEModule::Get()->GetPlatform());
   if (pPlatform->m_GdiplusExt.IsAvailable()) {
     return pPlatform->m_GdiplusExt.LoadDIBitmap(args);
   }
diff --git a/core/fxge/win32/fx_win32_gdipext.cpp b/core/fxge/win32/fx_win32_gdipext.cpp
index ea3db4d..0b6667b 100644
--- a/core/fxge/win32/fx_win32_gdipext.cpp
+++ b/core/fxge/win32/fx_win32_gdipext.cpp
@@ -302,7 +302,7 @@
 
 const CGdiplusExt& GetGdiplusExt() {
   auto* pData =
-      reinterpret_cast<CWin32Platform*>(CFX_GEModule::Get()->GetPlatformData());
+      static_cast<CWin32Platform*>(CFX_GEModule::Get()->GetPlatform());
   return pData->m_GdiplusExt;
 }
 
diff --git a/core/fxge/win32/win32_int.h b/core/fxge/win32/win32_int.h
index 3d4ef2d..d0a4588 100644
--- a/core/fxge/win32/win32_int.h
+++ b/core/fxge/win32/win32_int.h
@@ -13,6 +13,7 @@
 #include <vector>
 
 #include "core/fxcrt/retain_ptr.h"
+#include "core/fxge/cfx_gemodule.h"
 #include "core/fxge/cfx_pathdata.h"
 #include "core/fxge/cfx_windowsrenderdevice.h"
 #include "core/fxge/renderdevicedriver_iface.h"
@@ -59,9 +60,15 @@
   HMODULE m_GdiModule = nullptr;
 };
 
-class CWin32Platform {
+class CWin32Platform : public CFX_GEModule::PlatformIface {
  public:
-  bool m_bHalfTone;
+  CWin32Platform();
+  ~CWin32Platform() override;
+
+  // CFX_GEModule::PlatformIface:
+  void Init() override;
+
+  bool m_bHalfTone = false;
   CGdiplusExt m_GdiplusExt;
 };