summaryrefslogtreecommitdiff
path: root/src/font
diff options
context:
space:
mode:
Diffstat (limited to 'src/font')
-rw-r--r--src/font/loader.rs49
1 files changed, 15 insertions, 34 deletions
diff --git a/src/font/loader.rs b/src/font/loader.rs
index a7c3bf4a..a0e2dce1 100644
--- a/src/font/loader.rs
+++ b/src/font/loader.rs
@@ -10,16 +10,14 @@ use super::{Font, FontInfo, FontClass, FontProvider};
/// Serves fonts matching queries.
pub struct FontLoader<'p> {
/// The font providers.
- providers: Vec<&'p (dyn FontProvider + 'p)>,
- /// The fonts available from each provider (indexed like `providers`).
- infos: Vec<&'p [FontInfo]>,
+ providers: Vec<Box<dyn FontProvider + 'p>>,
/// The internal state. Uses interior mutability because the loader works behind
/// an immutable reference to ease usage.
- state: RefCell<FontLoaderState<'p>>,
+ state: RefCell<FontLoaderState>,
}
/// Internal state of the font loader (seperated to wrap it in a `RefCell`).
-struct FontLoaderState<'p> {
+struct FontLoaderState {
/// The loaded fonts alongside their external indices. Some fonts may not
/// have external indices because they were loaded but did not contain the
/// required character. However, these are still stored because they may
@@ -28,21 +26,17 @@ struct FontLoaderState<'p> {
/// Allows to retrieve a font (index) quickly if a query was submitted before.
query_cache: HashMap<FontQuery, usize>,
/// Allows to re-retrieve loaded fonts by their info instead of loading them again.
- info_cache: HashMap<&'p FontInfo, usize>,
+ info_cache: HashMap<FontInfo, usize>,
/// Indexed by external indices (the ones inside the tuples in the `fonts` vector)
/// and maps to internal indices (the actual indices into the vector).
inner_index: Vec<usize>,
}
impl<'p> FontLoader<'p> {
- /// Create a new font loader using a set of providers.
- pub fn new<P: 'p>(providers: &'p [P]) -> FontLoader<'p> where P: AsRef<dyn FontProvider + 'p> {
- let providers: Vec<_> = providers.iter().map(|p| p.as_ref()).collect();
- let infos = providers.iter().map(|prov| prov.available()).collect();
-
+ /// Create a new font loader.
+ pub fn new() -> FontLoader<'p> {
FontLoader {
- providers,
- infos,
+ providers: vec![],
state: RefCell::new(FontLoaderState {
query_cache: HashMap::new(),
info_cache: HashMap::new(),
@@ -52,6 +46,11 @@ impl<'p> FontLoader<'p> {
}
}
+ /// Add a font provider to this loader.
+ pub fn add_font_provider<P: FontProvider + 'p>(&mut self, provider: P) {
+ self.providers.push(Box::new(provider));
+ }
+
/// Returns the font (and its index) best matching the query, if there is any.
pub fn get(&self, query: FontQuery) -> Option<(usize, Ref<Font>)> {
// Load results from the cache, if we had the exact same query before.
@@ -70,8 +69,8 @@ impl<'p> FontLoader<'p> {
// font that matches the first possible class.
for class in &query.fallback {
// For each class now go over all fonts from all font providers.
- for (provider, infos) in self.providers.iter().zip(&self.infos) {
- for info in infos.iter() {
+ for provider in &self.providers {
+ for info in provider.available().iter() {
let viable = info.classes.contains(class);
let matches = viable && query.classes.iter()
.all(|class| info.classes.contains(class));
@@ -90,7 +89,7 @@ impl<'p> FontLoader<'p> {
// Insert it into the storage and cache it by its info.
let index = state.fonts.len();
- state.info_cache.insert(info, index);
+ state.info_cache.insert(info.clone(), index);
state.fonts.push((None, font));
index
@@ -139,23 +138,6 @@ impl<'p> FontLoader<'p> {
let internal = state.inner_index[index];
Ref::map(state, |s| &s.fonts[internal].1)
}
-
- /// Move the whole list of fonts out.
- pub fn into_fonts(self) -> Vec<Font> {
- // Sort the fonts by external index so that they are in the correct order.
- // All fonts that were cached but not used by the outside are sorted to the back
- // and are removed in the next step.
- let mut fonts = self.state.into_inner().fonts;
- fonts.sort_by_key(|&(maybe_index, _)| match maybe_index {
- Some(index) => index,
- None => std::usize::MAX,
- });
-
- // Remove the fonts that are not used from the outside.
- fonts.into_iter().filter_map(|(maybe_index, font)| {
- if maybe_index.is_some() { Some(font) } else { None }
- }).collect()
- }
}
impl Debug for FontLoader<'_> {
@@ -163,7 +145,6 @@ impl Debug for FontLoader<'_> {
let state = self.state.borrow();
f.debug_struct("FontLoader")
.field("providers", &self.providers.len())
- .field("infos", &self.infos)
.field("fonts", &state.fonts)
.field("query_cache", &state.query_cache)
.field("info_cache", &state.info_cache)