Add still more fontations equivalents to cfx_face.cpp

This CL should put PDFium in a state where Fontations experts can
make concrete recommendations.

Bug: 42271123
Change-Id: If7c6c43ebce930f6ca1560beec08ef8f543c46be
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/148451
Commit-Queue: Tom Sepez <tsepez@chromium.org>
Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/core/fxge/cfx_face.cpp b/core/fxge/cfx_face.cpp
index 2cd2a60..af89e48 100644
--- a/core/fxge/cfx_face.cpp
+++ b/core/fxge/cfx_face.cpp
@@ -396,8 +396,10 @@
 bool CFX_Face::HasGlyphNames() const {
   const bool ft_result = !!(GetRec()->face_flags & FT_FACE_FLAG_GLYPH_NAMES);
 #if defined(PDF_ENABLE_SKIA_TYPEFACE_CHECKS)
-  // TODO(https://crbug.com/42271123): Compute equivalent result via Skia or
-  // Skrifa.
+#if defined(PDF_ENABLE_FONTATIONS)
+  pdfium::span<const uint8_t> data = GetData();
+  CHECK_EQ(ft_result, skrifa::has_glyph_names(rust::Slice(data)));
+#endif
 #endif
   return ft_result;
 }
@@ -415,8 +417,11 @@
 ByteString CFX_Face::GetFontFormat() {
   const ByteString ft_result(FT_Get_Font_Format(GetRec()));
 #if defined(PDF_ENABLE_SKIA_TYPEFACE_CHECKS)
-  // TODO(https://crbug.com/42271123): Compute equivalent result via Skia or
-  // Skrifa.
+#if defined(PDF_ENABLE_FONTATIONS)
+  pdfium::span<const uint8_t> data = GetData();
+  rust::String skrifa_result = skrifa::get_font_format(rust::Slice(data));
+  CHECK_EQ(ft_result, ByteString(skrifa_result.c_str()));
+#endif
 #endif
   return ft_result;
 }
@@ -436,6 +441,10 @@
   if (skia_typeface_) {
     CHECK_EQ(ft_result, skia_typeface_->isFixedPitch());
   }
+#if defined(PDF_ENABLE_FONTATIONS)
+  pdfium::span<const uint8_t> data = GetData();
+  CHECK_EQ(ft_result, skrifa::is_fixed_pitch(rust::Slice(data)));
+#endif
 #endif
   return ft_result;
 }
@@ -444,8 +453,10 @@
 bool CFX_Face::IsScalable() const {
   const bool ft_result = !!(GetRec()->face_flags & FT_FACE_FLAG_SCALABLE);
 #if defined(PDF_ENABLE_SKIA_TYPEFACE_CHECKS)
-  // TODO(https://crbug.com/42271123): Compute equivalent result via Skia or
-  // Skrifa.
+#if defined(PDF_ENABLE_FONTATIONS)
+  pdfium::span<const uint8_t> data = GetData();
+  CHECK_EQ(ft_result, skrifa::is_scalable(rust::Slice(data)));
+#endif
 #endif
   return ft_result;
 }
@@ -1227,8 +1238,17 @@
     }
   }
 #if defined(PDF_ENABLE_SKIA_TYPEFACE_CHECKS)
-  // TODO(https://crbug.com/42271123): Compute equivalent result via Skia or
-  // Skrifa.
+#if defined(PDF_ENABLE_FONTATIONS)
+  pdfium::span<const uint8_t> data = GetData();
+  skrifa::BoundingBox bbox =
+      skrifa::get_glyph_bounds(rust::Slice(data), glyph_index);
+  const uint16_t upem = GetUnitsPerEm();
+  FX_RECT skrifa_result(NormalizeFontMetric(bbox.x_min, upem),
+                        NormalizeFontMetric(bbox.y_max, upem),
+                        NormalizeFontMetric(bbox.x_max, upem),
+                        NormalizeFontMetric(bbox.y_min, upem));
+  // TODO(tsepez): verify results.
+#endif
 #endif
   return rect;
 }
diff --git a/core/fxge/skrifa/src/main.rs b/core/fxge/skrifa/src/main.rs
index 5fdb531..6abaac0 100644
--- a/core/fxge/skrifa/src/main.rs
+++ b/core/fxge/skrifa/src/main.rs
@@ -56,6 +56,14 @@
         pub y: f32,
     }
 
+    #[derive(Copy, Clone, PartialEq, Debug)]
+    pub struct BoundingBox {
+        pub x_min: f32,
+        pub y_min: f32,
+        pub x_max: f32,
+        pub y_max: f32,
+    }
+
     #[derive(Copy, Clone, PartialEq, Eq, Debug)]
     pub struct CodePageRange {
         pub range1: u32,
@@ -118,6 +126,11 @@
         fn agl_unicode_to_name(unicode: u32, name: &mut [u8]) -> bool;
 
         fn get_char_codes_and_indices(data: &[u8], max_char: u32) -> Vec<CharCodeAndIndex>;
+        fn has_glyph_names(data: &[u8]) -> bool;
+        fn is_fixed_pitch(data: &[u8]) -> bool;
+        fn is_scalable(data: &[u8]) -> bool;
+        fn get_font_format(data: &[u8]) -> String;
+        fn get_glyph_bounds(data: &[u8], glyph_index: u32) -> BoundingBox;
     }
 
     unsafe extern "C++" {
@@ -496,6 +509,76 @@
     results
 }
 
+pub fn has_glyph_names(data: &[u8]) -> bool {
+    if let Ok(font) = read_fonts::FontRef::new(data) {
+        let glyph_names = skrifa::GlyphNames::new(&font);
+        return glyph_names.source() != skrifa::GlyphNameSource::Synthesized;
+    }
+    false
+}
+
+pub fn is_fixed_pitch(data: &[u8]) -> bool {
+    if let Ok(font) = read_fonts::FontRef::new(data) {
+        use read_fonts::TableProvider;
+        if let Ok(post) = font.post() {
+            return post.is_fixed_pitch() != 0;
+        }
+    }
+    false
+}
+
+pub fn is_scalable(data: &[u8]) -> bool {
+    if let Ok(font) = read_fonts::FontRef::new(data) {
+        use read_fonts::TableProvider;
+        return font.glyf().is_ok() || font.cff().is_ok() || font.cff2().is_ok();
+    }
+    if read_fonts::ps::cff::CffFontRef::new(data, 0, None).is_ok() {
+        return true;
+    }
+    if read_fonts::ps::type1::Type1Font::new(data).is_ok() {
+        return true;
+    }
+    false
+}
+
+pub fn get_font_format(data: &[u8]) -> String {
+    if read_fonts::ps::type1::Type1Font::new(data).is_ok() {
+        return "Type 1".to_string();
+    }
+    if let Ok(font) = read_fonts::FontRef::new(data) {
+        use read_fonts::TableProvider;
+        if font.cff().is_ok() || font.cff2().is_ok() {
+            return "CFF".to_string();
+        }
+        if font.glyf().is_ok() {
+            return "TrueType".to_string();
+        }
+    }
+    if read_fonts::ps::cff::CffFontRef::new(data, 0, None).is_ok() {
+        return "CFF".to_string();
+    }
+    String::new()
+}
+
+pub fn get_glyph_bounds(data: &[u8], glyph_index: u32) -> skrifa_ffi::BoundingBox {
+    if let Ok(font) = read_fonts::FontRef::new(data) {
+        let metrics = skrifa::metrics::GlyphMetrics::new(
+            &font,
+            skrifa::instance::Size::unscaled(),
+            skrifa::instance::LocationRef::default(),
+        );
+        if let Some(bbox) = metrics.bounds(skrifa::GlyphId::new(glyph_index)) {
+            return skrifa_ffi::BoundingBox {
+                x_min: bbox.x_min,
+                y_min: bbox.y_min,
+                x_max: bbox.x_max,
+                y_max: bbox.y_max,
+            };
+        }
+    }
+    skrifa_ffi::BoundingBox { x_min: 0.0, y_min: 0.0, x_max: 0.0, y_max: 0.0 }
+}
+
 fn main() {
     skrifa_ffi::run("");
 }