Introduce unique_ptr deleters for FT objects.

Change-Id: I9dff4bbac8e60d5eda3b44367f65c964dcffd4f0
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/55755
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/core/fxge/android/cfpf_skiafontmgr.cpp b/core/fxge/android/cfpf_skiafontmgr.cpp
index 597e9f0..7d853ff 100644
--- a/core/fxge/android/cfpf_skiafontmgr.cpp
+++ b/core/fxge/android/cfpf_skiafontmgr.cpp
@@ -232,14 +232,19 @@
 CFPF_SkiaFontMgr::~CFPF_SkiaFontMgr() {
   m_FamilyFonts.clear();
   m_FontFaces.clear();
-  if (m_FTLibrary)
-    FT_Done_FreeType(m_FTLibrary);
 }
 
 bool CFPF_SkiaFontMgr::InitFTLibrary() {
-  if (!m_FTLibrary)
-    FT_Init_FreeType(&m_FTLibrary);
-  return !!m_FTLibrary;
+  if (m_FTLibrary)
+    return true;
+
+  FXFT_LibraryRec* pLibrary = nullptr;
+  FT_Init_FreeType(&pLibrary);
+  if (!pLibrary)
+    return false;
+
+  m_FTLibrary.reset(pLibrary);
+  return true;
 }
 
 void CFPF_SkiaFontMgr::LoadSystemFonts() {
@@ -342,7 +347,7 @@
   args.flags = FT_OPEN_PATHNAME;
   args.pathname = const_cast<FT_String*>(bsFile.unterminated_c_str());
   FXFT_FaceRec* face;
-  if (FT_Open_Face(m_FTLibrary, &args, iFaceIndex, &face))
+  if (FT_Open_Face(m_FTLibrary.get(), &args, iFaceIndex, &face))
     return nullptr;
   FT_Set_Pixel_Sizes(face, 0, 64);
   return face;
diff --git a/core/fxge/android/cfpf_skiafontmgr.h b/core/fxge/android/cfpf_skiafontmgr.h
index 49d1516..3b660f5 100644
--- a/core/fxge/android/cfpf_skiafontmgr.h
+++ b/core/fxge/android/cfpf_skiafontmgr.h
@@ -37,7 +37,7 @@
                                                 const ByteString& file);
 
   bool m_bLoaded = false;
-  FXFT_LibraryRec* m_FTLibrary = nullptr;
+  ScopedFXFTLibraryRec m_FTLibrary;
   std::vector<std::unique_ptr<CFPF_SkiaPathFont>> m_FontFaces;
   std::map<uint32_t, std::unique_ptr<CFPF_SkiaFont>> m_FamilyFonts;
 };
diff --git a/core/fxge/cfx_fontmapper.cpp b/core/fxge/cfx_fontmapper.cpp
index 9e792d0..c3df1cb 100644
--- a/core/fxge/cfx_fontmapper.cpp
+++ b/core/fxge/cfx_fontmapper.cpp
@@ -255,23 +255,9 @@
 
 }  // namespace
 
-CFX_FontMapper::CFX_FontMapper(CFX_FontMgr* mgr)
-    : m_bListLoaded(false), m_pFontMgr(mgr) {
-  m_MMFaces[0] = nullptr;
-  m_MMFaces[1] = nullptr;
-  memset(m_FoxitFaces, 0, sizeof(m_FoxitFaces));
-}
+CFX_FontMapper::CFX_FontMapper(CFX_FontMgr* mgr) : m_pFontMgr(mgr) {}
 
-CFX_FontMapper::~CFX_FontMapper() {
-  for (size_t i = 0; i < FX_ArraySize(m_FoxitFaces); ++i) {
-    if (m_FoxitFaces[i])
-      FT_Done_Face(m_FoxitFaces[i]);
-  }
-  if (m_MMFaces[0])
-    FT_Done_Face(m_MMFaces[0]);
-  if (m_MMFaces[1])
-    FT_Done_Face(m_MMFaces[1]);
-}
+CFX_FontMapper::~CFX_FontMapper() = default;
 
 void CFX_FontMapper::SetSystemFontInfo(
     std::unique_ptr<SystemFontInfoIface> pFontInfo) {
@@ -357,12 +343,13 @@
                                                int pitch_family) {
   if (iBaseFont < kNumStandardFonts) {
     if (m_FoxitFaces[iBaseFont])
-      return m_FoxitFaces[iBaseFont];
+      return m_FoxitFaces[iBaseFont].get();
     Optional<pdfium::span<const uint8_t>> font_data =
         m_pFontMgr->GetBuiltinFont(iBaseFont);
     if (font_data.has_value()) {
-      m_FoxitFaces[iBaseFont] = m_pFontMgr->GetFixedFace(font_data.value(), 0);
-      return m_FoxitFaces[iBaseFont];
+      m_FoxitFaces[iBaseFont].reset(
+          m_pFontMgr->GetFixedFace(font_data.value(), 0));
+      return m_FoxitFaces[iBaseFont].get();
     }
   }
   pSubstFont->m_bFlagMM = true;
@@ -373,17 +360,17 @@
     pSubstFont->m_Weight = pSubstFont->m_Weight * 4 / 5;
     pSubstFont->m_Family = "Chrome Serif";
     if (!m_MMFaces[1]) {
-      m_MMFaces[1] =
-          m_pFontMgr->GetFixedFace(m_pFontMgr->GetBuiltinFont(14).value(), 0);
+      m_MMFaces[1].reset(
+          m_pFontMgr->GetFixedFace(m_pFontMgr->GetBuiltinFont(14).value(), 0));
     }
-    return m_MMFaces[1];
+    return m_MMFaces[1].get();
   }
   pSubstFont->m_Family = "Chrome Sans";
   if (!m_MMFaces[0]) {
-    m_MMFaces[0] =
-        m_pFontMgr->GetFixedFace(m_pFontMgr->GetBuiltinFont(15).value(), 0);
+    m_MMFaces[0].reset(
+        m_pFontMgr->GetFixedFace(m_pFontMgr->GetBuiltinFont(15).value(), 0));
   }
-  return m_MMFaces[0];
+  return m_MMFaces[0].get();
 }
 
 FXFT_FaceRec* CFX_FontMapper::FindSubstFont(const ByteString& name,
@@ -673,11 +660,11 @@
 
 bool CFX_FontMapper::IsBuiltinFace(const FXFT_FaceRec* face) const {
   for (size_t i = 0; i < MM_FACE_COUNT; ++i) {
-    if (m_MMFaces[i] == face)
+    if (m_MMFaces[i].get() == face)
       return true;
   }
   for (size_t i = 0; i < FOXIT_FACE_COUNT; ++i) {
-    if (m_FoxitFaces[i] == face)
+    if (m_FoxitFaces[i].get() == face)
       return true;
   }
   return false;
diff --git a/core/fxge/cfx_fontmapper.h b/core/fxge/cfx_fontmapper.h
index 8096976..7b9b00b 100644
--- a/core/fxge/cfx_fontmapper.h
+++ b/core/fxge/cfx_fontmapper.h
@@ -71,13 +71,13 @@
     uint32_t charset;
   };
 
-  bool m_bListLoaded;
+  bool m_bListLoaded = false;
   ByteString m_LastFamily;
   std::vector<FaceData> m_FaceArray;
   std::unique_ptr<SystemFontInfoIface> m_pFontInfo;
   UnownedPtr<CFX_FontMgr> const m_pFontMgr;
-  FXFT_FaceRec* m_MMFaces[MM_FACE_COUNT];
-  FXFT_FaceRec* m_FoxitFaces[FOXIT_FACE_COUNT];
+  ScopedFXFTFaceRec m_MMFaces[MM_FACE_COUNT];
+  ScopedFXFTFaceRec m_FoxitFaces[FOXIT_FACE_COUNT];
 };
 
 #endif  // CORE_FXGE_CFX_FONTMAPPER_H_
diff --git a/core/fxge/cfx_fontmgr.cpp b/core/fxge/cfx_fontmgr.cpp
index aff16d1..28a7e1e 100644
--- a/core/fxge/cfx_fontmgr.cpp
+++ b/core/fxge/cfx_fontmgr.cpp
@@ -79,19 +79,15 @@
 CFX_FontMgr::CFX_FontMgr()
     : m_pBuiltinMapper(pdfium::MakeUnique<CFX_FontMapper>(this)) {}
 
-CFX_FontMgr::~CFX_FontMgr() {
-  // |m_FaceMap| and |m_pBuiltinMapper| reference |m_FTLibrary|, so they must
-  // be destroyed first.
-  m_FaceMap.clear();
-  m_pBuiltinMapper.reset();
-  FT_Done_FreeType(m_FTLibrary);
-}
+CFX_FontMgr::~CFX_FontMgr() = default;
 
 void CFX_FontMgr::InitFTLibrary() {
   if (m_FTLibrary)
     return;
 
-  FT_Init_FreeType(&m_FTLibrary);
+  FXFT_LibraryRec* pLibrary = nullptr;
+  FT_Init_FreeType(&pLibrary);
+  m_FTLibrary.reset(pLibrary);
   m_FTLibrarySupportsHinting =
       SetLcdFilterMode() || FreeTypeVersionSupportsHinting();
 }
@@ -137,8 +133,8 @@
   InitFTLibrary();
 
   FXFT_FaceRec* face = nullptr;
-  int ret =
-      FT_New_Memory_Face(m_FTLibrary, pData.get(), size, face_index, &face);
+  int ret = FT_New_Memory_Face(m_FTLibrary.get(), pData.get(), size, face_index,
+                               &face);
   if (ret)
     return nullptr;
 
@@ -192,8 +188,8 @@
                                         int face_index) {
   InitFTLibrary();
   FXFT_FaceRec* face = nullptr;
-  if (FT_New_Memory_Face(m_FTLibrary, span.data(), span.size(), face_index,
-                         &face)) {
+  if (FT_New_Memory_Face(m_FTLibrary.get(), span.data(), span.size(),
+                         face_index, &face)) {
     return nullptr;
   }
   return FT_Set_Pixel_Sizes(face, 64, 64) ? nullptr : face;
@@ -235,7 +231,7 @@
   FT_Int major;
   FT_Int minor;
   FT_Int patch;
-  FT_Library_Version(m_FTLibrary, &major, &minor, &patch);
+  FT_Library_Version(m_FTLibrary.get(), &major, &minor, &patch);
   // Freetype versions >= 2.8.1 support hinting even if subpixel rendering is
   // disabled. https://sourceforge.net/projects/freetype/files/freetype2/2.8.1/
   return major > 2 || (major == 2 && minor > 8) ||
@@ -243,6 +239,6 @@
 }
 
 bool CFX_FontMgr::SetLcdFilterMode() const {
-  return FT_Library_SetLcdFilter(m_FTLibrary, FT_LCD_FILTER_DEFAULT) !=
+  return FT_Library_SetLcdFilter(m_FTLibrary.get(), FT_LCD_FILTER_DEFAULT) !=
          FT_Err_Unimplemented_Feature;
 }
diff --git a/core/fxge/cfx_fontmgr.h b/core/fxge/cfx_fontmgr.h
index f021866..bb388db 100644
--- a/core/fxge/cfx_fontmgr.h
+++ b/core/fxge/cfx_fontmgr.h
@@ -63,16 +63,18 @@
   // Always present.
   CFX_FontMapper* GetBuiltinMapper() const { return m_pBuiltinMapper.get(); }
 
-  FXFT_LibraryRec* GetFTLibrary() const { return m_FTLibrary; }
+  FXFT_LibraryRec* GetFTLibrary() const { return m_FTLibrary.get(); }
   bool FTLibrarySupportsHinting() const { return m_FTLibrarySupportsHinting; }
 
  private:
   bool FreeTypeVersionSupportsHinting() const;
   bool SetLcdFilterMode() const;
 
+  // Must come before |m_pBuiltinMapper| and |m_FaceMap|.
+  ScopedFXFTLibraryRec m_FTLibrary;
+
   std::unique_ptr<CFX_FontMapper> m_pBuiltinMapper;
   std::map<ByteString, std::unique_ptr<CTTFontDesc>> m_FaceMap;
-  FXFT_LibraryRec* m_FTLibrary = nullptr;
   bool m_FTLibrarySupportsHinting = false;
 };
 
diff --git a/core/fxge/fx_freetype.h b/core/fxge/fx_freetype.h
index 0832d50..2dd379a 100644
--- a/core/fxge/fx_freetype.h
+++ b/core/fxge/fx_freetype.h
@@ -8,6 +8,9 @@
 #define CORE_FXGE_FX_FREETYPE_H_
 
 #include <ft2build.h>
+
+#include <memory>
+
 #include FT_FREETYPE_H
 #include FT_GLYPH_H
 #include FT_LCD_FILTER_H
@@ -20,6 +23,24 @@
 using FXFT_StreamRec = struct FT_StreamRec_;
 using FXFT_MM_VarPtr = FT_MM_Var*;
 
+struct FXFTFaceRecDeleter {
+  inline void operator()(FXFT_FaceRec* pRec) {
+    if (pRec)
+      FT_Done_Face(pRec);
+  }
+};
+
+struct FXFTLibraryRecDeleter {
+  inline void operator()(FXFT_LibraryRec* pRec) {
+    if (pRec)
+      FT_Done_FreeType(pRec);
+  }
+};
+
+using ScopedFXFTFaceRec = std::unique_ptr<FXFT_FaceRec, FXFTFaceRecDeleter>;
+using ScopedFXFTLibraryRec =
+    std::unique_ptr<FXFT_LibraryRec, FXFTLibraryRecDeleter>;
+
 #define FXFT_Select_Charmap(face, encoding) \
   FT_Select_Charmap(face, static_cast<FT_Encoding>(encoding))
 #define FXFT_Get_Name_Index(face, name) \