From 31516b7863b04d336253b62c08135b59dfb0056d Mon Sep 17 00:00:00 2001 From: Julia Date: Tue, 30 May 2023 14:46:27 -0400 Subject: [PATCH] `TextStyle::default()` ask system for known existing font family Rather than assuming a specific family exists, try a set of specific names and if they fail, just grab any old font that the system reports as existing Co-Authored-By: Nathan Sobo --- crates/gpui/src/font_cache.rs | 52 +++++++++++++++++++++------ crates/gpui/src/fonts.rs | 11 +++--- crates/gpui/src/platform.rs | 1 + crates/gpui/src/platform/mac/fonts.rs | 8 +++++ 4 files changed, 56 insertions(+), 16 deletions(-) diff --git a/crates/gpui/src/font_cache.rs b/crates/gpui/src/font_cache.rs index 4388ad4bcb..57dad48e34 100644 --- a/crates/gpui/src/font_cache.rs +++ b/crates/gpui/src/font_cache.rs @@ -25,8 +25,9 @@ struct Family { pub struct FontCache(RwLock); pub struct FontCacheState { - fonts: Arc, + font_system: Arc, families: Vec, + default_family: Option, font_selections: HashMap>, metrics: HashMap, wrapper_pool: HashMap<(FontId, OrderedFloat), Vec>, @@ -42,8 +43,9 @@ unsafe impl Send for FontCache {} impl FontCache { pub fn new(fonts: Arc) -> Self { Self(RwLock::new(FontCacheState { - fonts, + font_system: fonts, families: Default::default(), + default_family: None, font_selections: Default::default(), metrics: Default::default(), wrapper_pool: Default::default(), @@ -73,14 +75,14 @@ impl FontCache { let mut state = RwLockUpgradableReadGuard::upgrade(state); - if let Ok(font_ids) = state.fonts.load_family(name, features) { + if let Ok(font_ids) = state.font_system.load_family(name, features) { if font_ids.is_empty() { continue; } let family_id = FamilyId(state.families.len()); for font_id in &font_ids { - if state.fonts.glyph_for_char(*font_id, 'm').is_none() { + if state.font_system.glyph_for_char(*font_id, 'm').is_none() { return Err(anyhow!("font must contain a glyph for the 'm' character")); } } @@ -99,6 +101,31 @@ impl FontCache { )) } + /// Returns an arbitrary font family that is available on the system. + pub fn known_existing_family(&self) -> FamilyId { + if let Some(family_id) = self.0.read().default_family { + return family_id; + } + + let default_family = self + .load_family( + &["Courier", "Helvetica", "Arial", "Verdana"], + &Default::default(), + ) + .unwrap_or_else(|_| { + let all_family_names = self.0.read().font_system.all_families(); + let all_family_names: Vec<_> = all_family_names + .iter() + .map(|string| string.as_str()) + .collect(); + self.load_family(&all_family_names, &Default::default()) + .expect("could not load any default font family") + }); + + self.0.write().default_family = Some(default_family); + default_family + } + pub fn default_font(&self, family_id: FamilyId) -> FontId { self.select_font(family_id, &Properties::default()).unwrap() } @@ -115,7 +142,7 @@ impl FontCache { let mut inner = RwLockUpgradableReadGuard::upgrade(inner); let family = &inner.families[family_id.0]; let font_id = inner - .fonts + .font_system .select_font(&family.font_ids, properties) .unwrap_or(family.font_ids[0]); @@ -137,7 +164,7 @@ impl FontCache { if let Some(metrics) = state.metrics.get(&font_id) { f(metrics) } else { - let metrics = state.fonts.font_metrics(font_id); + let metrics = state.font_system.font_metrics(font_id); let metric = f(&metrics); let mut state = RwLockUpgradableReadGuard::upgrade(state); state.metrics.insert(font_id, metrics); @@ -157,8 +184,11 @@ impl FontCache { let bounds; { let state = self.0.read(); - glyph_id = state.fonts.glyph_for_char(font_id, 'm').unwrap(); - bounds = state.fonts.typographic_bounds(font_id, glyph_id).unwrap(); + glyph_id = state.font_system.glyph_for_char(font_id, 'm').unwrap(); + bounds = state + .font_system + .typographic_bounds(font_id, glyph_id) + .unwrap(); } bounds.width() * self.em_scale(font_id, font_size) } @@ -168,8 +198,8 @@ impl FontCache { let advance; { let state = self.0.read(); - glyph_id = state.fonts.glyph_for_char(font_id, 'm').unwrap(); - advance = state.fonts.advance(font_id, glyph_id).unwrap(); + glyph_id = state.font_system.glyph_for_char(font_id, 'm').unwrap(); + advance = state.font_system.advance(font_id, glyph_id).unwrap(); } advance.x() * self.em_scale(font_id, font_size) } @@ -214,7 +244,7 @@ impl FontCache { .or_default(); let wrapper = wrappers .pop() - .unwrap_or_else(|| LineWrapper::new(font_id, font_size, state.fonts.clone())); + .unwrap_or_else(|| LineWrapper::new(font_id, font_size, state.font_system.clone())); LineWrapperHandle { wrapper: Some(wrapper), font_cache: self.clone(), diff --git a/crates/gpui/src/fonts.rs b/crates/gpui/src/fonts.rs index e0f037acb8..5e77593d05 100644 --- a/crates/gpui/src/fonts.rs +++ b/crates/gpui/src/fonts.rs @@ -295,13 +295,14 @@ impl Default for TextStyle { .as_ref() .expect("TextStyle::default can only be called within a call to with_font_cache"); - let font_family_name = Arc::from("Courier"); - let font_family_id = font_cache - .load_family(&[&font_family_name], &Default::default()) - .unwrap(); + let font_family_id = font_cache.known_existing_family(); let font_id = font_cache .select_font(font_family_id, &Default::default()) - .unwrap(); + .expect("did not have any font in system-provided family"); + let font_family_name = font_cache + .family_name(font_family_id) + .expect("we loaded this family from the font cache, so this should work"); + Self { color: Default::default(), font_family_name, diff --git a/crates/gpui/src/platform.rs b/crates/gpui/src/platform.rs index 9b4fd7ca51..7fc02b0548 100644 --- a/crates/gpui/src/platform.rs +++ b/crates/gpui/src/platform.rs @@ -343,6 +343,7 @@ pub enum RasterizationOptions { pub trait FontSystem: Send + Sync { fn add_fonts(&self, fonts: &[Arc>]) -> anyhow::Result<()>; + fn all_families(&self) -> Vec; fn load_family(&self, name: &str, features: &FontFeatures) -> anyhow::Result>; fn select_font( &self, diff --git a/crates/gpui/src/platform/mac/fonts.rs b/crates/gpui/src/platform/mac/fonts.rs index 96916698fc..0414cb8a6c 100644 --- a/crates/gpui/src/platform/mac/fonts.rs +++ b/crates/gpui/src/platform/mac/fonts.rs @@ -66,6 +66,14 @@ impl platform::FontSystem for FontSystem { self.0.write().add_fonts(fonts) } + fn all_families(&self) -> Vec { + self.0 + .read() + .system_source + .all_families() + .expect("core text should never return an error") + } + fn load_family(&self, name: &str, features: &Features) -> anyhow::Result> { self.0.write().load_family(name, features) }