Encapsulate font metrics code inside CFX_Face

Instead of directly calling FreeType code on the handle returned by
CFX_Face::GetRec(), add CFX_Face methods for reading font metrics.

Bug: pdfium:2037
Change-Id: Ida247f6c6b45143a59fd2695b6b89e797c171a80
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/107495
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Dominik Röttsches <drott@chromium.org>
diff --git a/core/fpdfapi/font/cpdf_cidfont.cpp b/core/fpdfapi/font/cpdf_cidfont.cpp
index a8d14bf..f9beb2f 100644
--- a/core/fpdfapi/font/cpdf_cidfont.cpp
+++ b/core/fpdfapi/font/cpdf_cidfont.cpp
@@ -522,14 +522,15 @@
   FX_RECT rect;
   bool bVert = false;
   int glyph_index = GlyphFromCharCode(charcode, &bVert);
-  FXFT_FaceRec* face = m_Font.GetFaceRec();
+  RetainPtr<CFX_Face> face = m_Font.GetFace();
   if (face) {
-    if (m_Font.GetFace()->IsTricky()) {
-      int err =
-          FT_Load_Glyph(face, glyph_index, FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH);
+    FXFT_FaceRec* face_rec = face->GetRec();
+    if (face->IsTricky()) {
+      int err = FT_Load_Glyph(face_rec, glyph_index,
+                              FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH);
       if (!err) {
         FT_Glyph glyph;
-        err = FT_Get_Glyph(face->glyph, &glyph);
+        err = FT_Get_Glyph(face_rec->glyph, &glyph);
         if (!err) {
           FT_BBox cbox;
           FT_Glyph_Get_CBox(glyph, FT_GLYPH_BBOX_PIXELS, &cbox);
@@ -537,8 +538,8 @@
           const int xMax = FTPosToCBoxInt(cbox.xMax);
           const int yMin = FTPosToCBoxInt(cbox.yMin);
           const int yMax = FTPosToCBoxInt(cbox.yMax);
-          const int pixel_size_x = face->size->metrics.x_ppem;
-          const int pixel_size_y = face->size->metrics.y_ppem;
+          const int pixel_size_x = face_rec->size->metrics.x_ppem;
+          const int pixel_size_y = face_rec->size->metrics.y_ppem;
           if (pixel_size_x == 0 || pixel_size_y == 0) {
             rect = FX_RECT(xMin, yMax, xMax, yMin);
           } else {
@@ -546,15 +547,14 @@
                 FX_RECT(xMin * 1000 / pixel_size_x, yMax * 1000 / pixel_size_y,
                         xMax * 1000 / pixel_size_x, yMin * 1000 / pixel_size_y);
           }
-          rect.top = std::min(rect.top,
-                              static_cast<int>(FXFT_Get_Face_Ascender(face)));
-          rect.bottom = std::max(
-              rect.bottom, static_cast<int>(FXFT_Get_Face_Descender(face)));
+          rect.top = std::min(rect.top, static_cast<int>(face->GetAscender()));
+          rect.bottom =
+              std::max(rect.bottom, static_cast<int>(face->GetDescender()));
           FT_Done_Glyph(glyph);
         }
       }
     } else {
-      int err = FT_Load_Glyph(face, glyph_index, FT_LOAD_NO_SCALE);
+      int err = FT_Load_Glyph(face_rec, glyph_index, FT_LOAD_NO_SCALE);
       if (err == 0) {
         rect = GetCharBBoxForFace(face);
         if (rect.top <= kMaxRectTop)
diff --git a/core/fpdfapi/font/cpdf_font.cpp b/core/fpdfapi/font/cpdf_font.cpp
index 5eab3cd..3c5d1b6 100644
--- a/core/fpdfapi/font/cpdf_font.cpp
+++ b/core/fpdfapi/font/cpdf_font.cpp
@@ -218,16 +218,16 @@
 void CPDF_Font::CheckFontMetrics() {
   if (m_FontBBox.top == 0 && m_FontBBox.bottom == 0 && m_FontBBox.left == 0 &&
       m_FontBBox.right == 0) {
-    FXFT_FaceRec* face = m_Font.GetFaceRec();
+    RetainPtr<CFX_Face> face = m_Font.GetFace();
     if (face) {
       // Note that `m_FontBBox` is deliberately flipped.
-      const FX_RECT raw_bbox = m_Font.GetFace()->GetBBox();
+      const FX_RECT raw_bbox = face->GetBBox();
       m_FontBBox.left = TT2PDF(raw_bbox.left, face);
       m_FontBBox.bottom = TT2PDF(raw_bbox.top, face);
       m_FontBBox.right = TT2PDF(raw_bbox.right, face);
       m_FontBBox.top = TT2PDF(raw_bbox.bottom, face);
-      m_Ascent = TT2PDF(FXFT_Get_Face_Ascender(face), face);
-      m_Descent = TT2PDF(FXFT_Get_Face_Descender(face), face);
+      m_Ascent = TT2PDF(face->GetAscender(), face);
+      m_Descent = TT2PDF(face->GetDescender(), face);
     } else {
       bool bFirst = true;
       for (int i = 0; i < 256; i++) {
@@ -408,8 +408,8 @@
 }
 
 // static
-int CPDF_Font::TT2PDF(FT_Pos m, FXFT_FaceRec* face) {
-  int upm = FXFT_Get_Face_UnitsPerEM(face);
+int CPDF_Font::TT2PDF(FT_Pos m, const RetainPtr<CFX_Face>& face) {
+  int upm = face->GetUnitsPerEm();
   if (upm == 0)
     return pdfium::base::saturated_cast<int>(m);
 
@@ -418,12 +418,13 @@
 }
 
 // static
-FX_RECT CPDF_Font::GetCharBBoxForFace(FXFT_FaceRec* face) {
-  pdfium::base::ClampedNumeric<FT_Pos> left = FXFT_Get_Glyph_HoriBearingX(face);
-  pdfium::base::ClampedNumeric<FT_Pos> top = FXFT_Get_Glyph_HoriBearingY(face);
+FX_RECT CPDF_Font::GetCharBBoxForFace(const RetainPtr<CFX_Face>& face) {
+  FXFT_FaceRec* rec = face->GetRec();
+  pdfium::base::ClampedNumeric<FT_Pos> left = FXFT_Get_Glyph_HoriBearingX(rec);
+  pdfium::base::ClampedNumeric<FT_Pos> top = FXFT_Get_Glyph_HoriBearingY(rec);
   return FX_RECT(TT2PDF(left, face), TT2PDF(top, face),
-                 TT2PDF(left + FXFT_Get_Glyph_Width(face), face),
-                 TT2PDF(top - FXFT_Get_Glyph_Height(face), face));
+                 TT2PDF(left + FXFT_Get_Glyph_Width(rec), face),
+                 TT2PDF(top - FXFT_Get_Glyph_Height(rec), face));
 }
 
 // static
diff --git a/core/fpdfapi/font/cpdf_font.h b/core/fpdfapi/font/cpdf_font.h
index c3ac83a..c8c46b1 100644
--- a/core/fpdfapi/font/cpdf_font.h
+++ b/core/fpdfapi/font/cpdf_font.h
@@ -139,8 +139,8 @@
   CPDF_Font(CPDF_Document* pDocument, RetainPtr<CPDF_Dictionary> pFontDict);
   ~CPDF_Font() override;
 
-  static int TT2PDF(FT_Pos m, FXFT_FaceRec* face);
-  static FX_RECT GetCharBBoxForFace(FXFT_FaceRec* face);
+  static int TT2PDF(FT_Pos m, const RetainPtr<CFX_Face>& face);
+  static FX_RECT GetCharBBoxForFace(const RetainPtr<CFX_Face>& face);
 
   // Commonly used wrappers for UseTTCharmap().
   static bool UseTTCharmapMSUnicode(FXFT_FaceRec* face) {
diff --git a/core/fpdfapi/font/cpdf_simplefont.cpp b/core/fpdfapi/font/cpdf_simplefont.cpp
index f9f516b..dba78b6 100644
--- a/core/fpdfapi/font/cpdf_simplefont.cpp
+++ b/core/fpdfapi/font/cpdf_simplefont.cpp
@@ -76,9 +76,14 @@
     }
     return;
   }
-  FXFT_FaceRec* face = m_Font.GetFaceRec();
+  RetainPtr<CFX_Face> face = m_Font.GetFace();
+  if (!face) {
+    return;
+  }
+
+  FXFT_FaceRec* face_rec = face->GetRec();
   int err =
-      FT_Load_Glyph(face, glyph_index,
+      FT_Load_Glyph(face_rec, glyph_index,
                     FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH);
   if (err)
     return;
@@ -86,7 +91,7 @@
   m_CharBBox[charcode] = GetCharBBoxForFace(face);
 
   if (m_bUseFontWidth) {
-    int TT_Width = TT2PDF(FXFT_Get_Glyph_HoriAdvance(face), face);
+    int TT_Width = TT2PDF(FXFT_Get_Glyph_HoriAdvance(face_rec), face);
     if (m_CharWidth[charcode] == 0xffff) {
       m_CharWidth[charcode] = TT_Width;
     } else if (TT_Width && !IsEmbedded()) {
diff --git a/core/fxge/android/cfpf_skiafont.cpp b/core/fxge/android/cfpf_skiafont.cpp
index 053b1c4..47423e5 100644
--- a/core/fxge/android/cfpf_skiafont.cpp
+++ b/core/fxge/android/cfpf_skiafont.cpp
@@ -57,23 +57,20 @@
                     FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH)) {
     return 0;
   }
-  return static_cast<int32_t>(
-      FPF_EM_ADJUST(FXFT_Get_Face_UnitsPerEM(GetFaceRec()),
-                    FXFT_Get_Glyph_HoriAdvance(GetFaceRec())));
+  return static_cast<int32_t>(FPF_EM_ADJUST(
+      m_Face->GetUnitsPerEm(), FXFT_Get_Glyph_HoriAdvance(GetFaceRec())));
 }
 
 int32_t CFPF_SkiaFont::GetAscent() const {
   if (!m_Face)
     return 0;
-  return FPF_EM_ADJUST(FXFT_Get_Face_UnitsPerEM(GetFaceRec()),
-                       FXFT_Get_Face_Ascender(GetFaceRec()));
+  return FPF_EM_ADJUST(m_Face->GetUnitsPerEm(), m_Face->GetAscender());
 }
 
 int32_t CFPF_SkiaFont::GetDescent() const {
   if (!m_Face)
     return 0;
-  return FPF_EM_ADJUST(FXFT_Get_Face_UnitsPerEM(GetFaceRec()),
-                       FXFT_Get_Face_Descender(GetFaceRec()));
+  return FPF_EM_ADJUST(m_Face->GetUnitsPerEm(), m_Face->GetDescender());
 }
 
 bool CFPF_SkiaFont::GetGlyphBBox(int32_t iGlyphIndex, FX_RECT& rtBBox) {
@@ -109,7 +106,7 @@
                     FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH)) {
     return false;
   }
-  const FT_UShort em = FXFT_Get_Face_UnitsPerEM(GetFaceRec());
+  const uint16_t em = m_Face->GetUnitsPerEm();
   rtBBox.left = static_cast<int32_t>(
       FPF_EM_ADJUST(em, FXFT_Get_Glyph_HoriBearingX(GetFaceRec())));
   rtBBox.bottom = static_cast<int32_t>(
@@ -128,7 +125,7 @@
     return false;
   }
 
-  const FT_UShort em = FXFT_Get_Face_UnitsPerEM(GetFaceRec());
+  const uint16_t em = m_Face->GetUnitsPerEm();
   const FX_RECT raw_bbox = m_Face->GetBBox();
   rtBBox.left = static_cast<int32_t>(FPF_EM_ADJUST(em, raw_bbox.left));
   rtBBox.top = static_cast<int32_t>(FPF_EM_ADJUST(em, raw_bbox.top));
@@ -140,8 +137,7 @@
 int32_t CFPF_SkiaFont::GetHeight() const {
   if (!m_Face)
     return 0;
-  return FPF_EM_ADJUST(FXFT_Get_Face_UnitsPerEM(GetFaceRec()),
-                       FXFT_Get_Face_Height(GetFaceRec()));
+  return FPF_EM_ADJUST(m_Face->GetUnitsPerEm(), m_Face->GetHeight());
 }
 
 int32_t CFPF_SkiaFont::GetItalicAngle() const {
diff --git a/core/fxge/cfx_face.cpp b/core/fxge/cfx_face.cpp
index a1a40e5..71a6ead 100644
--- a/core/fxge/cfx_face.cpp
+++ b/core/fxge/cfx_face.cpp
@@ -85,6 +85,24 @@
                  pdfium::base::checked_cast<int32_t>(GetRec()->bbox.yMax));
 }
 
+uint16_t CFX_Face::GetUnitsPerEm() const {
+  return pdfium::base::checked_cast<uint16_t>(GetRec()->units_per_EM);
+}
+
+int16_t CFX_Face::GetAscender() const {
+  return pdfium::base::checked_cast<int16_t>(GetRec()->ascender);
+}
+
+int16_t CFX_Face::GetDescender() const {
+  return pdfium::base::checked_cast<int16_t>(GetRec()->descender);
+}
+
+#if BUILDFLAG(IS_ANDROID)
+int16_t CFX_Face::GetHeight() const {
+  return pdfium::base::checked_cast<int16_t>(GetRec()->height);
+}
+#endif
+
 pdfium::span<uint8_t> CFX_Face::GetData() const {
   return {GetRec()->stream->base, GetRec()->stream->size};
 }
diff --git a/core/fxge/cfx_face.h b/core/fxge/cfx_face.h
index 5a71ad1..8040c69 100644
--- a/core/fxge/cfx_face.h
+++ b/core/fxge/cfx_face.h
@@ -5,6 +5,9 @@
 #ifndef CORE_FXGE_CFX_FACE_H_
 #define CORE_FXGE_CFX_FACE_H_
 
+#include <stdint.h>
+
+#include "build/build_config.h"
 #include "core/fxcrt/bytestring.h"
 #include "core/fxcrt/fx_coordinates.h"
 #include "core/fxcrt/observed_ptr.h"
@@ -40,6 +43,12 @@
   ByteString GetStyleName() const;
 
   FX_RECT GetBBox() const;
+  uint16_t GetUnitsPerEm() const;
+  int16_t GetAscender() const;
+  int16_t GetDescender() const;
+#if BUILDFLAG(IS_ANDROID)
+  int16_t GetHeight() const;
+#endif
 
   pdfium::span<uint8_t> GetData() const;
 
diff --git a/core/fxge/cfx_font.cpp b/core/fxge/cfx_font.cpp
index fc19771..39a6445 100644
--- a/core/fxge/cfx_font.cpp
+++ b/core/fxge/cfx_font.cpp
@@ -414,8 +414,7 @@
   if (horiAdvance < kThousandthMinInt || horiAdvance > kThousandthMaxInt)
     return 0;
 
-  return static_cast<int>(
-      EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face->GetRec()), horiAdvance));
+  return static_cast<int>(EM_ADJUST(m_Face->GetUnitsPerEm(), horiAdvance));
 }
 
 bool CFX_Font::LoadEmbedded(pdfium::span<const uint8_t> src_span,
@@ -439,22 +438,22 @@
   if (!m_Face)
     return 0;
 
-  int ascender = FXFT_Get_Face_Ascender(m_Face->GetRec());
+  int ascender = m_Face->GetAscender();
   if (ascender < kThousandthMinInt || ascender > kThousandthMaxInt)
     return 0;
 
-  return EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face->GetRec()), ascender);
+  return EM_ADJUST(m_Face->GetUnitsPerEm(), ascender);
 }
 
 int CFX_Font::GetDescent() const {
   if (!m_Face)
     return 0;
 
-  int descender = FXFT_Get_Face_Descender(m_Face->GetRec());
+  int descender = m_Face->GetDescender();
   if (descender < kThousandthMinInt || descender > kThousandthMaxInt)
     return 0;
 
-  return EM_ADJUST(FXFT_Get_Face_UnitsPerEM(m_Face->GetRec()), descender);
+  return EM_ADJUST(m_Face->GetUnitsPerEm(), descender);
 }
 
 absl::optional<FX_RECT> CFX_Font::GetGlyphBBox(uint32_t glyph_index) {
@@ -482,12 +481,9 @@
     int pixel_size_y = m_Face->GetRec()->size->metrics.y_ppem;
     FX_RECT result = ScaledFXRectFromFTPos(
         cbox.xMin, cbox.yMax, cbox.xMax, cbox.yMin, pixel_size_x, pixel_size_y);
-    result.top =
-        std::min(result.top, pdfium::base::checked_cast<int32_t>(
-                                 FXFT_Get_Face_Ascender(m_Face->GetRec())));
+    result.top = std::min(result.top, static_cast<int>(m_Face->GetAscender()));
     result.bottom =
-        std::max(result.bottom, pdfium::base::checked_cast<int32_t>(
-                                    FXFT_Get_Face_Descender(m_Face->GetRec())));
+        std::max(result.bottom, static_cast<int>(m_Face->GetDescender()));
     FT_Done_Glyph(glyph);
     if (FT_Set_Pixel_Sizes(m_Face->GetRec(), 0, 64) != 0)
       return absl::nullopt;
@@ -496,7 +492,7 @@
   constexpr int kFlag = FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
   if (FT_Load_Glyph(m_Face->GetRec(), glyph_index, kFlag) != 0)
     return absl::nullopt;
-  int em = FXFT_Get_Face_UnitsPerEM(m_Face->GetRec());
+  int em = m_Face->GetUnitsPerEm();
   return ScaledFXRectFromFTPos(FXFT_Get_Glyph_HoriBearingX(m_Face->GetRec()),
                                FXFT_Get_Glyph_HoriBearingY(m_Face->GetRec()) -
                                    FXFT_Get_Glyph_Height(m_Face->GetRec()),
@@ -598,7 +594,7 @@
   if (!result.has_value())
     return result;
 
-  int em = FXFT_Get_Face_UnitsPerEM(m_Face->GetRec());
+  int em = m_Face->GetUnitsPerEm();
   if (em != 0) {
     FX_RECT& bbox = result.value();
     bbox.left = (bbox.left * 1000) / em;
@@ -645,13 +641,13 @@
     FT_Load_Glyph(m_Face->GetRec(), glyph_index,
                   FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH);
     FT_Pos min_width = FXFT_Get_Glyph_HoriAdvance(m_Face->GetRec()) * 1000 /
-                       FXFT_Get_Face_UnitsPerEM(m_Face->GetRec());
+                       m_Face->GetUnitsPerEm();
     coords[1] = max_param;
     FT_Set_MM_Design_Coordinates(m_Face->GetRec(), 2, coords);
     FT_Load_Glyph(m_Face->GetRec(), glyph_index,
                   FT_LOAD_NO_SCALE | FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH);
     FT_Pos max_width = FXFT_Get_Glyph_HoriAdvance(m_Face->GetRec()) * 1000 /
-                       FXFT_Get_Face_UnitsPerEM(m_Face->GetRec());
+                       m_Face->GetUnitsPerEm();
     if (max_width == min_width) {
       return;
     }
diff --git a/core/fxge/freetype/fx_freetype.h b/core/fxge/freetype/fx_freetype.h
index a3274ad..f796eb3 100644
--- a/core/fxge/freetype/fx_freetype.h
+++ b/core/fxge/freetype/fx_freetype.h
@@ -65,10 +65,6 @@
 #define FXFT_Get_Charmap_Encoding(charmap) (charmap)->encoding
 #define FXFT_Get_Charmap_PlatformID(charmap) (charmap)->platform_id
 #define FXFT_Get_Charmap_EncodingID(charmap) (charmap)->encoding_id
-#define FXFT_Get_Face_UnitsPerEM(face) (face)->units_per_EM
-#define FXFT_Get_Face_Height(face) (face)->height
-#define FXFT_Get_Face_Ascender(face) (face)->ascender
-#define FXFT_Get_Face_Descender(face) (face)->descender
 #define FXFT_Get_Glyph_HoriAdvance(face) (face)->glyph->metrics.horiAdvance
 #define FXFT_Get_Glyph_Outline(face) &((face)->glyph->outline)
 #define FXFT_Get_Glyph_Bitmap(face) (face)->glyph->bitmap