Encapsulate FT_Get_Sfnt_Table() calls

Implement various getters in CFX_Face to satisfy existing
FT_Get_Sfnt_Table() uses in the code base.

Bug: pdfium:2037
Change-Id: Ie25f93ada0da61e323ef7e36323a36e839f0846b
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/114794
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Dominik Röttsches <drott@chromium.org>
diff --git a/core/fxge/android/cfpf_skiafontmgr.cpp b/core/fxge/android/cfpf_skiafontmgr.cpp
index 08d7d17..59db044 100644
--- a/core/fxge/android/cfpf_skiafontmgr.cpp
+++ b/core/fxge/android/cfpf_skiafontmgr.cpp
@@ -199,16 +199,14 @@
     FPF_SKIACHARSET_Symbol,
 };
 
-uint32_t FPF_SkiaGetFaceCharset(TT_OS2* pOS2) {
-  uint32_t dwCharset = 0;
-  if (pOS2) {
-    for (int32_t i = 0; i < 32; i++) {
-      if (pOS2->ulCodePageRange1 & (1 << i))
-        dwCharset |= kFPFSkiaFontCharsets[i];
+uint32_t FPF_SkiaGetFaceCharset(uint32_t code_range) {
+  uint32_t charset = 0;
+  for (int32_t i = 0; i < 32; i++) {
+    if (code_range & (1 << i)) {
+      charset |= kFPFSkiaFontCharsets[i];
     }
   }
-  dwCharset |= FPF_SKIACHARSET_Default;
-  return dwCharset;
+  return charset;
 }
 
 }  // namespace
@@ -389,21 +387,26 @@
   if (face->IsFixedWidth()) {
     dwStyle |= FXFONT_FIXED_PITCH;
   }
-  TT_OS2* pOS2 =
-      static_cast<TT_OS2*>(FT_Get_Sfnt_Table(face->GetRec(), ft_sfnt_os2));
-  if (pOS2) {
-    if (pOS2->ulCodePageRange1 & (1 << 31))
+
+  uint32_t charset = FPF_SKIACHARSET_Default;
+  absl::optional<std::array<uint32_t, 2>> code_page_range =
+      face->GetOs2CodePageRange();
+  if (code_page_range.has_value()) {
+    if (code_page_range.value()[0] & (1 << 31)) {
       dwStyle |= FXFONT_SYMBOLIC;
-    if (pOS2->panose[0] == 2) {
-      uint8_t uSerif = pOS2->panose[1];
-      if ((uSerif > 1 && uSerif < 10) || uSerif > 13)
-        dwStyle |= FXFONT_SERIF;
+    }
+    charset |= FPF_SkiaGetFaceCharset(code_page_range.value()[0]);
+  }
+
+  absl::optional<std::array<uint8_t, 2>> panose = face->GetOs2Panose();
+  if (panose.has_value() && panose.value()[0] == 2) {
+    uint8_t serif = panose.value()[1];
+    if ((serif > 1 && serif < 10) || serif > 13) {
+      dwStyle |= FXFONT_SERIF;
     }
   }
-  if (pOS2 && (pOS2->ulCodePageRange1 & (1 << 31)))
-    dwStyle |= FXFONT_SYMBOLIC;
 
   return std::make_unique<CFPF_SkiaPathFont>(
-      file, face->GetFamilyName(), dwStyle, face->GetRec()->face_index,
-      FPF_SkiaGetFaceCharset(pOS2), face->GetRec()->num_glyphs);
+      file, face->GetFamilyName(), dwStyle, face->GetRec()->face_index, charset,
+      face->GetRec()->num_glyphs);
 }
diff --git a/core/fxge/cfx_face.cpp b/core/fxge/cfx_face.cpp
index c9bcd33..a5b5994 100644
--- a/core/fxge/cfx_face.cpp
+++ b/core/fxge/cfx_face.cpp
@@ -332,6 +332,34 @@
   return pdfium::base::checked_cast<size_t>(length);
 }
 
+absl::optional<std::array<uint32_t, 4>> CFX_Face::GetOs2UnicodeRange() {
+  auto* os2 = static_cast<TT_OS2*>(FT_Get_Sfnt_Table(GetRec(), FT_SFNT_OS2));
+  if (!os2) {
+    return absl::nullopt;
+  }
+  return std::array<uint32_t, 4>{static_cast<uint32_t>(os2->ulUnicodeRange1),
+                                 static_cast<uint32_t>(os2->ulUnicodeRange2),
+                                 static_cast<uint32_t>(os2->ulUnicodeRange3),
+                                 static_cast<uint32_t>(os2->ulUnicodeRange4)};
+}
+
+absl::optional<std::array<uint32_t, 2>> CFX_Face::GetOs2CodePageRange() {
+  auto* os2 = static_cast<TT_OS2*>(FT_Get_Sfnt_Table(GetRec(), FT_SFNT_OS2));
+  if (!os2) {
+    return absl::nullopt;
+  }
+  return std::array<uint32_t, 2>{static_cast<uint32_t>(os2->ulCodePageRange1),
+                                 static_cast<uint32_t>(os2->ulCodePageRange2)};
+}
+
+absl::optional<std::array<uint8_t, 2>> CFX_Face::GetOs2Panose() {
+  auto* os2 = static_cast<TT_OS2*>(FT_Get_Sfnt_Table(GetRec(), FT_SFNT_OS2));
+  if (!os2) {
+    return absl::nullopt;
+  }
+  return std::array<uint8_t, 2>{os2->panose[0], os2->panose[1]};
+}
+
 std::unique_ptr<CFX_GlyphBitmap> CFX_Face::RenderGlyph(const CFX_Font* pFont,
                                                        uint32_t glyph_index,
                                                        bool bFontStyle,
diff --git a/core/fxge/cfx_face.h b/core/fxge/cfx_face.h
index 4a0ee5d..6c57504 100644
--- a/core/fxge/cfx_face.h
+++ b/core/fxge/cfx_face.h
@@ -7,6 +7,7 @@
 
 #include <stdint.h>
 
+#include <array>
 #include <memory>
 
 #include "build/build_config.h"
@@ -72,6 +73,10 @@
   // it is large enough to hold the data.
   size_t GetSfntTable(uint32_t table, pdfium::span<uint8_t> buffer);
 
+  absl::optional<std::array<uint32_t, 4>> GetOs2UnicodeRange();
+  absl::optional<std::array<uint32_t, 2>> GetOs2CodePageRange();
+  absl::optional<std::array<uint8_t, 2>> GetOs2Panose();
+
   std::unique_ptr<CFX_GlyphBitmap> RenderGlyph(const CFX_Font* pFont,
                                                uint32_t glyph_index,
                                                bool bFontStyle,
diff --git a/xfa/fgas/font/cfgas_fontmgr.cpp b/xfa/fgas/font/cfgas_fontmgr.cpp
index 1bb2375..bef5532 100644
--- a/xfa/fgas/font/cfgas_fontmgr.cpp
+++ b/xfa/fgas/font/cfgas_fontmgr.cpp
@@ -21,6 +21,7 @@
 #include "core/fxcrt/fx_extension.h"
 #include "core/fxcrt/fx_memory_wrappers.h"
 #include "core/fxcrt/fx_system.h"
+#include "core/fxcrt/span_util.h"
 #include "core/fxge/cfx_font.h"
 #include "core/fxge/cfx_fontmapper.h"
 #include "core/fxge/cfx_fontmgr.h"
@@ -431,25 +432,6 @@
   return results;
 }
 
-void GetUSBCSB(FXFT_FaceRec* pFace, uint32_t* USB, uint32_t* CSB) {
-  TT_OS2* pOS2 = static_cast<TT_OS2*>(FT_Get_Sfnt_Table(pFace, ft_sfnt_os2));
-  if (!pOS2) {
-    USB[0] = 0;
-    USB[1] = 0;
-    USB[2] = 0;
-    USB[3] = 0;
-    CSB[0] = 0;
-    CSB[1] = 0;
-    return;
-  }
-  USB[0] = static_cast<uint32_t>(pOS2->ulUnicodeRange1);
-  USB[1] = static_cast<uint32_t>(pOS2->ulUnicodeRange2);
-  USB[2] = static_cast<uint32_t>(pOS2->ulUnicodeRange3);
-  USB[3] = static_cast<uint32_t>(pOS2->ulUnicodeRange4);
-  CSB[0] = static_cast<uint32_t>(pOS2->ulCodePageRange1);
-  CSB[1] = static_cast<uint32_t>(pOS2->ulCodePageRange2);
-}
-
 uint32_t GetFlags(const RetainPtr<CFX_Face>& face) {
   uint32_t flags = 0;
   if (face->IsBold()) {
@@ -462,17 +444,18 @@
     flags |= FXFONT_FIXED_PITCH;
   }
 
-  TT_OS2* pOS2 =
-      static_cast<TT_OS2*>(FT_Get_Sfnt_Table(face->GetRec(), ft_sfnt_os2));
-  if (!pOS2)
-    return flags;
-
-  if (pOS2->ulCodePageRange1 & (1 << 31))
+  absl::optional<std::array<uint32_t, 2>> code_page_range =
+      face->GetOs2CodePageRange();
+  if (code_page_range.has_value() && (code_page_range.value()[0] & (1 << 31))) {
     flags |= FXFONT_SYMBOLIC;
-  if (pOS2->panose[0] == 2) {
-    uint8_t uSerif = pOS2->panose[1];
-    if ((uSerif > 1 && uSerif < 10) || uSerif > 13)
+  }
+
+  absl::optional<std::array<uint8_t, 2>> panose = face->GetOs2Panose();
+  if (panose.has_value() && panose.value()[0] == 2) {
+    uint8_t serif = panose.value()[1];
+    if ((serif > 1 && serif < 10) || serif > 13) {
       flags |= FXFONT_SERIF;
+    }
   }
   return flags;
 }
@@ -737,7 +720,25 @@
   auto pFont = std::make_unique<CFGAS_FontDescriptor>();
   pFont->m_dwFontStyles |= GetFlags(pFace);
 
-  GetUSBCSB(pFace->GetRec(), pFont->m_dwUsb, pFont->m_dwCsb);
+  // TODO(crbug.com/pdfium/2085): Use make_span() in fewer places after updating
+  // pdfium::span.
+  absl::optional<std::array<uint32_t, 4>> unicode_range =
+      pFace->GetOs2UnicodeRange();
+  auto usb_span = pdfium::make_span(pFont->m_dwUsb);
+  if (unicode_range.has_value()) {
+    fxcrt::spancpy(usb_span, pdfium::make_span(unicode_range.value()));
+  } else {
+    fxcrt::spanclr(usb_span);
+  }
+
+  absl::optional<std::array<uint32_t, 2>> code_page_range =
+      pFace->GetOs2CodePageRange();
+  auto csb_span = pdfium::make_span(pFont->m_dwCsb);
+  if (code_page_range.has_value()) {
+    fxcrt::spancpy(csb_span, pdfium::make_span(code_page_range.value()));
+  } else {
+    fxcrt::spanclr(csb_span);
+  }
 
   static constexpr uint32_t kNameTag =
       CFX_FontMapper::MakeTag('n', 'a', 'm', 'e');