1
1
mirror of https://github.com/wez/wezterm.git synced 2024-11-10 15:04:32 +03:00

font-config: fall back to searching by postscript name

Our first pass is to match based on the overall constraints
supplied by the user, but if that fails, we fall back to
looking up by postscript name.
This commit is contained in:
Wez Furlong 2021-04-09 10:26:46 -07:00
parent 16e7457049
commit 0694e905e8
2 changed files with 75 additions and 39 deletions

View File

@ -310,7 +310,6 @@ impl Pattern {
}
pub fn list(&self) -> anyhow::Result<FontSet> {
log::trace!("listing: {:?}", self);
unsafe {
// This defines the fields that are retrieved
let oset = FcObjectSetCreate();

View File

@ -23,52 +23,89 @@ impl FontLocator for FontConfigFontLocator {
) -> anyhow::Result<Vec<ParsedFont>> {
let mut fonts = vec![];
for attr in fonts_selection {
for &spacing in &SPACING {
let mut pattern = FontPattern::new()?;
let start = std::time::Instant::now();
pattern.family(&attr.family)?;
pattern.add_integer("weight", to_fc_weight(attr.weight))?;
pattern.add_integer("width", to_fc_width(attr.width))?;
pattern.add_integer(
"slant",
if attr.italic {
fcwrap::FC_SLANT_ITALIC
} else {
fcwrap::FC_SLANT_ROMAN
},
)?;
pattern.add_integer("spacing", spacing)?;
fn by_family(attr: &FontAttributes, spacing: i32) -> anyhow::Result<FontPattern> {
let mut pattern = FontPattern::new()?;
let start = std::time::Instant::now();
pattern.family(&attr.family)?;
pattern.add_integer("weight", to_fc_weight(attr.weight))?;
pattern.add_integer("width", to_fc_width(attr.width))?;
pattern.add_integer(
"slant",
if attr.italic {
fcwrap::FC_SLANT_ITALIC
} else {
fcwrap::FC_SLANT_ROMAN
},
)?;
pattern.add_integer("spacing", spacing)?;
log::trace!("fc pattern before config subst: {:?}", pattern);
pattern.config_substitute(fcwrap::MatchKind::Pattern)?;
pattern.default_substitute();
log::trace!("fc pattern before config subst: {:?}", pattern);
pattern.config_substitute(fcwrap::MatchKind::Pattern)?;
pattern.default_substitute();
let best = pattern.get_best_match()?;
let best = pattern.get_best_match()?;
log::trace!(
"best match took {:?} to compute and is {:?}",
start.elapsed(),
best
);
Ok(best)
}
fn by_postscript(attr: &FontAttributes, _spacing: i32) -> anyhow::Result<FontPattern> {
let mut pattern = FontPattern::new()?;
let start = std::time::Instant::now();
pattern.add_string("postscriptname", &attr.family)?;
let matches = pattern.list()?;
for best in matches.iter() {
log::trace!(
"best match took {:?} to compute and is {:?}",
"listing by postscriptname took {:?} to compute and is {:?}",
start.elapsed(),
best
);
return Ok(best);
}
let file = best.get_file()?;
let index = best.get_integer("index")? as u32;
let variation = index >> 16;
let index = index & 0xffff;
let handle = FontDataHandle {
source: FontDataSource::OnDisk(file.into()),
index,
variation,
};
log::trace!(
"listing by postscriptname took {:?} to compute and produced no results",
start.elapsed(),
);
anyhow::bail!("no match for postscript name");
}
// fontconfig will give us a boatload of random fallbacks.
// so we need to parse the returned font
// here to see if we got what we asked for.
if let Ok(parsed) = crate::parser::ParsedFont::from_locator(&handle) {
if parsed.matches_attributes(attr) != FontMatch::NoMatch {
log::trace!("found font-config match for {:?}", parsed.names());
fonts.push(parsed);
loaded.insert(attr.clone());
for attr in fonts_selection {
for &spacing in &SPACING {
if loaded.contains(&attr) {
continue;
}
// First, we assume that attr.family is the family name.
// If that doesn't work, we try by postscript name.
for resolver in &[by_family, by_postscript] {
match resolver(attr, spacing) {
Ok(best) => {
let file = best.get_file()?;
let index = best.get_integer("index")? as u32;
let variation = index >> 16;
let index = index & 0xffff;
let handle = FontDataHandle {
source: FontDataSource::OnDisk(file.into()),
index,
variation,
};
// fontconfig will give us a boatload of random fallbacks.
// so we need to parse the returned font
// here to see if we got what we asked for.
if let Ok(parsed) = crate::parser::ParsedFont::from_locator(&handle) {
if parsed.matches_attributes(attr) != FontMatch::NoMatch {
log::trace!("found font-config match for {:?}", parsed.names());
fonts.push(parsed);
loaded.insert(attr.clone());
}
}
}
Err(err) => log::trace!("while searching for {:?}: {:#}", attr, err),
}
}
}