Make CPDF_FontGlobals a per-process singleton.

Currently, it is a member of CPDF_PageModule, and while it seems
like a step backwards to re-introduce a global instance, this change
prevents lower-level modules from reaching up into the page module to
get the resources they require. This removes one circular inclusion
and gets us one step closer to removing another.

Change-Id: I604cae7c8b240666fa5791a8c8a46e9542e99112
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/55391
Reviewed-by: Lei Zhang <thestig@chromium.org>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fpdfapi/BUILD.gn b/core/fpdfapi/BUILD.gn
index 1b8c39e..f4ea940 100644
--- a/core/fpdfapi/BUILD.gn
+++ b/core/fpdfapi/BUILD.gn
@@ -26,7 +26,6 @@
     "render",
   ]
   allow_circular_includes_from = [
-    "font",
     "page",
     "parser",
     "render",
diff --git a/core/fpdfapi/cpdf_modulemgr.cpp b/core/fpdfapi/cpdf_modulemgr.cpp
index 35b719d..494b2fc 100644
--- a/core/fpdfapi/cpdf_modulemgr.cpp
+++ b/core/fpdfapi/cpdf_modulemgr.cpp
@@ -10,6 +10,7 @@
 #include "core/fpdfapi/cmaps/GB1/cmaps_gb1.h"
 #include "core/fpdfapi/cmaps/Japan1/cmaps_japan1.h"
 #include "core/fpdfapi/cmaps/Korea1/cmaps_korea1.h"
+#include "core/fpdfapi/font/cpdf_fontglobals.h"
 #include "core/fpdfapi/page/cpdf_pagemodule.h"
 #include "core/fxcodec/fx_codec.h"
 #include "third_party/base/ptr_util.h"
@@ -105,8 +106,7 @@
 }
 
 void CPDF_ModuleMgr::LoadEmbeddedGB1CMaps() {
-  CPDF_FontGlobals* pFontGlobals =
-      CPDF_ModuleMgr::Get()->GetPageModule()->GetFontGlobals();
+  auto* pFontGlobals = CPDF_FontGlobals::GetInstance();
   pFontGlobals->SetEmbeddedCharset(
       CIDSET_GB1,
       pdfium::make_span(g_FXCMAP_GB1_cmaps, g_FXCMAP_GB1_cmaps_size));
@@ -114,8 +114,7 @@
 }
 
 void CPDF_ModuleMgr::LoadEmbeddedCNS1CMaps() {
-  CPDF_FontGlobals* pFontGlobals =
-      CPDF_ModuleMgr::Get()->GetPageModule()->GetFontGlobals();
+  auto* pFontGlobals = CPDF_FontGlobals::GetInstance();
   pFontGlobals->SetEmbeddedCharset(
       CIDSET_CNS1,
       pdfium::make_span(g_FXCMAP_CNS1_cmaps, g_FXCMAP_CNS1_cmaps_size));
@@ -123,8 +122,7 @@
 }
 
 void CPDF_ModuleMgr::LoadEmbeddedJapan1CMaps() {
-  CPDF_FontGlobals* pFontGlobals =
-      CPDF_ModuleMgr::Get()->GetPageModule()->GetFontGlobals();
+  auto* pFontGlobals = CPDF_FontGlobals::GetInstance();
   pFontGlobals->SetEmbeddedCharset(
       CIDSET_JAPAN1,
       pdfium::make_span(g_FXCMAP_Japan1_cmaps, g_FXCMAP_Japan1_cmaps_size));
@@ -133,8 +131,7 @@
 }
 
 void CPDF_ModuleMgr::LoadEmbeddedKorea1CMaps() {
-  CPDF_FontGlobals* pFontGlobals =
-      CPDF_ModuleMgr::Get()->GetPageModule()->GetFontGlobals();
+  auto* pFontGlobals = CPDF_FontGlobals::GetInstance();
   pFontGlobals->SetEmbeddedCharset(
       CIDSET_KOREA1,
       pdfium::make_span(g_FXCMAP_Korea1_cmaps, g_FXCMAP_Korea1_cmaps_size));
diff --git a/core/fpdfapi/font/cpdf_cid2unicodemap.cpp b/core/fpdfapi/font/cpdf_cid2unicodemap.cpp
index f36834d..612881f 100644
--- a/core/fpdfapi/font/cpdf_cid2unicodemap.cpp
+++ b/core/fpdfapi/font/cpdf_cid2unicodemap.cpp
@@ -6,9 +6,8 @@
 
 #include "core/fpdfapi/font/cpdf_cid2unicodemap.h"
 
-#include "core/fpdfapi/cpdf_modulemgr.h"
 #include "core/fpdfapi/font/cpdf_cmapmanager.h"
-#include "core/fpdfapi/page/cpdf_pagemodule.h"
+#include "core/fpdfapi/font/cpdf_fontglobals.h"
 
 CPDF_CID2UnicodeMap::CPDF_CID2UnicodeMap() = default;
 
@@ -30,8 +29,6 @@
 
 void CPDF_CID2UnicodeMap::Load(CPDF_CMapManager* pMgr, CIDSet charset) {
   m_Charset = charset;
-
-  CPDF_FontGlobals* pFontGlobals =
-      CPDF_ModuleMgr::Get()->GetPageModule()->GetFontGlobals();
-  m_pEmbeddedMap = pFontGlobals->GetEmbeddedToUnicode(charset);
+  m_pEmbeddedMap =
+      CPDF_FontGlobals::GetInstance()->GetEmbeddedToUnicode(charset);
 }
diff --git a/core/fpdfapi/font/cpdf_cidfont.cpp b/core/fpdfapi/font/cpdf_cidfont.cpp
index 9ebda33..46e5405 100644
--- a/core/fpdfapi/font/cpdf_cidfont.cpp
+++ b/core/fpdfapi/font/cpdf_cidfont.cpp
@@ -12,13 +12,12 @@
 
 #include "build/build_config.h"
 #include "core/fpdfapi/cmaps/cmap_int.h"
-#include "core/fpdfapi/cpdf_modulemgr.h"
 #include "core/fpdfapi/font/cfx_cttgsubtable.h"
 #include "core/fpdfapi/font/cpdf_cid2unicodemap.h"
 #include "core/fpdfapi/font/cpdf_cmap.h"
 #include "core/fpdfapi/font/cpdf_cmapparser.h"
 #include "core/fpdfapi/font/cpdf_fontencoding.h"
-#include "core/fpdfapi/page/cpdf_pagemodule.h"
+#include "core/fpdfapi/font/cpdf_fontglobals.h"
 #include "core/fpdfapi/parser/cpdf_array.h"
 #include "core/fpdfapi/parser/cpdf_dictionary.h"
 #include "core/fpdfapi/parser/cpdf_stream_acc.h"
@@ -127,10 +126,6 @@
 // Boundary value to avoid integer overflow when adding 1/64th of the value.
 constexpr int kMaxRectTop = 2114445437;
 
-CPDF_FontGlobals* GetFontGlobals() {
-  return CPDF_ModuleMgr::Get()->GetPageModule()->GetFontGlobals();
-}
-
 #if !defined(OS_WIN)
 
 bool IsValidEmbeddedCharcodeFromUnicodeCharset(CIDSet charset) {
@@ -157,7 +152,7 @@
     return 0;
 
   pdfium::span<const uint16_t> map =
-      GetFontGlobals()->GetEmbeddedToUnicode(charset);
+      CPDF_FontGlobals::GetInstance()->GetEmbeddedToUnicode(charset);
   return cid < map.size() ? map[cid] : 0;
 }
 
@@ -168,7 +163,7 @@
     return 0;
 
   pdfium::span<const uint16_t> map =
-      GetFontGlobals()->GetEmbeddedToUnicode(charset);
+      CPDF_FontGlobals::GetInstance()->GetEmbeddedToUnicode(charset);
   for (uint32_t i = 0; i < map.size(); ++i) {
     if (map[i] == unicode) {
       uint32_t charCode = CharCodeFromCID(pEmbedMap, i);
@@ -361,7 +356,7 @@
   ByteString subtype = pCIDFontDict->GetStringFor("Subtype");
   m_bType1 = (subtype == "CIDFontType0");
 
-  CPDF_CMapManager* manager = GetFontGlobals()->GetCMapManager();
+  CPDF_CMapManager* manager = CPDF_FontGlobals::GetInstance()->GetCMapManager();
   if (pEncoding->IsName()) {
     ByteString cmap = pEncoding->GetString();
     m_pCMap = manager->GetPredefinedCMap(cmap);
@@ -830,7 +825,7 @@
 
   m_Charset = CIDSET_GB1;
 
-  CPDF_CMapManager* manager = GetFontGlobals()->GetCMapManager();
+  CPDF_CMapManager* manager = CPDF_FontGlobals::GetInstance()->GetCMapManager();
   m_pCMap = manager->GetPredefinedCMap("GBK-EUC-H");
   m_pCID2UnicodeMap = manager->GetCID2UnicodeMap(m_Charset);
   if (!IsEmbedded())
diff --git a/core/fpdfapi/font/cpdf_cmap.cpp b/core/fpdfapi/font/cpdf_cmap.cpp
index 998ee71..8615084 100644
--- a/core/fpdfapi/font/cpdf_cmap.cpp
+++ b/core/fpdfapi/font/cpdf_cmap.cpp
@@ -11,11 +11,9 @@
 #include <vector>
 
 #include "core/fpdfapi/cmaps/cmap_int.h"
-#include "core/fpdfapi/cpdf_modulemgr.h"
 #include "core/fpdfapi/font/cpdf_cmapmanager.h"
 #include "core/fpdfapi/font/cpdf_cmapparser.h"
 #include "core/fpdfapi/font/cpdf_fontglobals.h"
-#include "core/fpdfapi/page/cpdf_pagemodule.h"
 #include "core/fpdfapi/parser/cpdf_simple_parser.h"
 
 namespace {
@@ -285,10 +283,8 @@
         m_MixedTwoByteLeadingBytes[b] = true;
     }
   }
-  CPDF_FontGlobals* pFontGlobals =
-      CPDF_ModuleMgr::Get()->GetPageModule()->GetFontGlobals();
-  m_pEmbedMap =
-      FindEmbeddedCMap(pFontGlobals->GetEmbeddedCharset(m_Charset), bsName);
+  m_pEmbedMap = FindEmbeddedCMap(
+      CPDF_FontGlobals::GetInstance()->GetEmbeddedCharset(m_Charset), bsName);
   if (!m_pEmbedMap)
     return;
 
diff --git a/core/fpdfapi/font/cpdf_cmapparser.cpp b/core/fpdfapi/font/cpdf_cmapparser.cpp
index 21be136..08336eb 100644
--- a/core/fpdfapi/font/cpdf_cmapparser.cpp
+++ b/core/fpdfapi/font/cpdf_cmapparser.cpp
@@ -9,8 +9,6 @@
 #include <vector>
 
 #include "core/fpdfapi/cmaps/cmap_int.h"
-#include "core/fpdfapi/cpdf_modulemgr.h"
-#include "core/fpdfapi/page/cpdf_pagemodule.h"
 #include "core/fpdfapi/parser/cpdf_array.h"
 #include "core/fpdfapi/parser/cpdf_dictionary.h"
 #include "core/fpdfapi/parser/cpdf_simple_parser.h"
diff --git a/core/fpdfapi/font/cpdf_font.cpp b/core/fpdfapi/font/cpdf_font.cpp
index 81e195b..fa68614 100644
--- a/core/fpdfapi/font/cpdf_font.cpp
+++ b/core/fpdfapi/font/cpdf_font.cpp
@@ -12,14 +12,14 @@
 #include <vector>
 
 #include "build/build_config.h"
-#include "core/fpdfapi/cpdf_modulemgr.h"
+#include "core/fpdfapi/font/cpdf_cidfont.h"
 #include "core/fpdfapi/font/cpdf_fontencoding.h"
+#include "core/fpdfapi/font/cpdf_fontglobals.h"
 #include "core/fpdfapi/font/cpdf_tounicodemap.h"
 #include "core/fpdfapi/font/cpdf_truetypefont.h"
 #include "core/fpdfapi/font/cpdf_type1font.h"
 #include "core/fpdfapi/font/cpdf_type3font.h"
 #include "core/fpdfapi/page/cpdf_docpagedata.h"
-#include "core/fpdfapi/page/cpdf_pagemodule.h"
 #include "core/fpdfapi/parser/cpdf_array.h"
 #include "core/fpdfapi/parser/cpdf_dictionary.h"
 #include "core/fpdfapi/parser/cpdf_document.h"
@@ -291,8 +291,7 @@
   if (font_id < 0)
     return nullptr;
 
-  CPDF_FontGlobals* pFontGlobals =
-      CPDF_ModuleMgr::Get()->GetPageModule()->GetFontGlobals();
+  auto* pFontGlobals = CPDF_FontGlobals::GetInstance();
   CPDF_Font* pFont = pFontGlobals->Find(pDoc, font_id);
   if (pFont)
     return pFont;
diff --git a/core/fpdfapi/font/cpdf_fontglobals.cpp b/core/fpdfapi/font/cpdf_fontglobals.cpp
index 9e2585f..a520466 100644
--- a/core/fpdfapi/font/cpdf_fontglobals.cpp
+++ b/core/fpdfapi/font/cpdf_fontglobals.cpp
@@ -13,12 +13,37 @@
 #include "third_party/base/ptr_util.h"
 #include "third_party/base/stl_util.h"
 
+namespace {
+
+CPDF_FontGlobals* g_FontGlobals = nullptr;
+
+}  // namespace
+
+// static
+void CPDF_FontGlobals::Create() {
+  ASSERT(!g_FontGlobals);
+  g_FontGlobals = new CPDF_FontGlobals();
+}
+
+// static
+void CPDF_FontGlobals::Destroy() {
+  ASSERT(g_FontGlobals);
+  delete g_FontGlobals;
+  g_FontGlobals = nullptr;
+}
+
+// static
+CPDF_FontGlobals* CPDF_FontGlobals::GetInstance() {
+  ASSERT(g_FontGlobals);
+  return g_FontGlobals;
+}
+
 CPDF_FontGlobals::CPDF_FontGlobals() {
   memset(m_EmbeddedCharsets, 0, sizeof(m_EmbeddedCharsets));
   memset(m_EmbeddedToUnicodes, 0, sizeof(m_EmbeddedToUnicodes));
 }
 
-CPDF_FontGlobals::~CPDF_FontGlobals() {}
+CPDF_FontGlobals::~CPDF_FontGlobals() = default;
 
 CPDF_Font* CPDF_FontGlobals::Find(CPDF_Document* pDoc, uint32_t index) {
   auto it = m_StockMap.find(pDoc);
diff --git a/core/fpdfapi/font/cpdf_fontglobals.h b/core/fpdfapi/font/cpdf_fontglobals.h
index 9f6adf2..fde71d8 100644
--- a/core/fpdfapi/font/cpdf_fontglobals.h
+++ b/core/fpdfapi/font/cpdf_fontglobals.h
@@ -18,8 +18,10 @@
 
 class CPDF_FontGlobals {
  public:
-  CPDF_FontGlobals();
-  ~CPDF_FontGlobals();
+  // Per-process singleton which must be managed by callers.
+  static void Create();
+  static void Destroy();
+  static CPDF_FontGlobals* GetInstance();
 
   void Clear(CPDF_Document* pDoc);
   CPDF_Font* Find(CPDF_Document* pDoc, uint32_t index);
@@ -45,6 +47,9 @@
   CPDF_CMapManager* GetCMapManager() { return &m_CMapManager; }
 
  private:
+  CPDF_FontGlobals();
+  ~CPDF_FontGlobals();
+
   CPDF_CMapManager m_CMapManager;
   pdfium::span<const FXCMAP_CMap> m_EmbeddedCharsets[CIDSET_NUM_SETS];
   pdfium::span<const uint16_t> m_EmbeddedToUnicodes[CIDSET_NUM_SETS];
diff --git a/core/fpdfapi/font/cpdf_tounicodemap.cpp b/core/fpdfapi/font/cpdf_tounicodemap.cpp
index 370c6df..aca7feb 100644
--- a/core/fpdfapi/font/cpdf_tounicodemap.cpp
+++ b/core/fpdfapi/font/cpdf_tounicodemap.cpp
@@ -8,9 +8,8 @@
 
 #include <utility>
 
-#include "core/fpdfapi/cpdf_modulemgr.h"
 #include "core/fpdfapi/font/cpdf_cid2unicodemap.h"
-#include "core/fpdfapi/page/cpdf_pagemodule.h"
+#include "core/fpdfapi/font/cpdf_fontglobals.h"
 #include "core/fpdfapi/parser/cpdf_simple_parser.h"
 #include "core/fpdfapi/parser/cpdf_stream.h"
 #include "core/fxcrt/fx_extension.h"
@@ -224,11 +223,9 @@
     }
   }
   if (cid_set) {
-    m_pBaseMap = CPDF_ModuleMgr::Get()
-                     ->GetPageModule()
-                     ->GetFontGlobals()
-                     ->GetCMapManager()
-                     ->GetCID2UnicodeMap(cid_set);
+    m_pBaseMap =
+        CPDF_FontGlobals::GetInstance()->GetCMapManager()->GetCID2UnicodeMap(
+            cid_set);
   } else {
     m_pBaseMap = nullptr;
   }
diff --git a/core/fpdfapi/page/cpdf_pagemodule.cpp b/core/fpdfapi/page/cpdf_pagemodule.cpp
index adc7793..95d23baf 100644
--- a/core/fpdfapi/page/cpdf_pagemodule.cpp
+++ b/core/fpdfapi/page/cpdf_pagemodule.cpp
@@ -6,6 +6,7 @@
 
 #include "core/fpdfapi/page/cpdf_pagemodule.h"
 
+#include "core/fpdfapi/font/cpdf_fontglobals.h"
 #include "core/fpdfapi/page/cpdf_colorspace.h"
 #include "core/fpdfapi/page/cpdf_devicecs.h"
 #include "core/fpdfapi/page/cpdf_patterncs.h"
@@ -16,12 +17,11 @@
       m_StockCMYKCS(pdfium::MakeRetain<CPDF_DeviceCS>(PDFCS_DEVICECMYK)),
       m_StockPatternCS(pdfium::MakeRetain<CPDF_PatternCS>(nullptr)) {
   m_StockPatternCS->InitializeStockPattern();
+  CPDF_FontGlobals::Create();
 }
 
-CPDF_PageModule::~CPDF_PageModule() = default;
-
-CPDF_FontGlobals* CPDF_PageModule::GetFontGlobals() {
-  return &m_FontGlobals;
+CPDF_PageModule::~CPDF_PageModule() {
+  CPDF_FontGlobals::Destroy();
 }
 
 RetainPtr<CPDF_ColorSpace> CPDF_PageModule::GetStockCS(int family) {
@@ -37,5 +37,5 @@
 }
 
 void CPDF_PageModule::ClearStockFont(CPDF_Document* pDoc) {
-  m_FontGlobals.Clear(pDoc);
+  CPDF_FontGlobals::GetInstance()->Clear(pDoc);
 }
diff --git a/core/fpdfapi/page/cpdf_pagemodule.h b/core/fpdfapi/page/cpdf_pagemodule.h
index ae6363d..cd078ea 100644
--- a/core/fpdfapi/page/cpdf_pagemodule.h
+++ b/core/fpdfapi/page/cpdf_pagemodule.h
@@ -7,7 +7,6 @@
 #ifndef CORE_FPDFAPI_PAGE_CPDF_PAGEMODULE_H_
 #define CORE_FPDFAPI_PAGE_CPDF_PAGEMODULE_H_
 
-#include "core/fpdfapi/font/cpdf_fontglobals.h"
 #include "core/fxcrt/retain_ptr.h"
 
 class CPDF_Document;
@@ -20,12 +19,10 @@
   CPDF_PageModule();
   ~CPDF_PageModule();
 
-  CPDF_FontGlobals* GetFontGlobals();
   RetainPtr<CPDF_ColorSpace> GetStockCS(int family);
   void ClearStockFont(CPDF_Document* pDoc);
 
  private:
-  CPDF_FontGlobals m_FontGlobals;
   RetainPtr<CPDF_DeviceCS> m_StockGrayCS;
   RetainPtr<CPDF_DeviceCS> m_StockRGBCS;
   RetainPtr<CPDF_DeviceCS> m_StockCMYKCS;
diff --git a/core/fpdfapi/parser/cpdf_document.cpp b/core/fpdfapi/parser/cpdf_document.cpp
index 0fca030..12149d0 100644
--- a/core/fpdfapi/parser/cpdf_document.cpp
+++ b/core/fpdfapi/parser/cpdf_document.cpp
@@ -25,11 +25,13 @@
 #include "core/fpdfapi/parser/cpdf_read_validator.h"
 #include "core/fpdfapi/parser/cpdf_reference.h"
 #include "core/fpdfapi/parser/cpdf_stream.h"
+#include "core/fpdfapi/parser/cpdf_stream_acc.h"
 #include "core/fpdfapi/parser/cpdf_string.h"
 #include "core/fpdfapi/render/cpdf_dibbase.h"
 #include "core/fpdfapi/render/cpdf_docrenderdata.h"
 #include "core/fxcodec/JBig2_DocumentContext.h"
 #include "core/fxcrt/fx_codepage.h"
+#include "core/fxge/cfx_font.h"
 #include "core/fxge/cfx_fontmapper.h"
 #include "core/fxge/cfx_substfont.h"
 #include "core/fxge/cfx_unicodeencoding.h"