Cache rustybuzz shape plans.
This commit is contained in:
parent
94e6cdefda
commit
73acfb0962
7 changed files with 98 additions and 17 deletions
|
|
@ -18,7 +18,7 @@ log = "0.4.20"
|
||||||
modit = { version = "0.1.3", optional = true }
|
modit = { version = "0.1.3", optional = true }
|
||||||
rangemap = "1.4.0"
|
rangemap = "1.4.0"
|
||||||
rustc-hash = { version = "1.1.0", default-features = false }
|
rustc-hash = { version = "1.1.0", default-features = false }
|
||||||
rustybuzz = { version = "0.11.0", default-features = false, features = ["libm"] }
|
rustybuzz = { version = "0.12.0", default-features = false, features = ["libm"] }
|
||||||
self_cell = "1.0.1"
|
self_cell = "1.0.1"
|
||||||
swash = { version = "0.1.8", optional = true }
|
swash = { version = "0.1.8", optional = true }
|
||||||
syntect = { version = "5.1.0", optional = true }
|
syntect = { version = "5.1.0", optional = true }
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ use alloc::vec::Vec;
|
||||||
use fontdb::Family;
|
use fontdb::Family;
|
||||||
use unicode_script::Script;
|
use unicode_script::Script;
|
||||||
|
|
||||||
use crate::{Font, FontSystem};
|
use crate::{Font, FontSystem, ShapePlanCache};
|
||||||
|
|
||||||
use self::platform::*;
|
use self::platform::*;
|
||||||
|
|
||||||
|
|
@ -103,6 +103,10 @@ impl<'a> FontFallbackIter<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn shape_plan_cache(&mut self) -> &mut ShapePlanCache {
|
||||||
|
self.font_system.shape_plan_cache()
|
||||||
|
}
|
||||||
|
|
||||||
fn face_contains_family(&self, id: fontdb::ID, family_name: &str) -> bool {
|
fn face_contains_family(&self, id: fontdb::ID, family_name: &str) -> bool {
|
||||||
if let Some(face) = self.font_system.db().face(id) {
|
if let Some(face) = self.font_system.db().face(id) {
|
||||||
face.families.iter().any(|(name, _)| name == family_name)
|
face.families.iter().any(|(name, _)| name == family_name)
|
||||||
|
|
|
||||||
|
|
@ -1,17 +1,10 @@
|
||||||
use crate::{Attrs, AttrsOwned, Font};
|
use crate::{Attrs, AttrsOwned, Font, HashMap, ShapePlanCache};
|
||||||
use alloc::string::String;
|
use alloc::string::String;
|
||||||
use alloc::sync::Arc;
|
use alloc::sync::Arc;
|
||||||
use alloc::vec::Vec;
|
use alloc::vec::Vec;
|
||||||
use core::fmt;
|
use core::fmt;
|
||||||
use core::ops::{Deref, DerefMut};
|
use core::ops::{Deref, DerefMut};
|
||||||
|
|
||||||
type BuildHasher = core::hash::BuildHasherDefault<rustc_hash::FxHasher>;
|
|
||||||
|
|
||||||
#[cfg(feature = "std")]
|
|
||||||
type HashMap<K, V> = std::collections::HashMap<K, V, BuildHasher>;
|
|
||||||
#[cfg(not(feature = "std"))]
|
|
||||||
type HashMap<K, V> = hashbrown::HashMap<K, V, BuildHasher>;
|
|
||||||
|
|
||||||
// re-export fontdb and rustybuzz
|
// re-export fontdb and rustybuzz
|
||||||
pub use fontdb;
|
pub use fontdb;
|
||||||
pub use rustybuzz;
|
pub use rustybuzz;
|
||||||
|
|
@ -29,6 +22,9 @@ pub struct FontSystem {
|
||||||
|
|
||||||
/// Cache for font matches.
|
/// Cache for font matches.
|
||||||
font_matches_cache: HashMap<AttrsOwned, Arc<Vec<fontdb::ID>>>,
|
font_matches_cache: HashMap<AttrsOwned, Arc<Vec<fontdb::ID>>>,
|
||||||
|
|
||||||
|
/// Cache for rustybuzz shape plans.
|
||||||
|
shape_plan_cache: ShapePlanCache,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for FontSystem {
|
impl fmt::Debug for FontSystem {
|
||||||
|
|
@ -74,8 +70,9 @@ impl FontSystem {
|
||||||
Self {
|
Self {
|
||||||
locale,
|
locale,
|
||||||
db,
|
db,
|
||||||
font_cache: HashMap::default(),
|
font_cache: Default::default(),
|
||||||
font_matches_cache: HashMap::default(),
|
font_matches_cache: Default::default(),
|
||||||
|
shape_plan_cache: ShapePlanCache::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -89,6 +86,11 @@ impl FontSystem {
|
||||||
&self.db
|
&self.db
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the shape plan cache.
|
||||||
|
pub(crate) fn shape_plan_cache(&mut self) -> &mut ShapePlanCache {
|
||||||
|
&mut self.shape_plan_cache
|
||||||
|
}
|
||||||
|
|
||||||
/// Get a mutable reference to the database.
|
/// Get a mutable reference to the database.
|
||||||
pub fn db_mut(&mut self) -> &mut fontdb::Database {
|
pub fn db_mut(&mut self) -> &mut fontdb::Database {
|
||||||
self.font_matches_cache.clear();
|
self.font_matches_cache.clear();
|
||||||
|
|
|
||||||
14
src/lib.rs
14
src/lib.rs
|
|
@ -108,8 +108,8 @@ mod buffer;
|
||||||
pub use self::buffer_line::*;
|
pub use self::buffer_line::*;
|
||||||
mod buffer_line;
|
mod buffer_line;
|
||||||
|
|
||||||
pub use self::cache::*;
|
pub use self::glyph_cache::*;
|
||||||
mod cache;
|
mod glyph_cache;
|
||||||
|
|
||||||
pub use self::edit::*;
|
pub use self::edit::*;
|
||||||
mod edit;
|
mod edit;
|
||||||
|
|
@ -123,7 +123,17 @@ mod layout;
|
||||||
pub use self::shape::*;
|
pub use self::shape::*;
|
||||||
mod shape;
|
mod shape;
|
||||||
|
|
||||||
|
use self::shape_plan_cache::*;
|
||||||
|
mod shape_plan_cache;
|
||||||
|
|
||||||
#[cfg(feature = "swash")]
|
#[cfg(feature = "swash")]
|
||||||
pub use self::swash::*;
|
pub use self::swash::*;
|
||||||
#[cfg(feature = "swash")]
|
#[cfg(feature = "swash")]
|
||||||
mod swash;
|
mod swash;
|
||||||
|
|
||||||
|
type BuildHasher = core::hash::BuildHasherDefault<rustc_hash::FxHasher>;
|
||||||
|
|
||||||
|
#[cfg(feature = "std")]
|
||||||
|
type HashMap<K, V> = std::collections::HashMap<K, V, BuildHasher>;
|
||||||
|
#[cfg(not(feature = "std"))]
|
||||||
|
type HashMap<K, V> = hashbrown::HashMap<K, V, BuildHasher>;
|
||||||
|
|
|
||||||
19
src/shape.rs
19
src/shape.rs
|
|
@ -12,7 +12,9 @@ use unicode_script::{Script, UnicodeScript};
|
||||||
use unicode_segmentation::UnicodeSegmentation;
|
use unicode_segmentation::UnicodeSegmentation;
|
||||||
|
|
||||||
use crate::fallback::FontFallbackIter;
|
use crate::fallback::FontFallbackIter;
|
||||||
use crate::{Align, AttrsList, Color, Font, FontSystem, LayoutGlyph, LayoutLine, Wrap};
|
use crate::{
|
||||||
|
Align, AttrsList, Color, Font, FontSystem, LayoutGlyph, LayoutLine, ShapePlanCache, Wrap,
|
||||||
|
};
|
||||||
|
|
||||||
/// The shaping strategy of some text.
|
/// The shaping strategy of some text.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||||
|
|
@ -85,6 +87,7 @@ impl fmt::Debug for ShapeBuffer {
|
||||||
fn shape_fallback(
|
fn shape_fallback(
|
||||||
scratch: &mut ShapeBuffer,
|
scratch: &mut ShapeBuffer,
|
||||||
glyphs: &mut Vec<ShapeGlyph>,
|
glyphs: &mut Vec<ShapeGlyph>,
|
||||||
|
shape_plan_cache: &mut ShapePlanCache,
|
||||||
font: &Font,
|
font: &Font,
|
||||||
line: &str,
|
line: &str,
|
||||||
attrs_list: &AttrsList,
|
attrs_list: &AttrsList,
|
||||||
|
|
@ -110,7 +113,8 @@ fn shape_fallback(
|
||||||
let rtl = matches!(buffer.direction(), rustybuzz::Direction::RightToLeft);
|
let rtl = matches!(buffer.direction(), rustybuzz::Direction::RightToLeft);
|
||||||
assert_eq!(rtl, span_rtl);
|
assert_eq!(rtl, span_rtl);
|
||||||
|
|
||||||
let glyph_buffer = rustybuzz::shape(font.rustybuzz(), &[], buffer);
|
let shape_plan = shape_plan_cache.get(font, &buffer);
|
||||||
|
let glyph_buffer = rustybuzz::shape_with_plan(font.rustybuzz(), shape_plan, buffer);
|
||||||
let glyph_infos = glyph_buffer.glyph_infos();
|
let glyph_infos = glyph_buffer.glyph_infos();
|
||||||
let glyph_positions = glyph_buffer.glyph_positions();
|
let glyph_positions = glyph_buffer.glyph_positions();
|
||||||
|
|
||||||
|
|
@ -218,7 +222,15 @@ fn shape_run(
|
||||||
|
|
||||||
let glyph_start = glyphs.len();
|
let glyph_start = glyphs.len();
|
||||||
let mut missing = shape_fallback(
|
let mut missing = shape_fallback(
|
||||||
scratch, glyphs, &font, line, attrs_list, start_run, end_run, span_rtl,
|
scratch,
|
||||||
|
glyphs,
|
||||||
|
font_iter.shape_plan_cache(),
|
||||||
|
&font,
|
||||||
|
line,
|
||||||
|
attrs_list,
|
||||||
|
start_run,
|
||||||
|
end_run,
|
||||||
|
span_rtl,
|
||||||
);
|
);
|
||||||
|
|
||||||
//TODO: improve performance!
|
//TODO: improve performance!
|
||||||
|
|
@ -236,6 +248,7 @@ fn shape_run(
|
||||||
let fb_missing = shape_fallback(
|
let fb_missing = shape_fallback(
|
||||||
scratch,
|
scratch,
|
||||||
&mut fb_glyphs,
|
&mut fb_glyphs,
|
||||||
|
font_iter.shape_plan_cache(),
|
||||||
&font,
|
&font,
|
||||||
line,
|
line,
|
||||||
attrs_list,
|
attrs_list,
|
||||||
|
|
|
||||||
52
src/shape_plan_cache.rs
Normal file
52
src/shape_plan_cache.rs
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
use std::collections::hash_map::Entry;
|
||||||
|
|
||||||
|
use crate::{Font, HashMap};
|
||||||
|
|
||||||
|
/// Key for caching shape plans.
|
||||||
|
#[derive(Debug, Hash, PartialEq, Eq)]
|
||||||
|
struct ShapePlanKey {
|
||||||
|
font_id: fontdb::ID,
|
||||||
|
direction: rustybuzz::Direction,
|
||||||
|
script: rustybuzz::Script,
|
||||||
|
language: Option<rustybuzz::Language>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A helper structure for caching rustybuzz shape plans.
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct ShapePlanCache(HashMap<ShapePlanKey, rustybuzz::ShapePlan>);
|
||||||
|
|
||||||
|
impl ShapePlanCache {
|
||||||
|
pub fn get(&mut self, font: &Font, buffer: &rustybuzz::UnicodeBuffer) -> &rustybuzz::ShapePlan {
|
||||||
|
let key = ShapePlanKey {
|
||||||
|
font_id: font.id(),
|
||||||
|
direction: buffer.direction(),
|
||||||
|
script: buffer.script(),
|
||||||
|
language: buffer.language(),
|
||||||
|
};
|
||||||
|
match self.0.entry(key) {
|
||||||
|
Entry::Occupied(occ) => occ.into_mut(),
|
||||||
|
Entry::Vacant(vac) => {
|
||||||
|
let ShapePlanKey {
|
||||||
|
direction,
|
||||||
|
script,
|
||||||
|
language,
|
||||||
|
..
|
||||||
|
} = vac.key();
|
||||||
|
let plan = rustybuzz::ShapePlan::new(
|
||||||
|
font.rustybuzz(),
|
||||||
|
*direction,
|
||||||
|
Some(*script),
|
||||||
|
language.as_ref(),
|
||||||
|
&[],
|
||||||
|
);
|
||||||
|
vac.insert(plan)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Debug for ShapePlanCache {
|
||||||
|
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
|
||||||
|
f.debug_tuple("ShapePlanCache").finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue