mirror of
https://github.com/wez/wezterm.git
synced 2024-11-23 15:04:36 +03:00
fonts: place FontDataHandle in ParsedFont
This commit is contained in:
parent
364ab2a35b
commit
392fe098c9
@ -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
|
||||
|
@ -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 {
|
||||
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<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(|| {
|
||||
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<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<()> {
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
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<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(())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user