mirror of
https://github.com/wez/wezterm.git
synced 2024-12-25 22:33:52 +03:00
fonts: allow unloading unused fonts from the shaper
When we process the system fallback list, we can produce a long list of fonts to be speculatively processed by the shaper. Until this commit, the shaper would always keep the associated freetype face open forever, which increases the number of open files and the amount of allocated memory. This commit allows the shaper to release a font if it has never produced any valid shaper results, which keeps the list down to just the fonts that are in use.
This commit is contained in:
parent
3ce44823a0
commit
02e58d904d
@ -3,7 +3,7 @@ use crate::hbwrap as harfbuzz;
|
||||
use crate::parser::ParsedFont;
|
||||
use crate::shaper::{FallbackIdx, FontMetrics, FontShaper, GlyphInfo};
|
||||
use crate::units::*;
|
||||
use anyhow::anyhow;
|
||||
use anyhow::{anyhow, Context};
|
||||
use config::ConfigHandle;
|
||||
use log::error;
|
||||
use ordered_float::NotNan;
|
||||
@ -52,6 +52,7 @@ fn make_glyphinfo(text: &str, font_idx: usize, info: &Info) -> GlyphInfo {
|
||||
struct FontPair {
|
||||
face: ftwrap::Face,
|
||||
font: harfbuzz::Font,
|
||||
shaped_any: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Hash, PartialEq, Eq, Clone)]
|
||||
@ -133,7 +134,11 @@ impl HarfbuzzShaper {
|
||||
let mut font = harfbuzz::Font::new(face.face);
|
||||
let (load_flags, _) = ftwrap::compute_load_flags_from_config();
|
||||
font.set_load_flags(load_flags);
|
||||
*opt_pair = Some(FontPair { face, font });
|
||||
*opt_pair = Some(FontPair {
|
||||
face,
|
||||
font,
|
||||
shaped_any: false,
|
||||
});
|
||||
}
|
||||
|
||||
Ok(Some(RefMut::map(opt_pair, |opt_pair| {
|
||||
@ -168,13 +173,14 @@ impl HarfbuzzShaper {
|
||||
);
|
||||
|
||||
let cell_width;
|
||||
let shaped_any;
|
||||
|
||||
{
|
||||
match self.load_fallback(font_idx)? {
|
||||
#[allow(clippy::float_cmp)]
|
||||
match self.load_fallback(font_idx).context("load_fallback")? {
|
||||
Some(mut pair) => {
|
||||
let (width, _height) = pair.face.set_font_size(font_size, dpi)?;
|
||||
cell_width = width;
|
||||
shaped_any = pair.shaped_any;
|
||||
pair.font.shape(&mut buf, Some(features.as_slice()));
|
||||
}
|
||||
None => {
|
||||
@ -254,6 +260,8 @@ impl HarfbuzzShaper {
|
||||
}
|
||||
*/
|
||||
|
||||
let mut direct_clusters = 0;
|
||||
|
||||
for infos in &info_clusters {
|
||||
let cluster_len: usize = infos.iter().map(|info| info.len).sum();
|
||||
let cluster_start = infos.first().unwrap().cluster;
|
||||
@ -319,12 +327,32 @@ impl HarfbuzzShaper {
|
||||
if glyph.x_advance != PixelLength::new(0.0) {
|
||||
// log::error!("glyph: {:?}, nominal width: {:?}/{:?} = {:?}", glyph, glyph.x_advance, cell_width, nom_width);
|
||||
cluster.push(glyph);
|
||||
direct_clusters += 1;
|
||||
}
|
||||
|
||||
next_idx += len;
|
||||
}
|
||||
}
|
||||
|
||||
if !shaped_any {
|
||||
if let Some(opt_pair) = self.fonts.get(font_idx) {
|
||||
if direct_clusters == 0 {
|
||||
// If we've never shaped anything from this font, and we didn't
|
||||
// shape it just now, then we're probably a fallback font from
|
||||
// the system and unlikely to be useful to keep around, so we
|
||||
// unload it.
|
||||
log::trace!(
|
||||
"Shaper didn't resolve glyphs from {:?}, so unload it",
|
||||
self.handles[font_idx]
|
||||
);
|
||||
opt_pair.borrow_mut().take();
|
||||
} else if let Some(pair) = &mut *opt_pair.borrow_mut() {
|
||||
// We shaped something: mark this pair up so that it sticks around
|
||||
pair.shaped_any = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(cluster)
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user