1
1
mirror of https://github.com/wez/wezterm.git synced 2024-11-23 23:21:08 +03:00

fonts: defer loading and setting font size

There's a lot of overhead for doing the size setting on each shaper
call!
This commit is contained in:
Wez Furlong 2019-12-14 14:00:15 -08:00
parent 21ab0887db
commit 990d12fdf4
2 changed files with 55 additions and 17 deletions

View File

@ -17,6 +17,7 @@ pub mod font_loader;
/// The `index` parameter is the index into a font /// The `index` parameter is the index into a font
/// collection if the data represents a collection of /// collection if the data represents a collection of
/// fonts. /// fonts.
#[derive(Clone)]
pub enum FontDataHandle { pub enum FontDataHandle {
OnDisk { OnDisk {
path: PathBuf, path: PathBuf,

View File

@ -3,9 +3,9 @@ use crate::font::hbwrap as harfbuzz;
use crate::font::locator::FontDataHandle; use crate::font::locator::FontDataHandle;
use crate::font::shaper::{FallbackIdx, FontMetrics, FontShaper, GlyphInfo}; use crate::font::shaper::{FallbackIdx, FontMetrics, FontShaper, GlyphInfo};
use crate::font::units::*; use crate::font::units::*;
use failure::{bail, Fallible}; use failure::{bail, format_err, Fallible};
use log::{debug, error}; use log::{debug, error};
use std::cell::RefCell; use std::cell::{RefCell, RefMut};
fn make_glyphinfo( fn make_glyphinfo(
text: &str, text: &str,
@ -32,26 +32,58 @@ fn make_glyphinfo(
struct FontPair { struct FontPair {
face: ftwrap::Face, face: ftwrap::Face,
font: harfbuzz::Font, font: harfbuzz::Font,
size: f64,
dpi: u32,
} }
pub struct HarfbuzzShaper { pub struct HarfbuzzShaper {
fonts: Vec<RefCell<FontPair>>, handles: Vec<FontDataHandle>,
_lib: ftwrap::Library, fonts: Vec<RefCell<Option<FontPair>>>,
lib: ftwrap::Library,
} }
impl HarfbuzzShaper { impl HarfbuzzShaper {
pub fn new(handles: &[FontDataHandle]) -> Fallible<Self> { pub fn new(handles: &[FontDataHandle]) -> Fallible<Self> {
let lib = ftwrap::Library::new()?; let lib = ftwrap::Library::new()?;
let handles = handles.to_vec();
let mut fonts = vec![]; let mut fonts = vec![];
for handle in handles { for _ in 0..handles.len() {
let face = lib.face_from_locator(handle)?; fonts.push(RefCell::new(None));
let mut font = harfbuzz::Font::new(face.face); }
let render_mode = ftwrap::FT_Render_Mode::FT_RENDER_MODE_LIGHT; Ok(Self {
let load_flags = ftwrap::compute_load_flags_for_mode(render_mode); fonts,
font.set_load_flags(load_flags); handles,
fonts.push(RefCell::new(FontPair { face, font })); lib,
})
}
fn load_fallback(&self, font_idx: FallbackIdx) -> Fallible<Option<RefMut<FontPair>>> {
if font_idx >= self.handles.len() {
return Ok(None);
}
match self.fonts.get(font_idx) {
None => Ok(None),
Some(opt_pair) => {
let mut opt_pair = opt_pair.borrow_mut();
if opt_pair.is_none() {
let face = self.lib.face_from_locator(&self.handles[font_idx])?;
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);
*opt_pair = Some(FontPair {
face,
font,
size: 0.,
dpi: 0,
});
}
Ok(Some(RefMut::map(opt_pair, |opt_pair| {
opt_pair.as_mut().unwrap()
})))
}
} }
Ok(Self { fonts, _lib: lib })
} }
fn do_shape( fn do_shape(
@ -77,10 +109,13 @@ impl HarfbuzzShaper {
buf.add_str(s); buf.add_str(s);
{ {
match self.fonts.get(font_idx) { match self.load_fallback(font_idx)? {
Some(pair) => { Some(mut pair) => {
let mut pair = pair.borrow_mut(); if pair.size != font_size || pair.dpi != dpi {
pair.face.set_font_size(font_size, dpi)?; pair.face.set_font_size(font_size, dpi)?;
pair.size = font_size;
pair.dpi = dpi;
}
pair.font.shape(&mut buf, Some(features.as_slice())); pair.font.shape(&mut buf, Some(features.as_slice()));
} }
None => { None => {
@ -220,7 +255,9 @@ impl FontShaper for HarfbuzzShaper {
} }
fn metrics(&self, size: f64, dpi: u32) -> Fallible<FontMetrics> { fn metrics(&self, size: f64, dpi: u32) -> Fallible<FontMetrics> {
let mut pair = self.fonts[0].borrow_mut(); let mut pair = self
.load_fallback(0)?
.ok_or_else(|| format_err!("unable to load first font!?"))?;
let (cell_width, cell_height) = pair.face.set_font_size(size, dpi)?; let (cell_width, cell_height) = pair.face.set_font_size(size, dpi)?;
let y_scale = unsafe { (*(*pair.face.face).size).metrics.y_scale as f64 / 65536.0 }; let y_scale = unsafe { (*(*pair.face.face).size).metrics.y_scale as f64 / 65536.0 };
let metrics = FontMetrics { let metrics = FontMetrics {