diff --git a/wezterm-font/src/db.rs b/wezterm-font/src/db.rs index c48dc79b2..58945c370 100644 --- a/wezterm-font/src/db.rs +++ b/wezterm-font/src/db.rs @@ -12,7 +12,6 @@ use std::sync::{Arc, Mutex}; struct Entry { parsed: ParsedFont, - handle: FontDataHandle, coverage: Mutex>>, } @@ -22,8 +21,8 @@ impl Entry { fn compute_coverage(&self) -> anyhow::Result> { let lib = Library::new()?; let face = lib - .face_from_locator(&self.handle) - .with_context(|| format!("freetype parsing {:?}", self.handle))?; + .face_from_locator(&self.parsed.handle) + .with_context(|| format!("freetype parsing {:?}", self.parsed))?; Ok(face.compute_coverage()) } @@ -63,11 +62,10 @@ impl FontDatabase { } } - fn load_font_info(&mut self, font_info: Vec<(ParsedFont, FontDataHandle)>) { - for (parsed, handle) in font_info { + fn load_font_info(&mut self, font_info: Vec) { + for parsed in font_info { let entry = Arc::new(Entry { parsed, - handle, coverage: Mutex::new(None), }); @@ -163,7 +161,7 @@ impl FontDatabase { .with_context(|| format!("coverage_interaction for {:?}", entry.parsed))?; let len = covered.len(); if len > 0 { - matches.push((len, entry.handle.clone())); + matches.push((len, entry.parsed.handle.clone())); } } @@ -186,7 +184,7 @@ impl FontDatabase { pub fn resolve(&self, font_attr: &FontAttributes) -> Option<&FontDataHandle> { if let Some(entry) = self.by_full_name.get(&font_attr.family) { if entry.parsed.matches_attributes(font_attr) == FontMatch::FullName { - return Some(&entry.handle); + return Some(&entry.parsed.handle); } } @@ -200,7 +198,7 @@ impl FontDatabase { } candidates.sort_by(|a, b| a.0.cmp(&b.0)); let best = candidates.first()?; - return Some(&best.1.handle); + return Some(&best.1.parsed.handle); } None diff --git a/wezterm-font/src/ftwrap.rs b/wezterm-font/src/ftwrap.rs index 5102112e1..1f75a4835 100644 --- a/wezterm-font/src/ftwrap.rs +++ b/wezterm-font/src/ftwrap.rs @@ -73,11 +73,9 @@ pub fn compute_load_flags_from_config() -> (i32, FT_Render_Mode) { (load_flags as i32, render) } -type CowVecU8 = Cow<'static, [u8]>; - pub struct Face { pub face: FT_Face, - _bytes: CowVecU8, + source: FontDataHandle, size: Option, lib: FT_Library, } @@ -142,7 +140,12 @@ impl Face { let num_styles = (*mm).num_namedstyles; for i in 1..=num_styles { FT_Set_Named_Instance(self.face, i); - res.push(ParsedFont::from_face(&self)?); + let source = FontDataHandle { + source: self.source.source.clone(), + index: self.source.index, + variation: i, + }; + res.push(ParsedFont::from_face(&self, source)?); } FT_Done_MM_Var(self.lib, mm); @@ -492,37 +495,42 @@ impl Library { /// For a TTC, it will be the number of contained fonts pub fn query_num_faces(&self, source: &FontDataSource) -> anyhow::Result { let face = match source { - FontDataSource::OnDisk(path) => self - .new_face(path.to_str().unwrap(), -1) - .context("query_num_faces")?, + FontDataSource::OnDisk(path) => self.new_face(path, -1).context("query_num_faces")?, FontDataSource::Memory { data, .. } => self - .new_face_from_slice(data.clone(), -1) + .new_face_from_slice(&data, -1) .context("query_num_faces")?, }; - Ok(unsafe { (*face.face).num_faces }.try_into()?) + let num_faces = unsafe { (*face).num_faces }.try_into(); + + unsafe { + FT_Done_Face(face); + } + + Ok(num_faces?) } pub fn face_from_locator(&self, handle: &FontDataHandle) -> anyhow::Result { - let face = match &handle.source { - FontDataSource::OnDisk(path) => { - self.new_face(path.to_str().unwrap(), handle.index as _)? - } - FontDataSource::Memory { data, .. } => { - self.new_face_from_slice(data.clone(), handle.index as _)? - } - }; + let source = handle.clone(); + let mut index = handle.index; if handle.variation != 0 { - unsafe { - ft_result(FT_Set_Named_Instance(face.face, handle.variation), ()) - .context("FT_Set_Named_Instance")?; - } + index |= handle.variation << 16; } - Ok(face) + let face = match &source.source { + FontDataSource::OnDisk(path) => self.new_face(path.to_str().unwrap(), index as _)?, + FontDataSource::Memory { data, .. } => self.new_face_from_slice(&data, index as _)?, + }; + + Ok(Face { + face, + lib: self.lib, + source, + size: None, + }) } - pub fn new_face

(&self, path: P, face_index: FT_Long) -> anyhow::Result + fn new_face

(&self, path: P, face_index: FT_Long) -> anyhow::Result where P: AsRef, { @@ -538,55 +546,27 @@ impl Library { &mut face as *mut _, ) }; - return Ok(Face { - face: ft_result(res, face).with_context(|| { - format!( - "FT_New_Face for {} index {}", - path.as_ref().display(), - face_index - ) - })?, - _bytes: CowVecU8::Borrowed(b""), - size: None, - lib: self.lib, + return ft_result(res, face).with_context(|| { + format!( + "FT_New_Face for {} index {}", + path.as_ref().display(), + face_index + ) }); } } - let path = path.as_ref(); - - let data = std::fs::read(path)?; - log::trace!( - "Loading {} ({} bytes) for freetype!", - path.display(), - data.len() + anyhow::bail!( + "path {} cannot be represented as a c-string for freetype", + path.as_ref().display() ); - let data = CowVecU8::Owned(data); - - let res = unsafe { - FT_New_Memory_Face( - self.lib, - data.as_ptr(), - data.len() as _, - face_index, - &mut face as *mut _, - ) - }; - Ok(Face { - face: ft_result(res, face).with_context(|| { - format!( - "FT_New_Memory_Face for {} index {}", - path.display(), - face_index - ) - })?, - _bytes: data, - size: None, - lib: self.lib, - }) } - pub fn new_face_from_slice(&self, data: CowVecU8, face_index: FT_Long) -> anyhow::Result { + fn new_face_from_slice( + &self, + data: &Cow<'static, [u8]>, + face_index: FT_Long, + ) -> anyhow::Result { let mut face = ptr::null_mut(); let res = unsafe { @@ -598,13 +578,7 @@ impl Library { &mut face as *mut _, ) }; - Ok(Face { - face: ft_result(res, face) - .with_context(|| format!("FT_New_Memory_Face for index {}", face_index))?, - _bytes: data, - size: None, - lib: self.lib, - }) + ft_result(res, face).with_context(|| format!("FT_New_Memory_Face for index {}", face_index)) } pub fn set_lcd_filter(&mut self, filter: FT_LcdFilter) -> anyhow::Result<()> { diff --git a/wezterm-font/src/locator/core_text.rs b/wezterm-font/src/locator/core_text.rs index 00270e6c4..e815056df 100644 --- a/wezterm-font/src/locator/core_text.rs +++ b/wezterm-font/src/locator/core_text.rs @@ -61,11 +61,11 @@ fn handle_from_descriptor(descriptor: &CTFontDescriptor) -> Option {}", family_name, path.display()); let source = FontDataSource::OnDisk(path); if parse_and_collect_font_info(&source, &mut font_info).is_ok() { - for (parsed, handle) in font_info { + for parsed in font_info { if parsed.matches_attributes(attr) != FontMatch::NoMatch { - return Some(handle); + return Some(parsed.handle); } } } diff --git a/wezterm-font/src/parser.rs b/wezterm-font/src/parser.rs index d861b88b2..c893812ac 100644 --- a/wezterm-font/src/parser.rs +++ b/wezterm-font/src/parser.rs @@ -110,6 +110,7 @@ pub struct ParsedFont { weight: FontWeight, width: FontWidth, italic: bool, + pub handle: FontDataHandle, } #[derive(Debug)] @@ -145,10 +146,10 @@ impl ParsedFont { pub fn from_locator(handle: &FontDataHandle) -> anyhow::Result { let lib = crate::ftwrap::Library::new()?; let face = lib.face_from_locator(handle)?; - Self::from_face(&face) + Self::from_face(&face, handle.clone()) } - pub fn from_face(face: &crate::ftwrap::Face) -> anyhow::Result { + pub fn from_face(face: &crate::ftwrap::Face, handle: FontDataHandle) -> anyhow::Result { let italic = face.italic(); let (weight, width) = face.weight_and_width(); let weight = FontWeight::from_opentype_weight(weight); @@ -159,6 +160,7 @@ impl ParsedFont { weight, width, italic, + handle, }) } @@ -249,7 +251,7 @@ pub fn resolve_font_from_ttc_data( for index in 0..num_faces { locator.set_index(index); let face = lib.face_from_locator(&locator)?; - let parsed = ParsedFont::from_face(&face)?; + let parsed = ParsedFont::from_face(&face, locator.clone())?; if parsed.matches_attributes(attr) != FontMatch::NoMatch { return Ok(Some(index as usize)); @@ -262,9 +264,7 @@ pub fn resolve_font_from_ttc_data( /// we bundle JetBrains Mono and Noto Color Emoji to act as reasonably /// sane fallback fonts. /// This function loads those. -pub(crate) fn load_built_in_fonts( - font_info: &mut Vec<(ParsedFont, FontDataHandle)>, -) -> anyhow::Result<()> { +pub(crate) fn load_built_in_fonts(font_info: &mut Vec) -> anyhow::Result<()> { macro_rules! font { ($font:literal) => { (include_bytes!($font) as &'static [u8], $font) @@ -290,19 +290,17 @@ pub(crate) fn load_built_in_fonts( font!("../../assets/fonts/PowerlineExtraSymbols.otf"), font!("../../assets/fonts/LastResortHE-Regular.ttf"), ] { - let face = lib.new_face_from_slice(Cow::Borrowed(data), 0)?; - let parsed = ParsedFont::from_face(&face)?; - font_info.push(( - parsed, - FontDataHandle { - source: FontDataSource::Memory { - data: Cow::Borrowed(data), - name: name.to_string(), - }, - index: 0, - variation: 0, + let locator = FontDataHandle { + source: FontDataSource::Memory { + data: Cow::Borrowed(data), + name: name.to_string(), }, - )); + index: 0, + variation: 0, + }; + let face = lib.face_from_locator(&locator)?; + let parsed = ParsedFont::from_face(&face, locator)?; + font_info.push(parsed); } Ok(()) @@ -310,7 +308,7 @@ pub(crate) fn load_built_in_fonts( pub(crate) fn parse_and_collect_font_info( source: &FontDataSource, - font_info: &mut Vec<(ParsedFont, FontDataHandle)>, + font_info: &mut Vec, ) -> anyhow::Result<()> { let lib = crate::ftwrap::Library::new()?; let num_faces = lib.query_num_faces(&source)?; @@ -319,7 +317,7 @@ pub(crate) fn parse_and_collect_font_info( lib: &crate::ftwrap::Library, source: &FontDataSource, index: u32, - font_info: &mut Vec<(ParsedFont, FontDataHandle)>, + font_info: &mut Vec, ) -> anyhow::Result<()> { let locator = FontDataHandle { source: source.clone(), @@ -329,19 +327,12 @@ pub(crate) fn parse_and_collect_font_info( let face = lib.face_from_locator(&locator)?; if let Ok(variations) = face.variations() { - for (variation, parsed) in variations.into_iter().enumerate() { - font_info.push(( - parsed, - FontDataHandle { - source: source.clone(), - index, - variation: variation as u32 + 1, - }, - )); + for parsed in variations { + font_info.push(parsed); } } else { let parsed = ParsedFont::from_locator(&locator)?; - font_info.push((parsed, locator)); + font_info.push(parsed); } Ok(()) }