Add additional Fontations calls to CFX_Face. Add checks against Fontations in GetStyleName(), GetOs2UnicodeRange(), GetGlyphName(), and GetNameIndex(). Bug: 42271123 Change-Id: Ia9a174383cfb68f941ddc0886c6e67c2297922ef Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/148331 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 88ecdff..cc8df64 100644 --- a/core/fxge/cfx_face.cpp +++ b/core/fxge/cfx_face.cpp
@@ -458,7 +458,19 @@ } ByteString CFX_Face::GetStyleName() const { - return ByteString(GetRec()->style_name); + ByteString ft_result(GetRec()->style_name); +#if defined(PDF_ENABLE_SKIA_TYPEFACE_CHECKS) +#if defined(PDF_ENABLE_FONTATIONS) + pdfium::span<const uint8_t> data = GetData(); + rust::String skrifa_result = skrifa::get_style_name( + rust::Slice<const uint8_t>(data.data(), data.size())); + CHECK_EQ(ft_result.IsEmpty(), skrifa_result.empty()); + if (!ft_result.IsEmpty() && !skrifa_result.empty()) { + CHECK_EQ(ft_result, ByteString(skrifa_result.c_str())); + } +#endif // defined(PDF_ENABLE_FONTATIONS) +#endif // defined(PDF_ENABLE_SKIA_TYPEFACE_CHECKS) + return ft_result; } FX_RECT CFX_Face::GetBBox() const { @@ -561,13 +573,35 @@ #if defined(PDF_ENABLE_XFA) std::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 std::nullopt; + std::optional<std::array<uint32_t, 4>> ft_result; + if (os2) { + ft_result = + 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)}; } - 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)}; + +#if defined(PDF_ENABLE_SKIA_TYPEFACE_CHECKS) +#if defined(PDF_ENABLE_FONTATIONS) + std::optional<std::array<uint32_t, 4>> skrifa_result; + pdfium::span<const uint8_t> data = GetData(); + skrifa::UnicodeRange range; + if (skrifa::get_os2_unicode_range( + rust::Slice<const uint8_t>(data.data(), data.size()), range)) { + skrifa_result = std::array<uint32_t, 4>{range.range1, range.range2, + range.range3, range.range4}; + } + CHECK_EQ(ft_result.has_value(), skrifa_result.has_value()); + if (ft_result.has_value() && skrifa_result.has_value()) { + for (size_t i = 0; i < 4; ++i) { + CHECK_EQ((*ft_result)[i], (*skrifa_result)[i]); + } + } +#endif // defined(PDF_ENABLE_FONTATIONS) +#endif // defined(PDF_ENABLE_SKIA_TYPEFACE_CHECKS) + + return ft_result; } #endif // defined(PDF_ENABLE_XFA) @@ -976,7 +1010,21 @@ char name[256] = {}; FT_Get_Glyph_Name(GetRec(), glyph_index, name, sizeof(name)); name[255] = 0; - return ByteString(name); + ByteString ft_result(name); + +#if defined(PDF_ENABLE_SKIA_TYPEFACE_CHECKS) +#if defined(PDF_ENABLE_FONTATIONS) + pdfium::span<const uint8_t> data = GetData(); + rust::String skrifa_result = skrifa::get_glyph_name( + rust::Slice<const uint8_t>(data.data(), data.size()), glyph_index); + CHECK_EQ(ft_result.IsEmpty(), skrifa_result.empty()); + if (!ft_result.IsEmpty() && !skrifa_result.empty()) { + CHECK_EQ(ft_result, ByteString(skrifa_result.c_str())); + } +#endif // defined(PDF_ENABLE_FONTATIONS) +#endif // defined(PDF_ENABLE_SKIA_TYPEFACE_CHECKS) + + return ft_result; } int CFX_Face::GetCharIndex(uint32_t code) { @@ -1006,7 +1054,18 @@ } int CFX_Face::GetNameIndex(const char* name) { - return FT_Get_Name_Index(GetRec(), name); + int ft_result = FT_Get_Name_Index(GetRec(), name); + +#if defined(PDF_ENABLE_SKIA_TYPEFACE_CHECKS) +#if defined(PDF_ENABLE_FONTATIONS) + pdfium::span<const uint8_t> data = GetData(); + uint32_t skrifa_result = skrifa::get_name_index( + rust::Slice<const uint8_t>(data.data(), data.size()), name); + CHECK_EQ(ft_result, static_cast<int>(skrifa_result)); +#endif // defined(PDF_ENABLE_FONTATIONS) +#endif // defined(PDF_ENABLE_SKIA_TYPEFACE_CHECKS) + + return ft_result; } int CFX_Face::LoadGlyph(uint32_t glyph_index, bool scale) {
diff --git a/core/fxge/skrifa/src/main.rs b/core/fxge/skrifa/src/main.rs index 9cffdad..9c9f1a8 100644 --- a/core/fxge/skrifa/src/main.rs +++ b/core/fxge/skrifa/src/main.rs
@@ -66,6 +66,14 @@ pub b1: u8, } + #[derive(Copy, Clone, PartialEq, Eq, Debug)] + pub struct UnicodeRange { + pub range1: u32, + pub range2: u32, + pub range3: u32, + pub range4: u32, + } + #[derive(Clone, Debug)] pub struct Outline { pub verbs: Vec<PathVerb>, @@ -93,6 +101,10 @@ fn get_os2_code_page_range(data: &[u8], range: &mut CodePageRange) -> bool; fn get_os2_panose(data: &[u8], panose: &mut Os2Panose) -> bool; fn get_os2_fs_type(data: &[u8], fs_type: &mut u16) -> bool; + fn get_os2_unicode_range(data: &[u8], range: &mut UnicodeRange) -> bool; + fn get_style_name(data: &[u8]) -> String; + fn get_glyph_name(data: &[u8], gid: u32) -> String; + fn get_name_index(data: &[u8], name: &str) -> u32; fn agl_name_to_unicode(name: &str, unicode: &mut u32) -> bool; fn agl_unicode_to_name(unicode: u32, name: &mut [u8]) -> bool; @@ -370,6 +382,52 @@ false } +pub fn get_os2_unicode_range(data: &[u8], range: &mut skrifa_ffi::UnicodeRange) -> bool { + if let Ok(font) = read_fonts::FontRef::new(data) { + use read_fonts::TableProvider; + if let Ok(os2) = font.os2() { + range.range1 = os2.ul_unicode_range_1(); + range.range2 = os2.ul_unicode_range_2(); + range.range3 = os2.ul_unicode_range_3(); + range.range4 = os2.ul_unicode_range_4(); + return true; + } + } + false +} + +pub fn get_style_name(data: &[u8]) -> String { + if let Ok(font) = skrifa::FontRef::new(data) { + use skrifa::string::StringId; + use skrifa::MetadataProvider; + if let Some(name) = font.localized_strings(StringId::SUBFAMILY_NAME).english_or_first() { + return name.to_string(); + } + } + String::new() +} + +pub fn get_glyph_name(data: &[u8], gid: u32) -> String { + if let Ok(font) = read_fonts::FontRef::new(data) { + let glyph_names = skrifa::GlyphNames::new(&font); + if let Some(name) = glyph_names.get(skrifa::GlyphId::new(gid)) { + return name.to_string(); + } + } + String::new() +} + +pub fn get_name_index(data: &[u8], name: &str) -> u32 { + if let Ok(font) = read_fonts::FontRef::new(data) { + let glyph_names = skrifa::GlyphNames::new(&font); + if let Some(gid) = glyph_names.iter().find(|(_id, n)| n.as_str() == name).map(|(id, _n)| id) + { + return gid.to_u32(); + } + } + 0 +} + fn main() { skrifa_ffi::run(""); }