mirror of
https://github.com/wez/wezterm.git
synced 2024-12-22 12:51:31 +03:00
adventures in shaping
This commit is a result of debugging a problem with a particular font where a VS2 variation of a glyph produced incorrect shaping. Further investigation showed that this was specific to using freetype font functions and that switching to opentype functions produces the correct shaping information in that case. Further-further investigation showed that this difference in behavior was really due to the font file being out of spec and freetype returning unexpected data as a result. This commit allows switching to using harfbuzz's own opentype font+face (rather than freetype) and/or switching the freetype-based font to using opentype font functions. These two options don't yield equivalent results in the wezterm integration: a couple of our shaping tests fail due to the x-advances not being the same. Those can be drastically different in some cases (eg: I seem to get 0 for certain bitmap strikes, and for Roboto the value is off by a factor of about 1.5). This is incomplete and not something I want to turn on by default at the moment, but I don't want to lose this work, hence this commit. refs: https://github.com/wez/wezterm/issues/2475 refs: https://github.com/harfbuzz/harfbuzz/issues/3806
This commit is contained in:
parent
2af5a05d19
commit
c4d19afa75
3
test-data/vs1-vs2.txt
Normal file
3
test-data/vs1-vs2.txt
Normal file
@ -0,0 +1,3 @@
|
||||
1d49c 𝒜 𝒜︀ 𝒜︁
|
||||
212c ℬ ℬ︀ ℬ︁
|
||||
1d49e 𝒞 𝒞︀ 𝒞︁
|
@ -14,6 +14,16 @@ use thiserror::Error;
|
||||
use unicode_segmentation::UnicodeSegmentation;
|
||||
use wezterm_bidi::Direction;
|
||||
|
||||
// Changing these will switch to using harfbuzz's opentype functions.
|
||||
// There's something awry with our integration in that mode: the advances
|
||||
// aren't equivalent to its freetype functions and this manifests most
|
||||
// prominently in proportional fonts as well as with fonts with bitmap
|
||||
// strikes.
|
||||
// Until we get to the bottom of this, these are compile-time rather
|
||||
// than runtime configs.
|
||||
const USE_OT_FUNCS: bool = false;
|
||||
const USE_OT_FACE: bool = false;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct Info {
|
||||
cluster: usize,
|
||||
@ -138,13 +148,19 @@ impl HarfbuzzShaper {
|
||||
let handle = &self.handles[font_idx];
|
||||
log::trace!("shaper wants {} {:?}", font_idx, handle);
|
||||
let face = self.lib.face_from_locator(&handle.handle)?;
|
||||
let mut font = harfbuzz::Font::new(face.face);
|
||||
let (load_flags, _) = ftwrap::compute_load_flags_from_config(
|
||||
handle.freetype_load_flags,
|
||||
handle.freetype_load_target,
|
||||
handle.freetype_render_target,
|
||||
);
|
||||
font.set_load_flags(load_flags);
|
||||
|
||||
let font = if USE_OT_FACE {
|
||||
harfbuzz::Font::from_locator(&handle.handle)?
|
||||
} else {
|
||||
let (load_flags, _) = ftwrap::compute_load_flags_from_config(
|
||||
handle.freetype_load_flags,
|
||||
handle.freetype_load_target,
|
||||
handle.freetype_render_target,
|
||||
);
|
||||
let mut font = harfbuzz::Font::new(face.face);
|
||||
font.set_load_flags(load_flags);
|
||||
font
|
||||
};
|
||||
|
||||
let features = match &handle.harfbuzz_features {
|
||||
Some(features) => features
|
||||
@ -220,22 +236,33 @@ impl HarfbuzzShaper {
|
||||
}
|
||||
}
|
||||
}
|
||||
pair.face.set_font_size(
|
||||
font_size * self.handles[font_idx].scale.unwrap_or(1.),
|
||||
dpi,
|
||||
)?;
|
||||
let point_size = font_size * self.handles[font_idx].scale.unwrap_or(1.);
|
||||
pair.face.set_font_size(point_size, dpi)?;
|
||||
|
||||
// Tell harfbuzz to recompute important font metrics!
|
||||
let mut font = pair.font.borrow_mut();
|
||||
|
||||
if USE_OT_FACE {
|
||||
font.set_ppem(0, 0);
|
||||
font.set_ptem(0.);
|
||||
let scale = (point_size * 2f64.powf(6.)) as i32;
|
||||
font.set_font_scale(scale, scale);
|
||||
}
|
||||
|
||||
font.font_changed();
|
||||
|
||||
if USE_OT_FUNCS {
|
||||
font.set_ot_funcs();
|
||||
}
|
||||
|
||||
shaped_any = pair.shaped_any;
|
||||
font.shape(&mut buf, pair.features.as_slice());
|
||||
/*
|
||||
log::info!(
|
||||
"shaped font_idx={} as: {}",
|
||||
log::trace!(
|
||||
"shaped font_idx={} {:?} as: {}",
|
||||
font_idx,
|
||||
buf.serialize(Some(&pair.font))
|
||||
&s[range.start..range.end],
|
||||
buf.serialize(Some(&*font))
|
||||
);
|
||||
*/
|
||||
break;
|
||||
}
|
||||
None => {
|
||||
|
Loading…
Reference in New Issue
Block a user