mirror of
https://github.com/wez/wezterm.git
synced 2024-12-24 05:42:03 +03:00
fonts: handle bitmap-only fonts better
terminus-bold.otb reports 0 height! Detect and force that case to go through the bitmap strike loading code path. Improve the size selection heuristic for bitmap strikes: previously, we would just pick the largest bitmap and allow it to be scaled down, which was OK for emoji fonts that just had 128px square glyphs, but is not ok for pre-rendered pixel strikes like terminus. Note that IncreaseFontSize works in terms of percentages only, so using a font like this may have "gaps" when ctrl-+ or - to change the font size. refs: https://github.com/wez/wezterm/issues/560
This commit is contained in:
parent
d62d2a5133
commit
1cf335cb45
@ -12,6 +12,7 @@ brief notes about them may accumulate here.
|
|||||||
|
|
||||||
* Fixed: 100% CPU due to spurious resize events generated by herbstluftwm. [#557](https://github.com/wez/wezterm/issues/557)
|
* Fixed: 100% CPU due to spurious resize events generated by herbstluftwm. [#557](https://github.com/wez/wezterm/issues/557)
|
||||||
* Fixed: improved conformance with xterm for keys like CTRL-6 and CTRL-/. [#556](https://github.com/wez/wezterm/discussions/556)
|
* Fixed: improved conformance with xterm for keys like CTRL-6 and CTRL-/. [#556](https://github.com/wez/wezterm/discussions/556)
|
||||||
|
* Fixed: detection and handling of fonts such as terminus-bold.otb that contain only bitmap strikes. [#560](https://github.com/wez/wezterm/issues/560)
|
||||||
|
|
||||||
### 20210314-114017-04b7cedd
|
### 20210314-114017-04b7cedd
|
||||||
|
|
||||||
|
@ -89,7 +89,14 @@ impl Face {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log::debug!("set_char_size computing {} dpi={}", point_size, dpi);
|
let pixel_height = point_size * dpi as f64 / 72.0;
|
||||||
|
log::debug!(
|
||||||
|
"set_char_size computing {} dpi={} (pixel height={})",
|
||||||
|
point_size,
|
||||||
|
dpi,
|
||||||
|
pixel_height
|
||||||
|
);
|
||||||
|
|
||||||
// Scaling before truncating to integer minimizes the chances of hitting
|
// Scaling before truncating to integer minimizes the chances of hitting
|
||||||
// the fallback code for set_pixel_sizes below.
|
// the fallback code for set_pixel_sizes below.
|
||||||
let size = (point_size * 64.0) as FT_F26Dot6;
|
let size = (point_size * 64.0) as FT_F26Dot6;
|
||||||
@ -100,6 +107,8 @@ impl Face {
|
|||||||
self.cell_metrics()
|
self.cell_metrics()
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
|
log::debug!("set_char_size: {:?}, will inspect strikes", err);
|
||||||
|
|
||||||
let sizes = unsafe {
|
let sizes = unsafe {
|
||||||
let rec = &(*self.face);
|
let rec = &(*self.face);
|
||||||
std::slice::from_raw_parts(rec.available_sizes, rec.num_fixed_sizes as usize)
|
std::slice::from_raw_parts(rec.available_sizes, rec.num_fixed_sizes as usize)
|
||||||
@ -107,24 +116,42 @@ impl Face {
|
|||||||
if sizes.is_empty() {
|
if sizes.is_empty() {
|
||||||
return Err(err);
|
return Err(err);
|
||||||
}
|
}
|
||||||
// Find the best matching size.
|
// Find the best matching size; we look for the strike whose height
|
||||||
// We just take the biggest.
|
// is closest to the desired size.
|
||||||
let mut best = 0;
|
struct Best {
|
||||||
let mut best_size = 0;
|
idx: usize,
|
||||||
let mut cell_width = 0;
|
distance: usize,
|
||||||
let mut cell_height = 0;
|
height: i16,
|
||||||
|
width: i16,
|
||||||
|
}
|
||||||
|
let mut best: Option<Best> = None;
|
||||||
|
|
||||||
for (idx, info) in sizes.iter().enumerate() {
|
for (idx, info) in sizes.iter().enumerate() {
|
||||||
let size = best_size.max(info.height);
|
log::debug!("idx={} info={:?}", idx, info);
|
||||||
if size > best_size {
|
let distance = (info.height - (pixel_height as i16)).abs() as usize;
|
||||||
best = idx;
|
let candidate = Best {
|
||||||
best_size = size;
|
idx,
|
||||||
cell_width = info.width;
|
distance,
|
||||||
cell_height = info.height;
|
height: info.height,
|
||||||
|
width: info.width,
|
||||||
|
};
|
||||||
|
|
||||||
|
match best.take() {
|
||||||
|
Some(existing) => {
|
||||||
|
best.replace(if candidate.distance < existing.distance {
|
||||||
|
candidate
|
||||||
|
} else {
|
||||||
|
existing
|
||||||
|
});
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
best.replace(candidate);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.select_size(best)?;
|
let best = best.unwrap();
|
||||||
(f64::from(cell_width), f64::from(cell_height))
|
self.select_size(best.idx)?;
|
||||||
|
(f64::from(best.width), f64::from(best.height))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -157,7 +184,15 @@ impl Face {
|
|||||||
},
|
},
|
||||||
(),
|
(),
|
||||||
)
|
)
|
||||||
.context("FT_Set_Char_Size")
|
.context("FT_Set_Char_Size")?;
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
if (*self.face).height == 0 {
|
||||||
|
anyhow::bail!("font has 0 height, fallback to bitmaps");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn select_size(&mut self, idx: usize) -> anyhow::Result<()> {
|
fn select_size(&mut self, idx: usize) -> anyhow::Result<()> {
|
||||||
|
Loading…
Reference in New Issue
Block a user