Reduce memory usage and loading time of FontSystem
This commit is contained in:
parent
acb4235101
commit
166b59f560
2 changed files with 30 additions and 62 deletions
|
|
@ -28,7 +28,6 @@ ttf-parser = { version = "0.21", default-features = false }
|
||||||
unicode-linebreak = "0.1.5"
|
unicode-linebreak = "0.1.5"
|
||||||
unicode-script = "0.5.5"
|
unicode-script = "0.5.5"
|
||||||
unicode-segmentation = "1.10.1"
|
unicode-segmentation = "1.10.1"
|
||||||
rayon = { version = "1", optional = true }
|
|
||||||
|
|
||||||
[dependencies.swash]
|
[dependencies.swash]
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
|
|
@ -55,7 +54,6 @@ std = [
|
||||||
"sys-locale",
|
"sys-locale",
|
||||||
"ttf-parser/std",
|
"ttf-parser/std",
|
||||||
"unicode-bidi/std",
|
"unicode-bidi/std",
|
||||||
"rayon"
|
|
||||||
]
|
]
|
||||||
vi = ["modit", "syntect", "cosmic_undo_2"]
|
vi = ["modit", "syntect", "cosmic_undo_2"]
|
||||||
wasm-web = ["sys-locale?/js"]
|
wasm-web = ["sys-locale?/js"]
|
||||||
|
|
|
||||||
|
|
@ -164,13 +164,39 @@ impl FontSystem {
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
monospace_font_ids.sort();
|
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();
|
||||||
|
|
||||||
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,
|
locale,
|
||||||
db,
|
db,
|
||||||
monospace_font_ids,
|
monospace_font_ids,
|
||||||
per_script_monospace_font_ids: Default::default(),
|
per_script_monospace_font_ids,
|
||||||
font_cache: Default::default(),
|
font_cache: Default::default(),
|
||||||
font_matches_cache: Default::default(),
|
font_matches_cache: Default::default(),
|
||||||
font_codepoint_support_info_cache: Default::default(),
|
font_codepoint_support_info_cache: Default::default(),
|
||||||
|
|
@ -178,19 +204,7 @@ impl FontSystem {
|
||||||
#[cfg(feature = "shape-run-cache")]
|
#[cfg(feature = "shape-run-cache")]
|
||||||
shape_run_cache: crate::ShapeRunCache::default(),
|
shape_run_cache: crate::ShapeRunCache::default(),
|
||||||
shape_buffer: ShapeBuffer::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.
|
/// Get the locale.
|
||||||
|
|
@ -214,50 +228,6 @@ impl FontSystem {
|
||||||
(self.locale, self.db)
|
(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.
|
/// Get a font by its ID.
|
||||||
pub fn get_font(&mut self, id: fontdb::ID) -> Option<Arc<Font>> {
|
pub fn get_font(&mut self, id: fontdb::ID) -> Option<Arc<Font>> {
|
||||||
self.font_cache
|
self.font_cache
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue