Cache fonts

This commit is contained in:
Jeremy Soller 2022-10-25 15:47:55 -06:00
parent c60aaaf9d2
commit 324c8837fd
No known key found for this signature in database
GPG key ID: 87F211AF2BE4C2FE
4 changed files with 46 additions and 23 deletions

View file

@ -829,8 +829,8 @@ impl<'a> TextBuffer<'a> {
"{}, {}: '{}' ('{}'): '{}' ({:?})",
self.cursor.line.get(),
self.cursor.index,
font_opt.map_or("?", |font| font.info.family.as_str()),
font_opt.map_or("?", |font| font.info.post_script_name.as_str()),
font_opt.as_ref().map_or("?", |font| font.info.family.as_str()),
font_opt.as_ref().map_or("?", |font| font.info.post_script_name.as_str()),
text_glyph,
text_glyph
);

View file

@ -1,8 +1,9 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
use std::sync::Arc;
use unicode_script::Script;
use super::Font;
use crate::Font;
use self::platform::*;
@ -27,7 +28,7 @@ mod platform;
mod platform;
pub struct FontFallbackIter<'a> {
fonts: &'a [Font<'a>],
fonts: &'a [Arc<Font<'a>>],
default_families: &'a [&'a str],
default_i: usize,
scripts: Vec<Script>,
@ -39,7 +40,12 @@ pub struct FontFallbackIter<'a> {
}
impl<'a> FontFallbackIter<'a> {
pub fn new(fonts: &'a [Font<'a>], default_families: &'a [&'a str], scripts: Vec<Script>, locale: &'a str) -> Self {
pub fn new(
fonts: &'a [Arc<Font<'a>>],
default_families: &'a [&'a str],
scripts: Vec<Script>,
locale: &'a str
) -> Self {
Self {
fonts,
default_families,
@ -84,7 +90,7 @@ impl<'a> FontFallbackIter<'a> {
}
impl<'a> Iterator for FontFallbackIter<'a> {
type Item = &'a Font<'a>;
type Item = &'a Arc<Font<'a>>;
fn next(&mut self) -> Option<Self::Item> {
while self.default_i < self.default_families.len() {
let default_family = self.default_families[self.default_i];

View file

@ -1,5 +1,6 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
use std::sync::Arc;
use unicode_script::{Script, UnicodeScript};
use super::{Font, FontShapeGlyph, FontShapeLine, FontShapeSpan, FontShapeWord};
@ -8,13 +9,13 @@ use super::fallback::{FontFallbackIter};
/// Fonts that match a pattern
pub struct FontMatches<'a> {
pub locale: &'a str,
pub fonts: Vec<Font<'a>>,
pub fonts: Vec<Arc<Font<'a>>>,
}
impl<'a> FontMatches<'a> {
fn shape_fallback(
&self,
font: &'a Font<'a>,
font: &Font<'a>,
line: &str,
start_word: usize,
end_word: usize,

View file

@ -1,14 +1,20 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
use std::{
collections::HashMap,
sync::{Arc, Mutex},
};
use crate::{Attrs, Font, FontMatches};
/// Access system fonts
pub struct FontSystem {
pub struct FontSystem<'a> {
pub locale: String,
db: fontdb::Database,
pub font_cache: Mutex<HashMap<fontdb::ID, Option<Arc<Font<'a>>>>>,
}
impl FontSystem {
impl<'a> FontSystem<'a> {
pub fn new() -> Self {
let locale = sys_locale::get_locale().unwrap_or_else(|| {
log::warn!("failed to get system locale, falling back to en-US");
@ -50,11 +56,29 @@ impl FontSystem {
);
}
Self { locale, db }
Self {
locale,
db,
font_cache: Mutex::new(HashMap::new()),
}
}
pub fn get_font(&'a self, id: fontdb::ID) -> Option<Arc<Font<'a>>> {
let mut font_cache = self.font_cache.lock().unwrap();
font_cache.entry(id).or_insert_with(|| {
let face = self.db.face(id)?;
match Font::new(face) {
Some(font) => Some(Arc::new(font)),
None => {
log::warn!("failed to load font '{}'", face.post_script_name);
None
}
}
}).clone()
}
pub fn matches<F: Fn(&fontdb::FaceInfo) -> bool>(
&self,
&'a self,
f: F,
) -> Option<FontMatches<'_>> {
let mut fonts = Vec::new();
@ -63,11 +87,9 @@ impl FontSystem {
continue;
}
match Font::new(face) {
match self.get_font(face.id) {
Some(font) => fonts.push(font),
None => {
log::warn!("failed to load font '{}'", face.post_script_name);
}
None => (),
}
}
@ -81,7 +103,7 @@ impl FontSystem {
}
}
pub fn matches_attrs(&self, attrs: Attrs) -> Option<FontMatches<'_>> {
pub fn matches_attrs(&'a self, attrs: Attrs) -> Option<FontMatches<'_>> {
self.matches(|info| {
let matched = {
info.style == attrs.style &&
@ -108,9 +130,3 @@ impl FontSystem {
})
}
}
impl Default for FontSystem {
fn default() -> Self {
Self::new()
}
}