FontContext: Cache data fetched from the cache thread

Before this change, if we needed to create a Font which we've already
created, but at a new size, then we'd fetch the FontTemplateInfo again.
If the bytes of the font are held in memory, then this could be
expensive as we need to pass those bytes over IPC.
This commit is contained in:
Jon Leighton 2018-04-02 21:49:19 +10:00
parent dc683a1fc9
commit 3025a269ec
4 changed files with 77 additions and 9 deletions

View file

@ -50,6 +50,7 @@ pub struct FontContext<S: FontSource> {
// so they will never be released. Find out a good time to drop them.
// See bug https://github.com/servo/servo/issues/3300
font_cache: HashMap<FontCacheKey, Option<FontRef>>,
font_template_cache: HashMap<FontTemplateCacheKey, Option<FontTemplateInfo>>,
font_group_cache:
HashMap<FontGroupCacheKey, Rc<RefCell<FontGroup>>, BuildHasherDefault<FnvHasher>>,
@ -64,6 +65,7 @@ impl<S: FontSource> FontContext<S> {
platform_handle: handle,
font_source,
font_cache: HashMap::new(),
font_template_cache: HashMap::new(),
font_group_cache: HashMap::with_hasher(Default::default()),
epoch: 0,
}
@ -76,6 +78,7 @@ impl<S: FontSource> FontContext<S> {
}
self.font_cache.clear();
self.font_template_cache.clear();
self.font_group_cache.clear();
self.epoch = current_epoch
}
@ -120,18 +123,42 @@ impl<S: FontSource> FontContext<S> {
);
let font =
self.font_source.font_template(
font_descriptor.template_descriptor.clone(),
family_descriptor.clone(),
)
.and_then(|template_info| self.create_font(template_info, font_descriptor.to_owned()).ok())
.map(|font| Rc::new(RefCell::new(font)));
self.font_template(&font_descriptor.template_descriptor, family_descriptor)
.and_then(|template_info| self.create_font(template_info, font_descriptor.to_owned()).ok())
.map(|font| Rc::new(RefCell::new(font)));
self.font_cache.insert(cache_key, font.clone());
font
})
}
fn font_template(
&mut self,
template_descriptor: &FontTemplateDescriptor,
family_descriptor: &FontFamilyDescriptor
) -> Option<FontTemplateInfo> {
let cache_key = FontTemplateCacheKey {
template_descriptor: template_descriptor.clone(),
family_descriptor: family_descriptor.clone(),
};
self.font_template_cache.get(&cache_key).map(|v| v.clone()).unwrap_or_else(|| {
debug!(
"FontContext::font_template cache miss for template_descriptor={:?} family_descriptor={:?}",
template_descriptor,
family_descriptor
);
let template_info = self.font_source.font_template(
template_descriptor.clone(),
family_descriptor.clone(),
);
self.font_template_cache.insert(cache_key, template_info.clone());
template_info
})
}
/// Create a `Font` for use in layout calculations, from a `FontTemplateData` returned by the
/// cache thread and a `FontDescriptor` which contains the styling parameters.
fn create_font(
@ -171,6 +198,12 @@ struct FontCacheKey {
family_descriptor: FontFamilyDescriptor,
}
#[derive(Debug, Eq, Hash, PartialEq)]
struct FontTemplateCacheKey {
template_descriptor: FontTemplateDescriptor,
family_descriptor: FontFamilyDescriptor,
}
#[derive(Debug)]
struct FontGroupCacheKey {
style: Arc<FontStyleStruct>,