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

fonts: workaround broken symbol fonts with 0 advances

The broot icon font has glyphs with horizontal advance set to 0.  That
would cause us to consider the glyph to be zero width, so handle that as
a special case.  Note that it is legit for certain cells to end up with
a zero advance/width during shaping if they represent combining
characters: this is more common in Arabic scripts.

refs: https://github.com/wez/wezterm/issues/1787
This commit is contained in:
Wez Furlong 2022-03-28 18:05:13 -07:00
parent 20688c4a62
commit a2004a2a7d
2 changed files with 16 additions and 4 deletions

View File

@ -765,6 +765,7 @@ impl Face {
/ (f64::from(0x1_0000) * 64.0); / (f64::from(0x1_0000) * 64.0);
let mut width = 0.0; let mut width = 0.0;
let mut num_examined = 0;
for i in 32..128 { for i in 32..128 {
let glyph_pos = FT_Get_Char_Index(self.face, i); let glyph_pos = FT_Get_Char_Index(self.face, i);
if glyph_pos == 0 { if glyph_pos == 0 {
@ -772,6 +773,7 @@ impl Face {
} }
let res = FT_Load_Glyph(self.face, glyph_pos, FT_LOAD_COLOR as i32); let res = FT_Load_Glyph(self.face, glyph_pos, FT_LOAD_COLOR as i32);
if succeeded(res) { if succeeded(res) {
num_examined += 1;
let glyph = &(*(*self.face).glyph); let glyph = &(*(*self.face).glyph);
if glyph.metrics.horiAdvance as f64 > width { if glyph.metrics.horiAdvance as f64 > width {
width = glyph.metrics.horiAdvance as f64; width = glyph.metrics.horiAdvance as f64;
@ -784,6 +786,7 @@ impl Face {
for glyph_pos in 1..8 { for glyph_pos in 1..8 {
let res = FT_Load_Glyph(self.face, glyph_pos, FT_LOAD_COLOR as i32); let res = FT_Load_Glyph(self.face, glyph_pos, FT_LOAD_COLOR as i32);
if succeeded(res) { if succeeded(res) {
num_examined += 1;
let glyph = &(*(*self.face).glyph); let glyph = &(*(*self.face).glyph);
if glyph.metrics.horiAdvance as f64 > width { if glyph.metrics.horiAdvance as f64 > width {
width = glyph.metrics.horiAdvance as f64; width = glyph.metrics.horiAdvance as f64;
@ -792,7 +795,9 @@ impl Face {
} }
if width == 0.0 { if width == 0.0 {
log::error!( log::error!(
"Couldn't find any glyphs for metrics, so guessing width == height" "Couldn't find usable advance metrics out of {} glyphs \
sampled from the font, so guessing width == height",
num_examined,
); );
width = height * 64.; width = height * 64.;
} }

View File

@ -468,11 +468,18 @@ impl HarfbuzzShaper {
for info in infos.iter() { for info in infos.iter() {
// Proportional width based on relative pixel dimensions vs. other glyphs in // Proportional width based on relative pixel dimensions vs. other glyphs in
// this same cluster // this same cluster
let weighted_cell_width = (cluster_info.cell_width as f64 * info.x_advance as f64
/ total_width)
.ceil() as u8;
// Note that weighted_cell_width can legitimately compute as zero here // Note that weighted_cell_width can legitimately compute as zero here
// for the case where a combining mark composes over another glyph // for the case where a combining mark composes over another glyph
// However, some symbol fonts have broken advance metrics and we don't
// want those glyphs to end up with zero width, so if this run is zero
// width then we round up to 1 cell.
// <https://github.com/wez/wezterm/issues/1787>
let weighted_cell_width = if total_width == 0. {
1
} else {
(cluster_info.cell_width as f64 * info.x_advance as f64 / total_width).ceil()
as u8
};
let weighted_cell_width = weighted_cell_width.min(remaining_cells); let weighted_cell_width = weighted_cell_width.min(remaining_cells);
remaining_cells = remaining_cells.saturating_sub(weighted_cell_width); remaining_cells = remaining_cells.saturating_sub(weighted_cell_width);