Avoid FT_FaceRec usage in various places

Switch various FT_FaceRec usage with CFX_Face instead.

- Implement CFX_Face::GetGlyphCount() and convert callers.
- Implement CFX_Face::CanEmbed() and convert caller.

Bug: pdfium:2037
Change-Id: Ifc0e9c55b266f70af20b209aa0ec7417f67f7f90
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/114777
Reviewed-by: Dominik Röttsches <drott@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
diff --git a/core/fpdfapi/font/cpdf_cidfont.cpp b/core/fpdfapi/font/cpdf_cidfont.cpp
index 3acb32c..b6cf44d 100644
--- a/core/fpdfapi/font/cpdf_cidfont.cpp
+++ b/core/fpdfapi/font/cpdf_cidfont.cpp
@@ -194,7 +194,7 @@
 
 #endif  // !BUILDFLAG(IS_WIN)
 
-void FT_UseCIDCharmap(const RetainPtr<CFX_Face>& face, CIDCoding coding) {
+void UseCIDCharmap(const RetainPtr<CFX_Face>& face, CIDCoding coding) {
   fxge::FontEncoding encoding;
   switch (coding) {
     case CIDCoding::kGB:
@@ -469,11 +469,13 @@
   if (m_Charset != CIDSET_UNKNOWN) {
     m_pCID2UnicodeMap = pFontGlobals->GetCID2UnicodeMap(m_Charset);
   }
-  if (m_Font.GetFaceRec()) {
-    if (m_FontType == CIDFontType::kType1)
-      m_Font.GetFace()->SelectCharMap(fxge::FontEncoding::kUnicode);
-    else
-      FT_UseCIDCharmap(m_Font.GetFace(), m_pCMap->GetCoding());
+  RetainPtr<CFX_Face> face = m_Font.GetFace();
+  if (face) {
+    if (m_FontType == CIDFontType::kType1) {
+      face->SelectCharMap(fxge::FontEncoding::kUnicode);
+    } else {
+      UseCIDCharmap(face, m_pCMap->GetCoding());
+    }
   }
   m_DefaultWidth = pCIDFontDict->GetIntegerFor("DW", 1000);
   RetainPtr<const CPDF_Array> pWidthArray = pCIDFontDict->GetArrayFor("W");
@@ -713,7 +715,6 @@
           unicode = unicode_str[0];
       }
     }
-    FXFT_FaceRec* face_rec = m_Font.GetFaceRec();
     if (unicode == 0) {
       if (!m_bAdobeCourierStd)
         return charcode ? static_cast<int>(charcode) : -1;
@@ -763,11 +764,12 @@
 #endif
       }
     }
-    if (!face_rec) {
+
+    RetainPtr<CFX_Face> face = m_Font.GetFace();
+    if (!face) {
       return unicode;
     }
 
-    RetainPtr<CFX_Face> face = m_Font.GetFace();
     size_t num_charmaps = face->GetCharMapCount();
     if (!face->SelectCharMap(fxge::FontEncoding::kUnicode)) {
       size_t i;
@@ -792,8 +794,10 @@
     return unicode;
   }
 
-  if (!m_Font.GetFaceRec())
+  RetainPtr<CFX_Face> face = m_Font.GetFace();
+  if (!face) {
     return -1;
+  }
 
   uint16_t cid = CIDFromCharCode(charcode);
   if (!m_pStreamAcc) {
@@ -808,7 +812,7 @@
     }
 
     absl::optional<fxge::FontEncoding> charmap =
-        m_Font.GetFace()->GetCurrentCharMapEncoding();
+        face->GetCurrentCharMapEncoding();
     if (!charmap.has_value()) {
       return cid;
     }
diff --git a/core/fpdfapi/font/cpdf_font.h b/core/fpdfapi/font/cpdf_font.h
index 5adce94..e2f9cf3 100644
--- a/core/fpdfapi/font/cpdf_font.h
+++ b/core/fpdfapi/font/cpdf_font.h
@@ -107,7 +107,7 @@
   }
   void ClearFontDict() { m_pFontDict = nullptr; }
   bool IsStandardFont() const;
-  bool HasFace() const { return !!m_Font.GetFaceRec(); }
+  bool HasFace() const { return !!m_Font.GetFace(); }
   void AppendChar(ByteString* str, uint32_t charcode) const;
 
   const FX_RECT& GetFontBBox() const { return m_FontBBox; }
diff --git a/core/fpdfapi/font/cpdf_simplefont.cpp b/core/fpdfapi/font/cpdf_simplefont.cpp
index dba78b6..eecdf5a 100644
--- a/core/fpdfapi/font/cpdf_simplefont.cpp
+++ b/core/fpdfapi/font/cpdf_simplefont.cpp
@@ -237,8 +237,9 @@
   LoadPDFEncoding(!!m_pFontFile, m_Font.IsTTFont());
   LoadGlyphMap();
   m_CharNames.clear();
-  if (!m_Font.GetFaceRec())
+  if (!HasFace()) {
     return true;
+  }
 
   if (FontStyleIsAllCaps(m_Flags)) {
     static const unsigned char kLowercases[][2] = {
diff --git a/core/fxge/android/cfpf_skiafontmgr.cpp b/core/fxge/android/cfpf_skiafontmgr.cpp
index 59db044..13089d6 100644
--- a/core/fxge/android/cfpf_skiafontmgr.cpp
+++ b/core/fxge/android/cfpf_skiafontmgr.cpp
@@ -408,5 +408,5 @@
 
   return std::make_unique<CFPF_SkiaPathFont>(
       file, face->GetFamilyName(), dwStyle, face->GetRec()->face_index, charset,
-      face->GetRec()->num_glyphs);
+      face->GetGlyphCount());
 }
diff --git a/core/fxge/cfx_face.cpp b/core/fxge/cfx_face.cpp
index 99574af..265fa1b 100644
--- a/core/fxge/cfx_face.cpp
+++ b/core/fxge/cfx_face.cpp
@@ -429,6 +429,10 @@
   return std::array<uint8_t, 2>{os2->panose[0], os2->panose[1]};
 }
 
+int CFX_Face::GetGlyphCount() const {
+  return pdfium::base::checked_cast<int>(GetRec()->num_glyphs);
+}
+
 std::unique_ptr<CFX_GlyphBitmap> CFX_Face::RenderGlyph(const CFX_Font* pFont,
                                                        uint32_t glyph_index,
                                                        bool bFontStyle,
@@ -714,6 +718,14 @@
   return !error;
 }
 
+#if BUILDFLAG(IS_WIN)
+bool CFX_Face::CanEmbed() {
+  FT_UShort fstype = FT_Get_FSType_Flags(GetRec());
+  return (fstype & (FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING |
+                    FT_FSTYPE_BITMAP_EMBEDDING_ONLY)) == 0;
+}
+#endif
+
 CFX_Face::CFX_Face(FXFT_FaceRec* rec, RetainPtr<Retainable> pDesc)
     : m_pRec(rec), m_pDesc(std::move(pDesc)) {
   DCHECK(m_pRec);
diff --git a/core/fxge/cfx_face.h b/core/fxge/cfx_face.h
index 551f358..944d731 100644
--- a/core/fxge/cfx_face.h
+++ b/core/fxge/cfx_face.h
@@ -83,6 +83,7 @@
   absl::optional<std::array<uint32_t, 2>> GetOs2CodePageRange();
   absl::optional<std::array<uint8_t, 2>> GetOs2Panose();
 
+  int GetGlyphCount() const;
   std::unique_ptr<CFX_GlyphBitmap> RenderGlyph(const CFX_Font* pFont,
                                                uint32_t glyph_index,
                                                bool bFontStyle,
@@ -113,6 +114,10 @@
   void SetCharMapByIndex(size_t index);
   bool SelectCharMap(fxge::FontEncoding encoding);
 
+#if BUILDFLAG(IS_WIN)
+  bool CanEmbed();
+#endif
+
   FXFT_FaceRec* GetRec() { return m_pRec.get(); }
   const FXFT_FaceRec* GetRec() const { return m_pRec.get(); }
 
diff --git a/core/fxge/cfx_glyphcache.cpp b/core/fxge/cfx_glyphcache.cpp
index a5610c6..c686f1b 100644
--- a/core/fxge/cfx_glyphcache.cpp
+++ b/core/fxge/cfx_glyphcache.cpp
@@ -124,8 +124,9 @@
 const CFX_Path* CFX_GlyphCache::LoadGlyphPath(const CFX_Font* pFont,
                                               uint32_t glyph_index,
                                               int dest_width) {
-  if (!GetFaceRec() || glyph_index == kInvalidGlyphIndex)
+  if (!GetFace() || glyph_index == kInvalidGlyphIndex) {
     return nullptr;
+  }
 
   const auto* pSubstFont = pFont->GetSubstFont();
   int weight = pSubstFont ? pSubstFont->m_Weight : 0;
diff --git a/core/fxge/cfx_glyphcache.h b/core/fxge/cfx_glyphcache.h
index 895d062..9390052 100644
--- a/core/fxge/cfx_glyphcache.h
+++ b/core/fxge/cfx_glyphcache.h
@@ -47,7 +47,6 @@
                     int weight);
 
   RetainPtr<CFX_Face> GetFace() { return m_Face; }
-  FXFT_FaceRec* GetFaceRec() { return m_Face ? m_Face->GetRec() : nullptr; }
 
 #if defined(PDF_USE_SKIA)
   CFX_TypeFace* GetDeviceCache(const CFX_Font* pFont);
diff --git a/core/fxge/cfx_unicodeencodingex.cpp b/core/fxge/cfx_unicodeencodingex.cpp
index 5fcf5a1..ee981b4 100644
--- a/core/fxge/cfx_unicodeencodingex.cpp
+++ b/core/fxge/cfx_unicodeencodingex.cpp
@@ -86,8 +86,9 @@
 
 std::unique_ptr<CFX_UnicodeEncodingEx> FX_CreateFontEncodingEx(
     CFX_Font* pFont) {
-  if (!pFont || !pFont->GetFaceRec())
+  if (!pFont || !pFont->GetFace()) {
     return nullptr;
+  }
 
   for (fxge::FontEncoding id : kEncodingIDs) {
     auto pFontEncoding = FXFM_CreateFontEncoding(pFont, id);
diff --git a/core/fxge/win32/cfx_psrenderer.cpp b/core/fxge/win32/cfx_psrenderer.cpp
index c2da036..2815d28 100644
--- a/core/fxge/win32/cfx_psrenderer.cpp
+++ b/core/fxge/win32/cfx_psrenderer.cpp
@@ -32,7 +32,6 @@
 #include "core/fxge/dib/cfx_dibbase.h"
 #include "core/fxge/dib/cfx_dibitmap.h"
 #include "core/fxge/dib/fx_dib.h"
-#include "core/fxge/freetype/fx_freetype.h"
 #include "core/fxge/text_char_pos.h"
 #include "core/fxge/win32/cfx_psfonttracker.h"
 #include "third_party/base/check_op.h"
@@ -40,12 +39,6 @@
 
 namespace {
 
-bool CanEmbed(CFX_Font* font) {
-  FT_UShort fstype = FT_Get_FSType_Flags(font->GetFaceRec());
-  return (fstype & (FT_FSTYPE_RESTRICTED_LICENSE_EMBEDDING |
-                    FT_FSTYPE_BITMAP_EMBEDDING_ONLY)) == 0;
-}
-
 absl::optional<ByteString> GenerateType42SfntData(
     const ByteString& psname,
     pdfium::span<const uint8_t> font_data) {
@@ -164,9 +157,15 @@
 }
 
 ByteString GenerateType42FontData(const CFX_Font* font) {
-  const FXFT_FaceRec* font_face_rec = font->GetFaceRec();
-  if (!font_face_rec)
+  RetainPtr<const CFX_Face> face = font->GetFace();
+  if (!face) {
     return ByteString();
+  }
+
+  int num_glyphs = face->GetGlyphCount();
+  if (num_glyphs < 0) {
+    return ByteString();
+  }
 
   const ByteString psname = font->GetPsName();
   DCHECK(!psname.IsEmpty());
@@ -181,8 +180,7 @@
   output += "\n";
   output += sfnt_data.value();
   output += GenerateType42FontDictionary(psname, font->GetRawBBox().value(),
-                                         font_face_rec->num_glyphs,
-                                         kGlyphsPerDescendantFont);
+                                         num_glyphs, kGlyphsPerDescendantFont);
   return output;
 }
 
@@ -766,8 +764,14 @@
                                           CFX_Font* font,
                                           float font_size,
                                           fxcrt::ostringstream& buf) {
-  if (m_Level != RenderingLevel::kLevel3Type42 || !CanEmbed(font))
+  if (m_Level != RenderingLevel::kLevel3Type42) {
     return false;
+  }
+
+  RetainPtr<CFX_Face> face = font->GetFace();
+  if (!face || !face->CanEmbed()) {
+    return false;
+  }
 
   if (font->GetFontType() != CFX_Font::FontType::kCIDTrueType)
     return false;
diff --git a/fpdfsdk/fpdf_edittext.cpp b/fpdfsdk/fpdf_edittext.cpp
index 608a4db..54bf4a4 100644
--- a/fpdfsdk/fpdf_edittext.cpp
+++ b/fpdfsdk/fpdf_edittext.cpp
@@ -306,14 +306,15 @@
   pFontDict->SetNewFor<CPDF_Name>("BaseFont", name);
 
   // If it doesn't have a single char, just fail.
-  if (pFont->GetFaceRec()->num_glyphs <= 0) {
+  RetainPtr<CFX_Face> face = pFont->GetFace();
+  if (face->GetGlyphCount() <= 0) {
     return nullptr;
   }
 
   // Simple fonts have 1-byte charcodes only.
   static constexpr uint32_t kMaxSimpleFontChar = 0xFF;
   auto char_codes_and_indices =
-      pFont->GetFace()->GetCharCodesAndIndices(kMaxSimpleFontChar);
+      face->GetCharCodesAndIndices(kMaxSimpleFontChar);
   if (char_codes_and_indices.empty()) {
     return nullptr;
   }
@@ -379,12 +380,13 @@
                                       pFontDesc->GetObjNum());
 
   // If it doesn't have a single char, just fail.
-  if (pFont->GetFaceRec()->num_glyphs <= 0) {
+  RetainPtr<CFX_Face> face = pFont->GetFace();
+  if (face->GetGlyphCount() <= 0) {
     return nullptr;
   }
 
-  auto char_codes_and_indices = pFont->GetFace()->GetCharCodesAndIndices(
-      pdfium::kMaximumSupplementaryCodePoint);
+  auto char_codes_and_indices =
+      face->GetCharCodesAndIndices(pdfium::kMaximumSupplementaryCodePoint);
   if (char_codes_and_indices.empty()) {
     return nullptr;
   }
diff --git a/xfa/fgas/font/cfgas_gefont.cpp b/xfa/fgas/font/cfgas_gefont.cpp
index 369ea78..35e8de5 100644
--- a/xfa/fgas/font/cfgas_gefont.cpp
+++ b/xfa/fgas/font/cfgas_gefont.cpp
@@ -89,7 +89,7 @@
 
   m_pFont->LoadSubst(csFontFamily, true, dwFontStyles, iWeight, 0, wCodePage,
                      false);
-  return m_pFont->GetFaceRec() && InitFont();
+  return m_pFont->GetFace() && InitFont();
 }
 #endif  // BUILDFLAG(IS_WIN)