From 4249b5687e83899084833e7855317ea54ab598c1 Mon Sep 17 00:00:00 2001 From: Keith Simmons Date: Tue, 12 Apr 2022 14:09:29 -0700 Subject: [PATCH] Implement font fallback in layout_line Co-authored-by: Max Brunsfeld --- crates/gpui/src/platform/mac/fonts.rs | 50 ++++++++++++++++----------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/crates/gpui/src/platform/mac/fonts.rs b/crates/gpui/src/platform/mac/fonts.rs index cf0f0c8b27..8ea5963697 100644 --- a/crates/gpui/src/platform/mac/fonts.rs +++ b/crates/gpui/src/platform/mac/fonts.rs @@ -13,13 +13,12 @@ use core_foundation::{ array::CFIndex, attributed_string::{CFAttributedStringRef, CFMutableAttributedString}, base::{CFRange, TCFType}, - number::CFNumber, string::CFString, }; use core_graphics::{ base::CGGlyph, color_space::CGColorSpace, context::CGContext, geometry::CGAffineTransform, }; -use core_text::{line::CTLine, string_attributes::kCTFontAttributeName}; +use core_text::{font::CTFont, line::CTLine, string_attributes::kCTFontAttributeName}; use font_kit::{ canvas::RasterizationOptions, handle::Handle, hinting::HintingOptions, source::SystemSource, sources::mem::MemSource, @@ -91,7 +90,7 @@ impl platform::FontSystem for FontSystem { } fn layout_line(&self, text: &str, font_size: f32, runs: &[(usize, RunStyle)]) -> LineLayout { - self.0.read().layout_line(text, font_size, runs) + self.0.write().layout_line(text, font_size, runs) } fn wrap_line(&self, text: &str, font_id: FontId, font_size: f32, width: f32) -> Vec { @@ -149,6 +148,19 @@ impl FontSystemState { self.fonts[font_id.0].glyph_for_char(ch) } + fn id_for_font(&mut self, requested_font: font_kit::font::Font) -> FontId { + // TODO: don't allocate the postscript name + // Note: Coretext always returns a Some option for postscript_name + let requested_font_name = requested_font.postscript_name(); + for (id, font) in self.fonts.iter().enumerate() { + if font.postscript_name() == requested_font_name { + return FontId(id); + } + } + self.fonts.push(requested_font); + FontId(self.fonts.len() - 1) + } + fn rasterize_glyph( &self, font_id: FontId, @@ -217,9 +229,12 @@ impl FontSystemState { } } - fn layout_line(&self, text: &str, font_size: f32, runs: &[(usize, RunStyle)]) -> LineLayout { - let font_id_attr_name = CFString::from_static_string("zed_font_id"); - + fn layout_line( + &mut self, + text: &str, + font_size: f32, + runs: &[(usize, RunStyle)], + ) -> LineLayout { // Construct the attributed string, converting UTF8 ranges to UTF16 ranges. let mut string = CFMutableAttributedString::new(); { @@ -269,11 +284,6 @@ impl FontSystemState { kCTFontAttributeName, &font.native_font().clone_with_font_size(font_size as f64), ); - string.set_attribute( - cf_range, - font_id_attr_name.as_concrete_TypeRef(), - &CFNumber::from(font_id.0 as i64), - ); } if utf16_end == utf16_line_len { @@ -287,15 +297,15 @@ impl FontSystemState { let mut runs = Vec::new(); for run in line.glyph_runs().into_iter() { - let font_id = FontId( - run.attributes() - .unwrap() - .get(&font_id_attr_name) - .downcast::() - .unwrap() - .to_i64() - .unwrap() as usize, - ); + let attributes = run.attributes().unwrap(); + let font = unsafe { + let native_font = attributes + .get(kCTFontAttributeName) + .downcast::() + .unwrap(); + font_kit::font::Font::from_native_font(native_font) + }; + let font_id = self.id_for_font(font); let mut ix_converter = StringIndexConverter::new(text); let mut glyphs = Vec::new();