diff --git a/components/fonts/platform/macos/core_text_font_cache.rs b/components/fonts/platform/macos/core_text_font_cache.rs index 23c03833551..0d2fb950e5a 100644 --- a/components/fonts/platform/macos/core_text_font_cache.rs +++ b/components/fonts/platform/macos/core_text_font_cache.rs @@ -17,6 +17,7 @@ use core_text::font_descriptor::kCTFontURLAttribute; use parking_lot::RwLock; use crate::FontData; +use crate::platform::font::PlatformFont; use crate::system_font_service::FontIdentifier; /// A cache of `CTFont` to avoid having to create `CTFont` instances over and over. It is @@ -36,7 +37,7 @@ impl CoreTextFontCache { font_identifier: FontIdentifier, data: Option<&FontData>, pt_size: f64, - ) -> Option { + ) -> Option { //// If you pass a zero font size to one of the Core Text APIs, it'll replace it with //// 12.0. We don't want that! (Issue #10492.) let clamped_pt_size = pt_size.max(0.01); @@ -49,7 +50,7 @@ impl CoreTextFontCache { .get(&font_identifier) .and_then(|identifier_cache| identifier_cache.get(&au_size)) { - return Some(core_text_font.clone()); + return Some(PlatformFont::new_with_ctfont(core_text_font.clone())); } } @@ -60,7 +61,7 @@ impl CoreTextFontCache { // on the cache has been acquired, the cache was populated with the data that we need. Thus // check again and return the CTFont if it is is already cached. if let Some(core_text_font) = identifier_cache.get(&au_size) { - return Some(core_text_font.clone()); + return Some(PlatformFont::new_with_ctfont(core_text_font.clone())); } let core_text_font = match font_identifier { @@ -98,6 +99,6 @@ impl CoreTextFontCache { }; identifier_cache.insert(au_size, core_text_font.clone()); - Some(core_text_font) + Some(PlatformFont::new_with_ctfont(core_text_font)) } } diff --git a/components/fonts/platform/macos/font.rs b/components/fonts/platform/macos/font.rs index 5249621be81..af3841141a8 100644 --- a/components/fonts/platform/macos/font.rs +++ b/components/fonts/platform/macos/font.rs @@ -70,10 +70,43 @@ unsafe impl Sync for PlatformFont {} unsafe impl Send for PlatformFont {} impl PlatformFont { + pub(crate) fn new_with_ctfont(ctfont: CTFont) -> Self { + Self { + ctfont, + h_kern_subtable: None, + } + } + + fn new( + font_identifier: FontIdentifier, + data: Option<&FontData>, + requested_size: Option, + ) -> Result { + let size = match requested_size { + Some(s) => s.to_f64_px(), + None => 0.0, + }; + let Some(mut platform_font) = + CoreTextFontCache::core_text_font(font_identifier, data, size) + else { + return Err("Could not generate CTFont for FontTemplateData"); + }; + + platform_font.load_h_kern_subtable(); + Ok(platform_font) + } + /// Cache all the data needed for basic horizontal kerning. This is used only as a fallback or /// fast path (when the GPOS table is missing or unnecessary) so it needn't handle every case. - fn find_h_kern_subtable(&self) -> Option { - let font_table = self.table_for_tag(KERN)?; + fn load_h_kern_subtable(&mut self) { + if self.h_kern_subtable.is_some() { + return; + } + + let Some(font_table) = self.table_for_tag(KERN) else { + return; + }; + let mut result = CachedKernTable { font_table, pair_data_range: 0..0, @@ -89,7 +122,7 @@ impl PlatformFont { let table = result.font_table.buffer(); let version = BigEndian::read_u16(table); if version != 0 { - return None; + return; } let num_subtables = BigEndian::read_u16(&table[2..]); let mut start = 4; @@ -102,7 +135,7 @@ impl PlatformFont { // Found a matching subtable. if !result.pair_data_range.is_empty() { debug!("Found multiple horizontal kern tables. Disable fast path."); - return None; + return; } // Read the subtable header. let subtable_start = start + SUBTABLE_HEADER_LEN; @@ -112,7 +145,7 @@ impl PlatformFont { result.pair_data_range = pair_data_start..end; if result.pair_data_range.len() != n_pairs * KERN_PAIR_LEN { debug!("Bad data in kern header. Disable fast path."); - return None; + return; } let pt_per_font_unit = @@ -122,10 +155,9 @@ impl PlatformFont { start = end; } } + if !result.pair_data_range.is_empty() { - Some(result) - } else { - None + self.h_kern_subtable = Some(result); } } } @@ -164,30 +196,6 @@ impl fmt::Debug for CachedKernTable { } } -impl PlatformFont { - fn new( - font_identifier: FontIdentifier, - data: Option<&FontData>, - requested_size: Option, - ) -> Result { - let size = match requested_size { - Some(s) => s.to_f64_px(), - None => 0.0, - }; - let Some(core_text_font) = CoreTextFontCache::core_text_font(font_identifier, data, size) - else { - return Err("Could not generate CTFont for FontTemplateData"); - }; - - let mut handle = PlatformFont { - ctfont: core_text_font.clone_with_font_size(size), - h_kern_subtable: None, - }; - handle.h_kern_subtable = handle.find_h_kern_subtable(); - Ok(handle) - } -} - impl PlatformFontMethods for PlatformFont { fn new_from_data( font_identifier: FontIdentifier,