1
1
mirror of https://github.com/wez/wezterm.git synced 2024-11-27 12:23:46 +03:00

fonts: place FontDataHandle in ParsedFont

This commit is contained in:
Wez Furlong 2021-04-08 11:58:52 -07:00
parent 364ab2a35b
commit 392fe098c9
5 changed files with 78 additions and 115 deletions

View File

@ -12,7 +12,6 @@ use std::sync::{Arc, Mutex};
struct Entry {
parsed: ParsedFont,
handle: FontDataHandle,
coverage: Mutex<Option<RangeSet<u32>>>,
}
@ -22,8 +21,8 @@ impl Entry {
fn compute_coverage(&self) -> anyhow::Result<RangeSet<u32>> {
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<ParsedFont>) {
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

View File

@ -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<FaceSize>,
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<u32> {
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<Face> {
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 {
index |= handle.variation << 16;
}
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 _)?,
};
if handle.variation != 0 {
unsafe {
ft_result(FT_Set_Named_Instance(face.face, handle.variation), ())
.context("FT_Set_Named_Instance")?;
}
Ok(Face {
face,
lib: self.lib,
source,
size: None,
})
}
Ok(face)
}
pub fn new_face<P>(&self, path: P, face_index: FT_Long) -> anyhow::Result<Face>
fn new_face<P>(&self, path: P, face_index: FT_Long) -> anyhow::Result<FT_Face>
where
P: AsRef<std::path::Path>,
{
@ -538,55 +546,27 @@ impl Library {
&mut face as *mut _,
)
};
return Ok(Face {
face: ft_result(res, face).with_context(|| {
return 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,
});
}
}
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<Face> {
fn new_face_from_slice(
&self,
data: &Cow<'static, [u8]>,
face_index: FT_Long,
) -> anyhow::Result<FT_Face> {
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<()> {

View File

@ -61,11 +61,11 @@ fn handle_from_descriptor(descriptor: &CTFontDescriptor) -> Option<FontDataHandl
let source = FontDataSource::OnDisk(path);
crate::parser::parse_and_collect_font_info(&source, &mut font_info).ok()?;
for (parsed, locator) in font_info {
for parsed in font_info {
if parsed.names().full_name == family_name
|| parsed.names().family.as_ref() == Some(&family_name)
{
return Some(locator);
return Some(parsed.handle);
}
}

View File

@ -157,9 +157,9 @@ fn handle_from_descriptor(
log::debug!("{} -> {}", 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);
}
}
}

View File

@ -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<Self> {
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<Self> {
pub fn from_face(face: &crate::ftwrap::Face, handle: FontDataHandle) -> anyhow::Result<Self> {
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<ParsedFont>) -> 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 {
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<ParsedFont>,
) -> 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<ParsedFont>,
) -> 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(())
}