1
1
mirror of https://github.com/wez/wezterm.git synced 2024-12-24 22:01:47 +03:00

macos: fonts: fix a potential unterminated loop

for fonts located by core text, if they are singular TTF files rather
than TTC files, and the font doesn't exactly match the search critiera,
we could loop forever re-parsing the same file over and over again.

This commit restructures the logic to definitively check the number
of contained font entries and constrain the loop to that number.

In addition, it adjusts the name matching, as macos can return
names like "Cascadia Code Roman" when the underlying font is named
"Cascadia Code".

refs: https://github.com/wez/wezterm/issues/475
This commit is contained in:
Wez Furlong 2021-02-25 20:47:02 -08:00
parent 35060fb2de
commit 4e27607615

View File

@ -10,6 +10,7 @@ use core_foundation::string::CFString;
use core_text::font::*; use core_text::font::*;
use core_text::font_descriptor::*; use core_text::font_descriptor::*;
use std::collections::HashSet; use std::collections::HashSet;
use ttf_parser::fonts_in_collection;
/// A FontLocator implemented using the system font loading /// A FontLocator implemented using the system font loading
/// functions provided by core text. /// functions provided by core text.
@ -51,15 +52,24 @@ fn descriptor_from_attr(attr: &FontAttributes) -> anyhow::Result<CTFontDescripto
fn handle_from_descriptor(descriptor: &CTFontDescriptor) -> Option<FontDataHandle> { fn handle_from_descriptor(descriptor: &CTFontDescriptor) -> Option<FontDataHandle> {
let path = descriptor.font_path()?; let path = descriptor.font_path()?;
let name = descriptor.display_name(); let name = descriptor.display_name();
let family_name = descriptor.family_name();
for index in 0.. { let data = std::fs::read(path).ok()?;
let handle = FontDataHandle::OnDisk { let size = fonts_in_collection(&data).unwrap_or(1);
path: path.clone(),
index, let mut handle = FontDataHandle::Memory {
data,
name,
index: 0,
}; };
for index in 0..size {
if let FontDataHandle::Memory { index: idx, .. } = &mut handle {
*idx = index;
}
let parsed = crate::parser::ParsedFont::from_locator(&handle).ok()?; let parsed = crate::parser::ParsedFont::from_locator(&handle).ok()?;
let names = parsed.names(); let names = parsed.names();
if names.full_name == name { if names.full_name == family_name || names.family.as_ref() == Some(&family_name) {
return Some(handle); return Some(handle);
} }
} }