Fix the fonts panic

co-authored-by: Piotr <piotr@zed.dev>
This commit is contained in:
Kirill Bulatov 2024-01-22 20:06:21 +02:00
parent 2bfbd72483
commit a75fa35a08

View file

@ -81,13 +81,11 @@ impl PlatformTextSystem for MacTextSystem {
fn all_font_names(&self) -> Vec<String> {
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<FontStyle> 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<String> {
unsafe { get_string_attribute(descriptor, kCTFontFamilyNameAttribute) }
}
fn get_string_attribute(
descriptor: &CTFontDescriptor,
attribute: CFStringRef,
) -> Option<String> {
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::<CFString>());
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};