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
/// collection if the data represents a collection of
/// fonts.
#[derive(Clone)]
pub enum FontDataHandle {
OnDisk {
path: PathBuf,

View File

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