mirror of
https://github.com/wez/wezterm.git
synced 2024-11-10 06:34:17 +03:00
wezterm-font: tidy up some font hinting/aa options
This commit more cleanly separates the load from the render flags, and fixes up the render call; at some point this got messed up such that we'd never end up with freetype returning subpixel format data (LCD) and instead we'd only ever get grayscale data. With that fixed, it's apparent that the colorization of the glyph data was wonky in the shader so this commit also cleans this up. refs: #320 refs: #121
This commit is contained in:
parent
bc1e12e0f5
commit
9892b16d40
8
deps/freetype/build.rs
vendored
8
deps/freetype/build.rs
vendored
@ -155,6 +155,14 @@ fn freetype() {
|
||||
.replace(
|
||||
"/* #define FT_CONFIG_OPTION_USE_PNG */",
|
||||
"#define FT_CONFIG_OPTION_USE_PNG",
|
||||
)
|
||||
.replace(
|
||||
"#define TT_CONFIG_OPTION_SUBPIXEL_HINTING 2",
|
||||
"#define TT_CONFIG_OPTION_SUBPIXEL_HINTING 3",
|
||||
)
|
||||
.replace(
|
||||
"/* #define FT_CONFIG_OPTION_SUBPIXEL_RENDERING */",
|
||||
"#define FT_CONFIG_OPTION_SUBPIXEL_RENDERING",
|
||||
),
|
||||
)
|
||||
.unwrap();
|
||||
|
@ -28,29 +28,28 @@ fn render_mode_to_load_target(render_mode: FT_Render_Mode) -> u32 {
|
||||
(render_mode as u32) & 15 << 16
|
||||
}
|
||||
|
||||
pub fn compute_load_flags_from_config() -> i32 {
|
||||
pub fn compute_load_flags_from_config() -> (i32, FT_Render_Mode) {
|
||||
let config = configuration();
|
||||
let flags = match (config.font_hinting, config.font_antialias) {
|
||||
(FontHinting::VerticalSubpixel, _) | (_, FontAntiAliasing::Subpixel) => {
|
||||
render_mode_to_load_target(FT_Render_Mode::FT_RENDER_MODE_LCD)
|
||||
}
|
||||
(FontHinting::None, _) => {
|
||||
|
||||
let render = match config.font_antialias {
|
||||
FontAntiAliasing::None => FT_Render_Mode::FT_RENDER_MODE_MONO,
|
||||
FontAntiAliasing::Greyscale => FT_Render_Mode::FT_RENDER_MODE_NORMAL,
|
||||
FontAntiAliasing::Subpixel => FT_Render_Mode::FT_RENDER_MODE_LCD,
|
||||
};
|
||||
|
||||
let flags = match config.font_hinting {
|
||||
FontHinting::None => {
|
||||
render_mode_to_load_target(FT_Render_Mode::FT_RENDER_MODE_NORMAL) | FT_LOAD_NO_HINTING
|
||||
}
|
||||
(FontHinting::Vertical, FontAntiAliasing::None)
|
||||
| (FontHinting::Full, FontAntiAliasing::None) => {
|
||||
render_mode_to_load_target(FT_Render_Mode::FT_RENDER_MODE_MONO)
|
||||
FontHinting::Vertical => render_mode_to_load_target(FT_Render_Mode::FT_RENDER_MODE_LIGHT),
|
||||
FontHinting::VerticalSubpixel | FontHinting::Full => {
|
||||
render_mode_to_load_target(FT_Render_Mode::FT_RENDER_MODE_LCD)
|
||||
}
|
||||
(FontHinting::Vertical, _) => {
|
||||
render_mode_to_load_target(FT_Render_Mode::FT_RENDER_MODE_LIGHT)
|
||||
}
|
||||
(FontHinting::Full, _) => render_mode_to_load_target(FT_Render_Mode::FT_RENDER_MODE_NORMAL),
|
||||
};
|
||||
|
||||
// If the bitmaps are in color, we want those!
|
||||
let flags = flags | FT_LOAD_COLOR;
|
||||
|
||||
#[allow(clippy::let_and_return)]
|
||||
let flags = if config.font_antialias == FontAntiAliasing::None {
|
||||
// When AA is disabled, force outline rendering to monochrome
|
||||
flags | FT_LOAD_MONOCHROME
|
||||
@ -58,7 +57,7 @@ pub fn compute_load_flags_from_config() -> i32 {
|
||||
flags
|
||||
} as i32;
|
||||
|
||||
flags
|
||||
(flags, render)
|
||||
}
|
||||
|
||||
pub struct Face {
|
||||
@ -149,14 +148,12 @@ impl Face {
|
||||
&mut self,
|
||||
glyph_index: FT_UInt,
|
||||
load_flags: FT_Int32,
|
||||
render_mode: FT_Render_Mode,
|
||||
) -> anyhow::Result<&FT_GlyphSlotRec_> {
|
||||
unsafe {
|
||||
let res = FT_Load_Glyph(
|
||||
self.face,
|
||||
glyph_index,
|
||||
(FT_LOAD_DEFAULT | FT_LOAD_RENDER) as i32 | load_flags,
|
||||
);
|
||||
ft_result(res, &*(*self.face).glyph)
|
||||
let res = FT_Load_Glyph(self.face, glyph_index, load_flags);
|
||||
let slot = ft_result(res, &mut *(*self.face).glyph)?;
|
||||
ft_result(FT_Render_Glyph(slot, render_mode), slot)
|
||||
}
|
||||
}
|
||||
|
||||
@ -204,6 +201,16 @@ impl Library {
|
||||
let lib = ft_result(res, lib).context("FT_Init_FreeType")?;
|
||||
let mut lib = Library { lib };
|
||||
|
||||
let interpreter_version: FT_UInt = 38;
|
||||
unsafe {
|
||||
FT_Property_Set(
|
||||
lib.lib,
|
||||
b"truetype\0" as *const u8 as *const FT_String,
|
||||
b"interpreter-version\0" as *const u8 as *const FT_String,
|
||||
&interpreter_version as *const FT_UInt as *const _,
|
||||
);
|
||||
}
|
||||
|
||||
// Due to patent concerns, the freetype library disables the LCD
|
||||
// filtering feature by default, and since we always build our
|
||||
// own copy of freetype, it is likewise disabled by default for
|
||||
|
@ -23,11 +23,11 @@ impl FontRasterizer for FreeTypeRasterizer {
|
||||
) -> anyhow::Result<RasterizedGlyph> {
|
||||
self.face.borrow_mut().set_font_size(size, dpi)?;
|
||||
|
||||
let load_flags = ftwrap::compute_load_flags_from_config();
|
||||
let (load_flags, render_mode) = ftwrap::compute_load_flags_from_config();
|
||||
|
||||
let mut face = self.face.borrow_mut();
|
||||
let descender = unsafe { (*(*face.face).size).metrics.descender as f64 / 64.0 };
|
||||
let ft_glyph = face.load_and_render_glyph(glyph_pos, load_flags)?;
|
||||
let ft_glyph = face.load_and_render_glyph(glyph_pos, load_flags, render_mode)?;
|
||||
|
||||
let mode: ftwrap::FT_Pixel_Mode =
|
||||
unsafe { mem::transmute(u32::from(ft_glyph.bitmap.pixel_mode)) };
|
||||
@ -144,9 +144,12 @@ impl FreeTypeRasterizer {
|
||||
let src_offset = y * pitch as usize;
|
||||
let dest_offset = y * width * 4;
|
||||
for x in 0..width {
|
||||
let blue = data[src_offset + (x * 3)];
|
||||
// Note: it is unclear whether the LCD data format
|
||||
// is BGR or RGB. I'm using RGB here because the
|
||||
// antialiasing in other apps seems to do this.
|
||||
let red = data[src_offset + (x * 3)];
|
||||
let green = data[src_offset + (x * 3) + 1];
|
||||
let red = data[src_offset + (x * 3) + 2];
|
||||
let blue = data[src_offset + (x * 3) + 2];
|
||||
let alpha = red | green | blue;
|
||||
rgba[dest_offset + (x * 4)] = red;
|
||||
rgba[dest_offset + (x * 4) + 1] = green;
|
||||
|
@ -105,7 +105,7 @@ impl HarfbuzzShaper {
|
||||
log::trace!("shaper wants {} {:?}", font_idx, &self.handles[font_idx]);
|
||||
let face = self.lib.face_from_locator(&self.handles[font_idx])?;
|
||||
let mut font = harfbuzz::Font::new(face.face);
|
||||
let load_flags = ftwrap::compute_load_flags_from_config();
|
||||
let (load_flags, _) = ftwrap::compute_load_flags_from_config();
|
||||
font.set_load_flags(load_flags);
|
||||
*opt_pair = Some(FontPair {
|
||||
face,
|
||||
|
@ -110,12 +110,11 @@ void main() {
|
||||
// the window_bg_layer.
|
||||
discard;
|
||||
} else {
|
||||
color = texture(atlas_nearest_sampler, o_tex);
|
||||
if (o_has_color == 0.0) {
|
||||
// if it's not a color emoji, tint with the fg_color
|
||||
color = texture(atlas_nearest_sampler, o_tex);
|
||||
color.rgb = o_fg_color.rgb;
|
||||
} else {
|
||||
color = texture(atlas_linear_sampler, o_tex);
|
||||
// if it's not a color emoji it will be grayscale
|
||||
// and we need to tint with the fg_color
|
||||
color.rgb *= o_fg_color.rgb;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user