diff --git a/crates/gpui/src/platform/mac/text_system.rs b/crates/gpui/src/platform/mac/text_system.rs index ba434026f6..21fe3c70a8 100644 --- a/crates/gpui/src/platform/mac/text_system.rs +++ b/crates/gpui/src/platform/mac/text_system.rs @@ -81,13 +81,11 @@ impl PlatformTextSystem for MacTextSystem { fn all_font_names(&self) -> Vec { let collection = core_text::font_collection::create_for_all_families(); let Some(descriptors) = collection.get_descriptors() else { - return vec![]; + return Vec::new(); }; let mut names = BTreeSet::new(); for descriptor in descriptors.into_iter() { - names.insert(descriptor.font_name()); - names.insert(descriptor.family_name()); - names.insert(descriptor.style_name()); + names.extend(lenient_font_attributes::family_name(&descriptor)); } if let Ok(fonts_in_memory) = self.0.read().memory_source.all_families() { names.extend(fonts_in_memory); @@ -612,6 +610,45 @@ impl From for FontkitStyle { } } +// Some fonts may have no attributest despite `core_text` requiring them (and panicking). +// This is the same version as `core_text` has without `expect` calls. +mod lenient_font_attributes { + use core_foundation::{ + base::{CFRetain, CFType, TCFType}, + string::{CFString, CFStringRef}, + }; + use core_text::font_descriptor::{ + kCTFontFamilyNameAttribute, CTFontDescriptor, CTFontDescriptorCopyAttribute, + }; + + pub fn family_name(descriptor: &CTFontDescriptor) -> Option { + unsafe { get_string_attribute(descriptor, kCTFontFamilyNameAttribute) } + } + + fn get_string_attribute( + descriptor: &CTFontDescriptor, + attribute: CFStringRef, + ) -> Option { + unsafe { + let value = CTFontDescriptorCopyAttribute(descriptor.as_concrete_TypeRef(), attribute); + if value.is_null() { + return None; + } + + let value = CFType::wrap_under_create_rule(value); + assert!(value.instance_of::()); + let s = wrap_under_get_rule(value.as_CFTypeRef() as CFStringRef); + Some(s.to_string()) + } + } + + unsafe fn wrap_under_get_rule(reference: CFStringRef) -> CFString { + assert!(!reference.is_null(), "Attempted to create a NULL object."); + let reference = CFRetain(reference as *const ::std::os::raw::c_void) as CFStringRef; + TCFType::wrap_under_create_rule(reference) + } +} + #[cfg(test)] mod tests { use crate::{font, px, FontRun, MacTextSystem, PlatformTextSystem};