mirror of
https://github.com/wez/wezterm.git
synced 2024-09-21 03:39:16 +03:00
wezterm: avoid implausible font sizes in shaper metrics
In this scenario: ```lua local wezterm = require "wezterm" return { font_size = 12.0, font_dirs = {"/home/wez/.fonts"}, font_locator = "ConfigDirsOnly", font = wezterm.font_with_fallback({ -- this is an invalid font "does not exist", "Noto Color Emoji", }), } ``` we'd take the metrics from the emoji font and the cell size would be crazy huge. With this change we filter out "outliers" based on the approximate pixel size for a font given its size and dpi. If a fallback position is significantly larger or smaller than the theoretical size then we skip it when considering the metrics. The result of this is that with the above configuration we end up with `{"Noto Color Emoji", "JetBrains Mono"}` as the font order; most of the textual glyphs will render from `JetBrains Mono` but the number glyphs prefer the `Noto Color Emoji` renditions which are typically double width. While the terminal looks a bit cartoonish as a result of that selection, the sizes are much more reasonable compared to the screenshot in #263. refs: #263
This commit is contained in:
parent
b3f51e8ee2
commit
bc1d4bba35
@ -267,9 +267,39 @@ impl FontShaper for HarfbuzzShaper {
|
||||
}
|
||||
|
||||
fn metrics(&self, size: f64, dpi: u32) -> anyhow::Result<FontMetrics> {
|
||||
// Returns the metrics for the selected font... but look out
|
||||
// for implausible sizes.
|
||||
// Ideally we wouldn't need this, but in the event that a user
|
||||
// has a wonky configuration we don't want to pick something
|
||||
// like a bitmap emoji font for the metrics or well end up
|
||||
// with crazy huge cells.
|
||||
// We do a sniff test based on the theoretical pixel height for
|
||||
// the supplied size+dpi.
|
||||
// If a given fallback slot deviates from the theoretical size
|
||||
// by too much we'll skip to the next slot.
|
||||
let theoretical_height = size * dpi as f64 / 72.0;
|
||||
let mut metrics_idx = 0;
|
||||
while let Ok(Some(mut pair)) = self.load_fallback(metrics_idx) {
|
||||
let (_, cell_height) = pair.face.set_font_size(size, dpi)?;
|
||||
let diff = (theoretical_height - cell_height).abs();
|
||||
let factor = diff / theoretical_height;
|
||||
if factor < 2.0 {
|
||||
break;
|
||||
}
|
||||
log::trace!(
|
||||
"skip idx {} because diff={} factor={} theoretical_height={} cell_height={}",
|
||||
metrics_idx,
|
||||
diff,
|
||||
factor,
|
||||
theoretical_height,
|
||||
cell_height
|
||||
);
|
||||
metrics_idx += 1;
|
||||
}
|
||||
|
||||
let mut pair = self
|
||||
.load_fallback(0)?
|
||||
.ok_or_else(|| anyhow!("unable to load first font!?"))?;
|
||||
.load_fallback(metrics_idx)?
|
||||
.ok_or_else(|| anyhow!("unable to load font idx {}!?", metrics_idx))?;
|
||||
let (cell_width, cell_height) = pair.face.set_font_size(size, dpi)?;
|
||||
let y_scale = unsafe { (*(*pair.face.face).size).metrics.y_scale as f64 / 65536.0 };
|
||||
let metrics = FontMetrics {
|
||||
|
Loading…
Reference in New Issue
Block a user