1
1
mirror of https://github.com/wez/wezterm.git synced 2024-11-24 07:46:59 +03:00

fonts: start adding new stuff to FontConfiguration

This commit is contained in:
Wez Furlong 2019-12-09 12:12:54 -08:00
parent accfc9b09c
commit cd07a31d84
6 changed files with 130 additions and 17 deletions

View File

@ -78,13 +78,7 @@ impl Font for FreeTypeFontImpl {
// when changing the load flags, we also need
// to change them for harfbuzz otherwise it won't
// hint correctly
let load_flags = (ftwrap::FT_LOAD_COLOR) as i32 |
// enable FT_LOAD_TARGET bits. There are no flags defined
// for these in the bindings so we do some bit magic for
// ourselves. This is how the FT_LOAD_TARGET_() macro
// assembles these bits.
(render_mode as i32) << 16;
let load_flags = ftwrap::compute_load_flags_for_mode(render_mode);
self.font.borrow_mut().set_load_flags(load_flags);
// This clone is conceptually unsafe, but ok in practice as we are

View File

@ -1,5 +1,6 @@
//! Higher level freetype bindings
use crate::font::loader::FontDataHandle;
use failure::{bail, format_err, Error, Fallible, ResultExt};
pub use freetype::*;
use std::ffi::CString;
@ -19,6 +20,15 @@ fn ft_result<T>(err: FT_Error, t: T) -> Result<T, Error> {
}
}
pub fn compute_load_flags_for_mode(render_mode: FT_Render_Mode) -> i32 {
FT_LOAD_COLOR as i32 |
// enable FT_LOAD_TARGET bits. There are no flags defined
// for these in the bindings so we do some bit magic for
// ourselves. This is how the FT_LOAD_TARGET_() macro
// assembles these bits.
(render_mode as i32) << 16
}
pub struct Face {
pub face: FT_Face,
_bytes: Vec<u8>,
@ -172,6 +182,15 @@ impl Library {
Ok(Library { lib })
}
pub fn face_from_locator(&self, handle: &FontDataHandle) -> Fallible<Face> {
match handle {
FontDataHandle::OnDisk { path, index } => {
self.new_face(path.to_str().unwrap(), *index as _)
}
FontDataHandle::Memory { data, index } => self.new_face_from_slice(&data, *index as _),
}
}
#[cfg(any(target_os = "macos", windows))]
pub fn load_font_kit_handle(&self, handle: &font_kit::handle::Handle) -> Result<Face, Error> {
use font_kit::handle::Handle;

View File

@ -1,6 +1,8 @@
use crate::config::FontAttributes;
use failure::Fallible;
use failure::{format_err, Error, Fallible};
use serde_derive::*;
use std::path::PathBuf;
use std::sync::Mutex;
#[cfg(all(unix, any(feature = "fontconfig", not(target_os = "macos"))))]
pub mod font_config;
@ -25,3 +27,79 @@ pub trait FontLocator {
/// FontDataHandle's that correspond to it
fn load_fonts(&self, fonts_selection: &[FontAttributes]) -> Fallible<Vec<FontDataHandle>>;
}
#[derive(Debug, Deserialize, Clone, Copy)]
pub enum FontLocatorSelection {
FontConfig,
FontLoader,
FontKit,
}
lazy_static::lazy_static! {
static ref DEFAULT_LOCATOR: Mutex<FontLocatorSelection> = Mutex::new(Default::default());
}
impl Default for FontLocatorSelection {
fn default() -> Self {
if cfg!(all(unix, not(target_os = "macos"))) {
FontLocatorSelection::FontConfig
} else {
FontLocatorSelection::FontLoader
}
}
}
impl FontLocatorSelection {
pub fn set_default(self) {
let mut def = DEFAULT_LOCATOR.lock().unwrap();
*def = self;
}
pub fn get_default() -> Self {
let def = DEFAULT_LOCATOR.lock().unwrap();
*def
}
pub fn variants() -> Vec<&'static str> {
vec!["FontConfig", "FontLoader", "FontKit"]
}
pub fn new_locator(self) -> Box<dyn FontLocator> {
match self {
Self::FontConfig => {
#[cfg(all(unix, any(feature = "fontconfig", not(target_os = "macos"))))]
return Box::new(font_config::FontConfigFontLocator {});
#[cfg(not(all(unix, any(feature = "fontconfig", not(target_os = "macos")))))]
panic!("fontconfig not compiled in");
}
Self::FontLoader => {
#[cfg(any(target_os = "macos", windows))]
return Box::new(font_loader::FontLoaderFontLocator {});
#[cfg(not(any(target_os = "macos", windows)))]
panic!("fontloader not compiled in");
}
Self::FontKit => {
#[cfg(any(target_os = "macos", windows))]
return Box::new(::font_kit::source::SystemSource::new());
#[cfg(not(any(target_os = "macos", windows)))]
panic!("fontkit not compiled in");
}
}
}
}
impl std::str::FromStr for FontLocatorSelection {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_lowercase().as_ref() {
"fontconfig" => Ok(Self::FontConfig),
"fontloader" => Ok(Self::FontLoader),
"fontkit" => Ok(Self::FontKit),
_ => Err(format_err!(
"{} is not a valid FontLocatorSelection variant, possible values are {:?}",
s,
Self::variants()
)),
}
}
}

View File

@ -34,19 +34,28 @@ pub mod fontloader_and_freetype;
#[cfg(any(target_os = "macos", windows))]
pub mod fontkit;
use crate::font::loader::{FontLocator, FontLocatorSelection};
use super::config::{configuration, ConfigHandle, TextStyle};
use term::CellAttributes;
pub struct LoadedFont {
rasterizer: Box<dyn rasterizer::FontRasterizer>,
shaper: Box<dyn shaper::FontShaper>,
}
type FontPtr = Rc<RefCell<Box<dyn NamedFont>>>;
/// Matches and loads fonts for a given input style
pub struct FontConfiguration {
fonts: RefCell<HashMap<TextStyle, FontPtr>>,
new_fonts: RefCell<HashMap<TextStyle, Rc<LoadedFont>>>,
system: Rc<dyn FontSystem>,
metrics: RefCell<Option<FontMetrics>>,
dpi_scale: RefCell<f64>,
font_scale: RefCell<f64>,
config_generation: RefCell<usize>,
loader: Box<dyn FontLocator>,
}
#[derive(Debug, Deserialize, Clone, Copy)]
@ -111,6 +120,7 @@ impl FontSystemSelection {
}
}
}
pub fn variants() -> Vec<&'static str> {
vec![
"FontConfigAndFreeType",
@ -153,8 +163,11 @@ impl std::str::FromStr for FontSystemSelection {
impl FontConfiguration {
/// Create a new empty configuration
pub fn new(system: FontSystemSelection) -> Self {
let loader = FontLocatorSelection::get_default().new_locator();
Self {
fonts: RefCell::new(HashMap::new()),
loader,
new_fonts: RefCell::new(HashMap::new()),
system: system.new_font_system(),
metrics: RefCell::new(None),
font_scale: RefCell::new(1.0),

View File

@ -19,12 +19,7 @@ impl FontRasterizer for FreeTypeRasterizer {
// ftwrap::FT_Render_Mode::FT_RENDER_MODE_LCD;
ftwrap::FT_Render_Mode::FT_RENDER_MODE_LIGHT;
let load_flags = (ftwrap::FT_LOAD_COLOR) as i32 |
// enable FT_LOAD_TARGET bits. There are no flags defined
// for these in the bindings so we do some bit magic for
// ourselves. This is how the FT_LOAD_TARGET_() macro
// assembles these bits.
(render_mode as i32) << 16;
let load_flags = ftwrap::compute_load_flags_for_mode(render_mode);
let mut face = self.face.borrow_mut();
let descender = unsafe { (*(*face.face).size).metrics.descender as f64 / 64.0 };
@ -268,9 +263,7 @@ impl FreeTypeRasterizer {
}
}
pub fn with_face_size_and_dpi(mut face: ftwrap::Face, size: f64, dpi: u32) -> Fallible<Self> {
face.set_font_size(size, dpi)?;
pub fn with_face(face: ftwrap::Face) -> Fallible<Self> {
let has_color = unsafe {
(((*face.face).face_flags as u32) & (ftwrap::FT_FACE_FLAG_COLOR as u32)) != 0
};

View File

@ -1,5 +1,6 @@
use crate::font::ftwrap;
use crate::font::hbwrap as harfbuzz;
use crate::font::loader::FontDataHandle;
use crate::font::shaper::FontShaper;
use crate::font::system::GlyphInfo;
use failure::{bail, Fallible};
@ -13,9 +14,24 @@ struct FontPair {
pub struct HarfbuzzShaper {
fonts: Vec<RefCell<FontPair>>,
lib: ftwrap::Library,
}
impl HarfbuzzShaper {
pub fn new(handles: &[FontDataHandle]) -> Fallible<Self> {
let lib = ftwrap::Library::new()?;
let mut fonts = vec![];
for handle in handles {
let face = lib.face_from_locator(handle)?;
let mut font = harfbuzz::Font::new(face.face);
let render_mode = ftwrap::FT_Render_Mode::FT_RENDER_MODE_LIGHT;
let load_flags = ftwrap::compute_load_flags_for_mode(render_mode);
font.set_load_flags(load_flags);
fonts.push(RefCell::new(FontPair { face, font }));
}
Ok(Self { fonts, lib })
}
fn do_shape(
&self,
font_idx: crate::font::system::FallbackIdx,