1
1
mirror of https://github.com/wez/wezterm.git synced 2024-11-22 22:42:48 +03:00

freetype: colr: fixup crazy scaling issue in char selector

Popping open the char selector could result in comedy-sized emoji
that dramatically overflow the bounds.

The reason for that is that glyphcache isn't smart enough to notice
when the glyph.height exceeds the cell_height and allows the glyph
bitmap to be rendered at the rasterized size.

The reason for that glyph being so huge is that freetype is producing
outlines that are too large.  The font metrics have the requested
x and y ppem values (eg: the nominal font size in pixels), but also
x and y scaling values that are not set to 1.  The result is that
the produced extents are too large by those x and y scaling values.

I'm not sure why that is, but it is simplest and most self-contained
to adjust for that scale factor when we rasterize via cairo, so that
is what we do here.
This commit is contained in:
Wez Furlong 2023-08-20 19:47:00 -07:00
parent b6ba87ad3c
commit 017432d0cf
No known key found for this signature in database
GPG Key ID: 7A7F66A31EC9B387

View File

@ -327,12 +327,31 @@ impl FreeTypeRasterizer {
glyph_pos,
FT_Color_Root_Transform::FT_COLOR_INCLUDE_ROOT_TRANSFORM,
)?;
let clip_box = face.get_color_glyph_clip_box(glyph_pos)?;
// The root transform produces extents that are larger than
// our nominal pixel size. I'm not sure why that is, but the
// factor corresponds to the metrics.(x|y)_scale in the root
// transform.
// It is desirable to retain the root transform as it includes
// any skew that may have been applied to the font.
// So let's extract the offending scaling factors and we'll
// compensate when we rasterize the paths.
let (scale_x, scale_y) = unsafe {
let upem = (*face.face).units_per_EM as f64;
let metrics = (*(*face.face).size).metrics;
log::trace!("upem={upem}, metrics: {metrics:#?}");
(
1. / metrics.x_scale.to_num::<f64>(),
1. / metrics.y_scale.to_num::<f64>(),
)
};
let palette = face.get_palette_data()?;
log::trace!("Palette: {palette:#?}");
face.select_palette(0)?;
let clip_box = face.get_color_glyph_clip_box(glyph_pos)?;
log::trace!("got clip_box: {clip_box:?}");
let mut walker = Walker {
load_flags,
@ -343,7 +362,7 @@ impl FreeTypeRasterizer {
log::trace!("ops: {:#?}", walker.ops);
rasterize_from_ops(walker.ops, 1., -1.)
rasterize_from_ops(walker.ops, scale_x, -scale_y)
}
}