1
1
mirror of https://github.com/wez/wezterm.git synced 2024-09-19 02:37:51 +03:00

introduce freetype_load_flags and freetype_load_target config

In the earlier times wezterm supported different font rasterizers,
and the configuration was a bit vague and generic to accomodate
differences in how the rasterizers worked.

Since then, we've standardized on freetype.

One of the things that's been bothering me for a while is that
we have some fiddly logic to transform from the config to the freetype
flags.

This commit does away with the transformation and simply exposes
the two sets of freetype options.

The main thing that I expect people to play with is
`freetype_load_target` which can have one of the following values:

```
pub enum FreeTypeLoadTarget {
    /// This corresponds to the default hinting algorithm, optimized
    for standard gray-level rendering.
    Normal,
    /// A lighter hinting algorithm for non-monochrome modes. Many
    generated glyphs are more fuzzy but better resemble its original
    shape. A bit like rendering on Mac OS X.  This target implies
    FT_LOAD_FORCE_AUTOHINT.
    Light,
    /// Strong hinting algorithm that should only be used for
    monochrome output. The result is probably unpleasant if the glyph
    is rendered in non-monochrome modes.
    Mono,
    /// A variant of Normal optimized for horizontally decimated LCD displays.
    HorizontalLcd,
    /// A variant of Normal optimized for vertically decimated LCD displays.
    VerticalLcd,
}
```

I expect most people will want to set this to one of `Normal`, `Light`
or `HorizontalLcd`.  `HorizontalLcd` is what `font_antialias=Subpixel`
used to select.

refs: #491
This commit is contained in:
Wez Furlong 2021-02-20 13:54:56 -08:00
parent 528a4846c7
commit dd70a8a53b
5 changed files with 98 additions and 25 deletions

1
Cargo.lock generated
View File

@ -672,6 +672,7 @@ name = "config"
version = "0.1.0"
dependencies = [
"anyhow",
"bitflags",
"bstr 0.2.15",
"dirs-next",
"filenamegen",

View File

@ -15,6 +15,7 @@ pretty_env_logger = "0.4"
[dependencies]
anyhow = "1.0"
bitflags = "1.0"
bstr = "0.2"
dirs-next = "2.0"
filenamegen = "0.2"

View File

@ -1,7 +1,88 @@
use crate::*;
use bitflags::*;
use luahelper::impl_lua_conversion;
use serde::{Deserialize, Deserializer, Serialize};
use termwiz::color::RgbColor;
#[derive(Debug, Deserialize, Serialize, Clone, Copy, PartialEq, Eq, Hash)]
pub enum FreeTypeLoadTarget {
/// This corresponds to the default hinting algorithm, optimized
/// for standard gray-level rendering.
Normal,
/// A lighter hinting algorithm for non-monochrome modes. Many
/// generated glyphs are more fuzzy but better resemble its
/// original shape. A bit like rendering on Mac OS X. This target
/// implies FT_LOAD_FORCE_AUTOHINT.
Light,
/// Strong hinting algorithm that should only be used for
/// monochrome output. The result is probably unpleasant if the
/// glyph is rendered in non-monochrome modes.
Mono,
/// A variant of Normal optimized for horizontally decimated LCD displays.
HorizontalLcd,
/// A variant of Normal optimized for vertically decimated LCD displays.
VerticalLcd,
}
impl Default for FreeTypeLoadTarget {
fn default() -> Self {
Self::Normal
}
}
bitflags! {
// Note that these are strongly coupled with deps/freetype/src/lib.rs,
// but we can't directly reference that from here without making config
// depend on freetype.
#[derive(Default, Deserialize, Serialize)]
pub struct FreeTypeLoadFlags: u32 {
/// FT_LOAD_DEFAULT
const DEFAULT = 0;
/// Disable hinting. This generally generates blurrier
/// bitmap glyph when the glyph is rendered in any of the
/// anti-aliased modes. See also the note below. This flag is
/// implied by FT_LOAD_NO_SCALE.
const NO_HINTING = 2;
const NO_BITMAP = 8;
/// Indicates that the auto-hinter is preferred over the
/// fonts native hinter.
const FORCE_AUTOHINT = 32;
const MONOCHROME = 4096;
/// Disable auto-hinter.
const NO_AUTOHINT = 32768;
}
}
impl FreeTypeLoadFlags {
pub fn de_string<'de, D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
let mut flags = FreeTypeLoadFlags::default();
for ele in s.split('|') {
let ele = ele.trim();
match ele {
"DEFAULT" => flags |= Self::DEFAULT,
"NO_HINTING" => flags |= Self::NO_HINTING,
"NO_BITMAP" => flags |= Self::NO_BITMAP,
"FORCE_AUTOHINT" => flags |= Self::FORCE_AUTOHINT,
"MONOCHROME" => flags |= Self::MONOCHROME,
"NO_AUTOHINT" => flags |= Self::NO_AUTOHINT,
_ => {
return Err(serde::de::Error::custom(format!(
"invalid FreeTypeLoadFlags {} in {}",
ele, s
)));
}
}
}
Ok(flags)
}
}
#[derive(Debug, Copy, Deserialize, Serialize, Clone, PartialEq, Eq, Hash)]
pub enum FontHinting {
/// No hinting is performed

View File

@ -571,6 +571,11 @@ pub struct Config {
#[serde(default)]
pub font_antialias: FontAntiAliasing,
#[serde(default)]
pub freetype_load_target: FreeTypeLoadTarget,
#[serde(default, deserialize_with = "FreeTypeLoadFlags::de_string")]
pub freetype_load_flags: FreeTypeLoadFlags,
/// Selects the freetype interpret version to use.
/// Likely values are 35, 38 and 40 which have different
/// characteristics with respective to subpixel hinting.

View File

@ -2,7 +2,7 @@
use crate::locator::FontDataHandle;
use anyhow::{anyhow, Context};
use config::{configuration, FontAntiAliasing, FontHinting};
use config::{configuration, FreeTypeLoadTarget};
pub use freetype::*;
use std::ptr;
@ -44,33 +44,18 @@ fn render_mode_to_load_target(render_mode: FT_Render_Mode) -> u32 {
pub fn compute_load_flags_from_config() -> (i32, FT_Render_Mode) {
let config = configuration();
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 load_flags = config.freetype_load_flags.bits() | FT_LOAD_COLOR;
let render = match config.freetype_load_target {
FreeTypeLoadTarget::Mono => FT_Render_Mode::FT_RENDER_MODE_MONO,
FreeTypeLoadTarget::Normal => FT_Render_Mode::FT_RENDER_MODE_NORMAL,
FreeTypeLoadTarget::Light => FT_Render_Mode::FT_RENDER_MODE_LIGHT,
FreeTypeLoadTarget::HorizontalLcd => FT_Render_Mode::FT_RENDER_MODE_LCD,
FreeTypeLoadTarget::VerticalLcd => FT_Render_Mode::FT_RENDER_MODE_LCD_V,
};
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 => 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)
}
};
let load_flags = load_flags | render_mode_to_load_target(render);
// If the bitmaps are in color, we want those!
let flags = flags | FT_LOAD_COLOR;
let flags = if config.font_antialias == FontAntiAliasing::None {
// When AA is disabled, force outline rendering to monochrome
flags | FT_LOAD_MONOCHROME
} else {
flags
} as i32;
(flags, render)
(load_flags as i32, render)
}
pub struct Face {