From 166b59f560c551dab391a864f7c1f503c1e18446 Mon Sep 17 00:00:00 2001 From: HoldMyBeer Date: Fri, 10 Jan 2025 17:15:53 +0300 Subject: [PATCH] Reduce memory usage and loading time of FontSystem --- Cargo.toml | 2 -- src/font/system.rs | 90 ++++++++++++++++------------------------------ 2 files changed, 30 insertions(+), 62 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b67db53..7dcfea8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -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" @@ -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"] diff --git a/src/font/system.rs b/src/font/system.rs index 880eb28..c4d5662 100644 --- a/src/font/system.rs +++ b/src/font/system.rs @@ -164,13 +164,39 @@ impl FontSystem { .collect::>(); monospace_font_ids.sort(); - let cloned_monospace_font_ids = monospace_font_ids.clone(); + let mut per_script_monospace_font_ids: HashMap<[u8; 4], BTreeSet> = + HashMap::default(); - let mut ret = Self { + 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(); + + 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(), @@ -178,19 +204,7 @@ impl FontSystem { #[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. @@ -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) { - #[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::>>>() - .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> { self.font_cache