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:
parent
21ab0887db
commit
990d12fdf4
@ -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,
|
||||||
|
@ -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 {
|
||||||
|
Loading…
Reference in New Issue
Block a user