1
1
mirror of https://github.com/wez/wezterm.git synced 2024-12-23 13:21:38 +03:00

fontconfig: allow proportional fallbacks for codepoints

refs: https://github.com/wez/wezterm/discussions/2468#discussioncomment-3528085
This commit is contained in:
Wez Furlong 2022-09-04 07:05:58 -07:00
parent 821e833ad0
commit c38816fc6e
2 changed files with 60 additions and 41 deletions

View File

@ -11,7 +11,10 @@ usually the best available version.
As features stabilize some brief notes about them will accumulate here.
* Not yet
#### Changed
* fontconfig: when locating a fallback font for a given codepoint, allow
matching non-monospace fonts if we can't find any matching monospace fonts.
[#2468](https://github.com/wez/wezterm/discussions/2468)
### 20220904-064125-9a6cee2b

View File

@ -170,52 +170,68 @@ impl FontLocator for FontConfigFontLocator {
charset.add(c)?;
}
let mut pattern = FontPattern::new()?;
pattern.add_charset(&charset)?;
pattern.add_integer("weight", 80)?;
pattern.add_integer("slant", 0)?;
let mut lists = vec![pattern
.list()
.context("pattern.list with no spacing constraint")?];
for &spacing in &SPACING {
pattern.delete_property("spacing")?;
pattern.add_integer("spacing", spacing)?;
lists.push(
pattern
.list()
.with_context(|| format!("pattern.list with spacing={}", spacing))?,
);
}
let mut fonts = vec![];
for list in lists {
for pat in list.iter() {
let num = pat.charset_intersect_count(&charset)?;
if num == 0 {
log::error!(
"Skipping bogus font-config result {:?} because it doesn't overlap",
pat
);
continue;
}
// Make two passes to locate a fallback: first try to find any
// strictly monospace version, then, if we didn't find any matches,
// look for a version with any spacing.
for only_monospace in [true, false] {
let mut pattern = FontPattern::new()?;
pattern.add_charset(&charset)?;
pattern.add_integer("weight", 80)?;
pattern.add_integer("slant", 0)?;
if let Ok(file) = pat.get_file().context("pat.get_file") {
log::trace!("{file:?} has {num} codepoints from {codepoints:?}");
let handle = FontDataHandle {
source: FontDataSource::OnDisk(file.into()),
index: pat.get_integer("index")?.try_into()?,
variation: 0,
origin: FontOrigin::FontConfig,
coverage: pat.get_charset().ok().map(|c| c.to_range_set()),
};
if let Ok(parsed) = crate::parser::ParsedFont::from_locator(&handle) {
fonts.push(parsed);
let mut lists = vec![pattern
.list()
.context("pattern.list with no spacing constraint")?];
if only_monospace {
for &spacing in &SPACING {
pattern.delete_property("spacing")?;
pattern.add_integer("spacing", spacing)?;
lists.push(
pattern
.list()
.with_context(|| format!("pattern.list with spacing={}", spacing))?,
);
}
}
for list in lists {
for pat in list.iter() {
let num = pat.charset_intersect_count(&charset)?;
if num == 0 {
log::error!(
"Skipping bogus font-config result {:?} because it doesn't overlap",
pat
);
continue;
}
if let Ok(file) = pat.get_file().context("pat.get_file") {
log::trace!("{file:?} has {num} codepoints from {codepoints:?}");
let handle = FontDataHandle {
source: FontDataSource::OnDisk(file.into()),
index: pat.get_integer("index")?.try_into()?,
variation: 0,
origin: FontOrigin::FontConfig,
coverage: pat.get_charset().ok().map(|c| c.to_range_set()),
};
if let Ok(parsed) = crate::parser::ParsedFont::from_locator(&handle) {
fonts.push(parsed);
}
}
}
}
if fonts.is_empty() {
// If we get here on the first iteration, then we didn't
// find a monospace version of fonts with those codepoints,
// let's continue and try any matching font
continue;
}
break;
}
Ok(fonts)