layout: Load Web fonts asynchronously.

Improves page load times significantly.

Closes #7343.
This commit is contained in:
Patrick Walton 2015-09-10 14:16:50 -07:00
parent 9523283c14
commit 9bb6acd690
8 changed files with 216 additions and 35 deletions

View file

@ -24,6 +24,7 @@ use std::default::Default;
use std::hash::{Hash, Hasher};
use std::rc::Rc;
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
use string_cache::Atom;
use style::computed_values::{font_style, font_variant};
use util::cache::HashCache;
@ -61,6 +62,10 @@ struct PaintFontCacheEntry {
font: Rc<RefCell<ScaledFont>>,
}
/// An epoch for the font context cache. The cache is flushed if the current epoch does not match
/// this one.
static FONT_CACHE_EPOCH: AtomicUsize = ATOMIC_USIZE_INIT;
/// The FontContext represents the per-thread/task state necessary for
/// working with fonts. It is the public API used by the layout and
/// paint code. It talks directly to the font cache task where
@ -79,6 +84,8 @@ pub struct FontContext {
layout_font_group_cache:
HashMap<LayoutFontGroupCacheKey, Rc<FontGroup>, DefaultState<FnvHasher>>,
epoch: usize,
}
impl FontContext {
@ -91,6 +98,7 @@ impl FontContext {
fallback_font_cache: vec!(),
paint_font_cache: vec!(),
layout_font_group_cache: HashMap::with_hash_state(Default::default()),
epoch: 0,
}
}
@ -127,11 +135,26 @@ impl FontContext {
})
}
fn expire_font_caches_if_necessary(&mut self) {
let current_epoch = FONT_CACHE_EPOCH.load(Ordering::SeqCst);
if current_epoch == self.epoch {
return
}
self.layout_font_cache.clear();
self.fallback_font_cache.clear();
self.paint_font_cache.clear();
self.layout_font_group_cache.clear();
self.epoch = current_epoch
}
/// Create a group of fonts for use in layout calculations. May return
/// a cached font if this font instance has already been used by
/// this context.
pub fn layout_font_group_for_style(&mut self, style: Arc<SpecifiedFontStyle>)
-> Rc<FontGroup> {
self.expire_font_caches_if_necessary();
let address = &*style as *const SpecifiedFontStyle as usize;
if let Some(ref cached_font_group) = self.layout_font_group_cache.get(&address) {
return (*cached_font_group).clone()
@ -319,3 +342,9 @@ impl borrow::Borrow<usize> for LayoutFontGroupCacheKey {
&self.address
}
}
#[inline]
pub fn invalidate_font_caches() {
FONT_CACHE_EPOCH.fetch_add(1, Ordering::SeqCst);
}