Skip to content

Commit

Permalink
Reduce memory usage and loading time of FontSystem
Browse files Browse the repository at this point in the history
  • Loading branch information
HoldMyBeer authored and jackpot51 committed Jan 10, 2025
1 parent acb4235 commit 166b59f
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 62 deletions.
2 changes: 0 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ ttf-parser = { version = "0.21", default-features = false }
unicode-linebreak = "0.1.5"
unicode-script = "0.5.5"
unicode-segmentation = "1.10.1"
rayon = { version = "1", optional = true }

[dependencies.swash]
version = "0.2.0"
Expand All @@ -55,7 +54,6 @@ std = [
"sys-locale",
"ttf-parser/std",
"unicode-bidi/std",
"rayon"
]
vi = ["modit", "syntect", "cosmic_undo_2"]
wasm-web = ["sys-locale?/js"]
Expand Down
90 changes: 30 additions & 60 deletions src/font/system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -164,33 +164,47 @@ impl FontSystem {
.collect::<Vec<_>>();
monospace_font_ids.sort();

let cloned_monospace_font_ids = monospace_font_ids.clone();
let mut per_script_monospace_font_ids: HashMap<[u8; 4], BTreeSet<fontdb::ID>> =
HashMap::default();

if cfg!(feature = "monospace_fallback") {
monospace_font_ids.iter().for_each(|&id| {
db.with_face_data(id, |font_data, face_index| {
let _ = ttf_parser::Face::parse(font_data, face_index).map(|face| {
face.tables()
.gpos
.into_iter()
.chain(face.tables().gsub)
.flat_map(|table| table.scripts)
.inspect(|script| {
per_script_monospace_font_ids
.entry(script.tag.to_bytes())
.or_default()
.insert(id);
})
});
});
});
}

let per_script_monospace_font_ids = per_script_monospace_font_ids
.into_iter()
.map(|(k, v)| (k, Vec::from_iter(v)))
.collect();

let mut ret = Self {
Self {
locale,
db,
monospace_font_ids,
per_script_monospace_font_ids: Default::default(),
per_script_monospace_font_ids,
font_cache: Default::default(),
font_matches_cache: Default::default(),
font_codepoint_support_info_cache: Default::default(),
monospace_fallbacks_buffer: BTreeSet::default(),
#[cfg(feature = "shape-run-cache")]
shape_run_cache: crate::ShapeRunCache::default(),
shape_buffer: ShapeBuffer::default(),
};
ret.cache_fonts(cloned_monospace_font_ids.clone());
cloned_monospace_font_ids.into_iter().for_each(|id| {
if let Some(font) = ret.get_font(id) {
font.scripts().iter().copied().for_each(|script| {
ret.per_script_monospace_font_ids
.entry(script)
.or_default()
.push(font.id);
});
}
});
ret
}
}

/// Get the locale.
Expand All @@ -214,50 +228,6 @@ impl FontSystem {
(self.locale, self.db)
}

/// Concurrently cache fonts by id list
pub fn cache_fonts(&mut self, mut ids: Vec<fontdb::ID>) {
#[cfg(feature = "std")]
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
#[cfg(feature = "std")]
{
ids = ids
.into_iter()
.filter(|id| {
let contains = self.font_cache.contains_key(id);
if !contains {
unsafe {
self.db.make_shared_face_data(*id);
}
}
!contains
})
.collect::<_>();
}

#[cfg(feature = "std")]
let fonts = ids.par_iter();
#[cfg(not(feature = "std"))]
let fonts = ids.iter();

fonts
.map(|id| match Font::new(&self.db, *id) {
Some(font) => Some(Arc::new(font)),
None => {
log::warn!(
"failed to load font '{}'",
self.db.face(*id)?.post_script_name
);
None
}
})
.collect::<Vec<Option<Arc<Font>>>>()
.into_iter()
.flatten()
.for_each(|font| {
self.font_cache.insert(font.id, Some(font));
});
}

/// Get a font by its ID.
pub fn get_font(&mut self, id: fontdb::ID) -> Option<Arc<Font>> {
self.font_cache
Expand Down

0 comments on commit 166b59f

Please sign in to comment.