diff options
-rw-r--r-- | components/gfx/Cargo.toml | 3 | ||||
-rw-r--r-- | components/gfx/font_cache_task.rs | 15 | ||||
-rw-r--r-- | components/gfx/font_context.rs | 80 | ||||
-rw-r--r-- | components/gfx/font_template.rs | 10 | ||||
-rw-r--r-- | components/gfx/lib.rs | 1 | ||||
-rw-r--r-- | components/layout/layout_task.rs | 2 | ||||
-rw-r--r-- | components/servo/Cargo.lock | 1 | ||||
-rw-r--r-- | components/style/font_face.rs | 28 | ||||
-rw-r--r-- | components/style/parser.rs | 1 | ||||
-rw-r--r-- | components/style/properties.mako.rs | 53 | ||||
-rw-r--r-- | components/style/stylesheets.rs | 4 | ||||
-rw-r--r-- | components/style/values.rs | 2 | ||||
-rw-r--r-- | ports/cef/Cargo.lock | 1 | ||||
-rw-r--r-- | ports/gonk/Cargo.lock | 1 |
14 files changed, 142 insertions, 60 deletions
diff --git a/components/gfx/Cargo.toml b/components/gfx/Cargo.toml index bb213624240..b012c92b6d8 100644 --- a/components/gfx/Cargo.toml +++ b/components/gfx/Cargo.toml @@ -66,6 +66,9 @@ branch = "upstream-2014-06-16" [dependencies.script_traits] path = "../script_traits" +[dependencies.string_cache] +git = "https://github.com/servo/string-cache" + [dependencies] url = "0.2.16" time = "0.1.12" diff --git a/components/gfx/font_cache_task.rs b/components/gfx/font_cache_task.rs index 8a87ed9fdb0..e22fe434f85 100644 --- a/components/gfx/font_cache_task.rs +++ b/components/gfx/font_cache_task.rs @@ -9,16 +9,17 @@ use platform::font_list::get_last_resort_font_families; use platform::font_context::FontContextHandle; use collections::str::Str; +use font_template::{FontTemplate, FontTemplateDescriptor}; +use net::resource_task::{ResourceTask, load_whole_resource}; +use platform::font_template::FontTemplateData; use std::borrow::ToOwned; use std::collections::HashMap; use std::sync::Arc; use std::sync::mpsc::{Sender, Receiver, channel}; -use font_template::{FontTemplate, FontTemplateDescriptor}; -use platform::font_template::FontTemplateData; -use net::resource_task::{ResourceTask, load_whole_resource}; -use util::task::spawn_named; -use util::str::LowercaseString; +use string_cache::Atom; use style::font_face::Source; +use util::str::LowercaseString; +use util::task::spawn_named; /// A list of font templates that make up a given font family. struct FontFamily { @@ -77,7 +78,7 @@ impl FontFamily { pub enum Command { GetFontTemplate(String, FontTemplateDescriptor, Sender<Reply>), GetLastResortFontTemplate(FontTemplateDescriptor, Sender<Reply>), - AddWebFont(String, Source, Sender<()>), + AddWebFont(Atom, Source, Sender<()>), Exit(Sender<()>), } @@ -315,7 +316,7 @@ impl FontCacheTask { } } - pub fn add_web_font(&self, family: String, src: Source) { + pub fn add_web_font(&self, family: Atom, src: Source) { let (response_chan, response_port) = channel(); self.chan.send(Command::AddWebFont(family, src, response_chan)).unwrap(); response_port.recv().unwrap(); diff --git a/components/gfx/font_context.rs b/components/gfx/font_context.rs index 24574676f65..fe9dbab2b12 100644 --- a/components/gfx/font_context.rs +++ b/components/gfx/font_context.rs @@ -7,19 +7,24 @@ use font::SpecifiedFontStyle; use platform::font_context::FontContextHandle; use style::computed_values::{font_style, font_variant}; +use font::FontHandleMethods; use font_cache_task::FontCacheTask; use font_template::FontTemplateDescriptor; -use platform::font_template::FontTemplateData; -use font::FontHandleMethods; use platform::font::FontHandle; +use platform::font_template::FontTemplateData; +use util::arc_ptr_eq; use util::cache::HashCache; -use util::smallvec::{SmallVec, SmallVec8}; +use util::fnv::FnvHasher; use util::geometry::Au; -use util::arc_ptr_eq; +use util::smallvec::{SmallVec, SmallVec8}; -use std::borrow::ToOwned; -use std::rc::Rc; +use std::borrow::{self, ToOwned}; use std::cell::RefCell; +use std::collections::HashMap; +use std::collections::hash_state::DefaultState; +use std::default::Default; +use std::hash::{Hash, Hasher}; +use std::rc::Rc; use std::sync::Arc; use azure::AzFloat; @@ -76,8 +81,8 @@ pub struct FontContext { /// per frame. TODO: Make this weak when incremental redraw is done. paint_font_cache: Vec<PaintFontCacheEntry>, - last_style: Option<Arc<SpecifiedFontStyle>>, - last_fontgroup: Option<Rc<FontGroup>>, + layout_font_group_cache: + HashMap<LayoutFontGroupCacheKey,Rc<FontGroup>,DefaultState<FnvHasher>>, } impl FontContext { @@ -89,8 +94,7 @@ impl FontContext { layout_font_cache: vec!(), fallback_font_cache: vec!(), paint_font_cache: vec!(), - last_style: None, - last_fontgroup: None, + layout_font_group_cache: HashMap::with_hash_state(Default::default()), } } @@ -132,14 +136,21 @@ impl FontContext { /// this context. pub fn get_layout_font_group_for_style(&mut self, style: Arc<SpecifiedFontStyle>) -> Rc<FontGroup> { - let matches = match self.last_style { - Some(ref last_style) => arc_ptr_eq(&style, last_style), - None => false, - }; - if matches { - return self.last_fontgroup.as_ref().unwrap().clone(); + 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() } + let layout_font_group_cache_key = LayoutFontGroupCacheKey { + pointer: style.clone(), + size: style.font_size, + address: address, + }; + if let Some(ref cached_font_group) = + self.layout_font_group_cache.get(&layout_font_group_cache_key) { + return (*cached_font_group).clone() + } + // TODO: The font context holds a strong ref to the cached fonts // so they will never be released. Find out a good time to drop them. @@ -147,6 +158,7 @@ impl FontContext { style.font_stretch, style.font_style == font_style::T::italic || style.font_style == font_style::T::oblique); + let mut fonts = SmallVec8::new(); for family in style.font_family.iter() { @@ -160,7 +172,7 @@ impl FontContext { break; } Some(ref cached_font_ref) => { - let cached_font = cached_font_ref.borrow(); + let cached_font = (*cached_font_ref).borrow(); if cached_font.descriptor == desc && cached_font.requested_pt_size == style.font_size && cached_font.variant == style.font_variant { @@ -243,8 +255,7 @@ impl FontContext { } let font_group = Rc::new(FontGroup::new(fonts)); - self.last_style = Some(style); - self.last_fontgroup = Some(font_group.clone()); + self.layout_font_group_cache.insert(layout_font_group_cache_key, font_group.clone()); font_group } @@ -275,3 +286,34 @@ impl FontContext { self.font_cache_task.clone() } } + +struct LayoutFontGroupCacheKey { + pointer: Arc<SpecifiedFontStyle>, + size: Au, + address: usize, +} + +impl PartialEq for LayoutFontGroupCacheKey { + fn eq(&self, other: &LayoutFontGroupCacheKey) -> bool { + self.pointer.font_family == other.pointer.font_family && + self.pointer.font_stretch == other.pointer.font_stretch && + self.pointer.font_style == other.pointer.font_style && + self.pointer.font_weight as u16 == other.pointer.font_weight as u16 && + self.size == other.size + } +} + +impl Eq for LayoutFontGroupCacheKey {} + +impl Hash for LayoutFontGroupCacheKey { + fn hash<H>(&self, hasher: &mut H) where H: Hasher { + self.pointer.hash.hash(hasher) + } +} + +impl borrow::Borrow<usize> for LayoutFontGroupCacheKey { + fn borrow(&self) -> &usize { + &self.address + } +} + diff --git a/components/gfx/font_template.rs b/components/gfx/font_template.rs index 736c8dfad41..50cf8c57fee 100644 --- a/components/gfx/font_template.rs +++ b/components/gfx/font_template.rs @@ -11,11 +11,11 @@ use std::borrow::ToOwned; use std::sync::{Arc, Weak}; use style::computed_values::{font_stretch, font_weight}; -/// Describes how to select a font from a given family. -/// This is very basic at the moment and needs to be -/// expanded or refactored when we support more of the -/// font styling parameters. -#[derive(Clone, Copy)] +/// Describes how to select a font from a given family. This is very basic at the moment and needs +/// to be expanded or refactored when we support more of the font styling parameters. +/// +/// NB: If you change this, you will need to update `style::properties::compute_font_hash()`. +#[derive(Clone, Copy, Eq, Hash)] pub struct FontTemplateDescriptor { pub weight: font_weight::T, pub stretch: font_stretch::T, diff --git a/components/gfx/lib.rs b/components/gfx/lib.rs index 0be282fb8f6..e1183753d5e 100644 --- a/components/gfx/lib.rs +++ b/components/gfx/lib.rs @@ -35,6 +35,7 @@ extern crate net; #[macro_use] extern crate util; extern crate msg; +extern crate string_cache; extern crate style; extern crate skia; extern crate time; diff --git a/components/layout/layout_task.rs b/components/layout/layout_task.rs index c61f84cf066..33bf00e837f 100644 --- a/components/layout/layout_task.rs +++ b/components/layout/layout_task.rs @@ -597,7 +597,7 @@ impl LayoutTask { if mq.evaluate(&rw_data.stylist.device) { iter_font_face_rules(&sheet, &rw_data.stylist.device, &|family, src| { - self.font_cache_task.add_web_font(family.to_owned(), (*src).clone()); + self.font_cache_task.add_web_font((*family).clone(), (*src).clone()); }); rw_data.stylist.add_stylesheet(sheet); } diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock index c7158c4239f..4183d8627e9 100644 --- a/components/servo/Cargo.lock +++ b/components/servo/Cargo.lock @@ -320,6 +320,7 @@ dependencies = [ "script_traits 0.0.1", "skia 0.0.20130412 (git+https://github.com/servo/skia?branch=upstream-2014-06-16)", "stb_image 0.1.0 (git+https://github.com/servo/rust-stb-image)", + "string_cache 0.0.0 (git+https://github.com/servo/string-cache)", "style 0.0.1", "time 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/components/style/font_face.rs b/components/style/font_face.rs index f10d2a4fa95..0c661745fb5 100644 --- a/components/style/font_face.rs +++ b/components/style/font_face.rs @@ -2,18 +2,18 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ +use computed_values::font_family::FontFamily; use cssparser::{Token, Parser, DeclarationListParser, AtRuleParser, DeclarationParser}; +use media_queries::Device; +use parser::{ParserContext, log_css_error}; +use properties::longhands::font_family::parse_one_family; use std::ascii::AsciiExt; +use string_cache::Atom; use stylesheets::CSSRule; -use properties::longhands::font_family::parse_one_family; -use computed_values::font_family::FontFamily; -use media_queries::Device; use url::{Url, UrlParser}; -use parser::{ParserContext, log_css_error}; - -pub fn iter_font_face_rules_inner<F>(rules: &[CSSRule], device: &Device, - callback: &F) where F: Fn(&str, &Source) { +pub fn iter_font_face_rules_inner<F>(rules: &[CSSRule], device: &Device, callback: &F) + where F: Fn(&Atom, &Source) { for rule in rules.iter() { match *rule { CSSRule::Style(..) | @@ -34,7 +34,7 @@ pub fn iter_font_face_rules_inner<F>(rules: &[CSSRule], device: &Device, #[derive(Clone, Debug, PartialEq, Eq)] pub enum Source { Url(UrlSource), - Local(String), + Local(Atom), } #[derive(Clone, Debug, PartialEq, Eq)] @@ -45,11 +45,10 @@ pub struct UrlSource { #[derive(Debug, PartialEq, Eq)] pub struct FontFaceRule { - pub family: String, + pub family: Atom, pub sources: Vec<Source>, } - pub fn parse_font_face_block(context: &ParserContext, input: &mut Parser) -> Result<FontFaceRule, ()> { let mut family = None; @@ -83,7 +82,7 @@ pub fn parse_font_face_block(context: &ParserContext, input: &mut Parser) } enum FontFaceDescriptorDeclaration { - Family(String), + Family(Atom), Src(Vec<Source>), } @@ -106,7 +105,8 @@ impl<'a, 'b> DeclarationParser for FontFaceRuleParser<'a, 'b> { fn parse_value(&self, name: &str, input: &mut Parser) -> Result<FontFaceDescriptorDeclaration, ()> { match_ignore_ascii_case! { name, "font-family" => { - Ok(FontFaceDescriptorDeclaration::Family(try!(parse_one_non_generic_family_name(input)))) + Ok(FontFaceDescriptorDeclaration::Family(try!( + parse_one_non_generic_family_name(input)))) }, "src" => { Ok(FontFaceDescriptorDeclaration::Src(try!(input.parse_comma_separated(|input| { @@ -118,9 +118,9 @@ impl<'a, 'b> DeclarationParser for FontFaceRuleParser<'a, 'b> { } } -fn parse_one_non_generic_family_name(input: &mut Parser) -> Result<String, ()> { +fn parse_one_non_generic_family_name(input: &mut Parser) -> Result<Atom, ()> { match parse_one_family(input) { - Ok(FontFamily::FamilyName(name)) => Ok(name), + Ok(FontFamily::FamilyName(name)) => Ok(name.clone()), _ => Err(()) } } diff --git a/components/style/parser.rs b/components/style/parser.rs index 6fd821f3435..c9d1891d708 100644 --- a/components/style/parser.rs +++ b/components/style/parser.rs @@ -10,7 +10,6 @@ use log; use stylesheets::Origin; - pub struct ParserContext<'a> { pub base_url: &'a Url, pub selector_context: SelectorParserContext, diff --git a/components/style/properties.mako.rs b/components/style/properties.mako.rs index d0503a83786..fbe09ac4dd4 100644 --- a/components/style/properties.mako.rs +++ b/components/style/properties.mako.rs @@ -8,10 +8,13 @@ use std::ascii::AsciiExt; use std::borrow::ToOwned; +use std::default::Default; use std::fmt; use std::fmt::Debug; +use std::hash::{Hash, Hasher}; use std::sync::Arc; +use util::fnv::FnvHasher; use util::logical_geometry::{WritingMode, LogicalMargin}; use util::geometry::Au; use url::Url; @@ -1456,18 +1459,20 @@ pub mod longhands { ${new_style_struct("Font", is_inherited=True)} <%self:longhand name="font-family"> - use std::borrow::ToOwned; use self::computed_value::FontFamily; + use std::borrow::ToOwned; + use string_cache::Atom; use values::computed::ComputedValueAsSpecified; impl ComputedValueAsSpecified for SpecifiedValue {} pub mod computed_value { use cssparser::ToCss; + use string_cache::Atom; use text_writer::{self, TextWriter}; - #[derive(PartialEq, Eq, Clone)] + #[derive(PartialEq, Eq, Clone, Hash)] pub enum FontFamily { - FamilyName(String), + FamilyName(Atom), // Generic // Serif, // SansSerif, @@ -1476,16 +1481,17 @@ pub mod longhands { // Monospace, } impl FontFamily { + #[inline] pub fn name(&self) -> &str { match *self { - FontFamily::FamilyName(ref name) => name, + FontFamily::FamilyName(ref name) => name.as_slice(), } } } impl ToCss for FontFamily { fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter { match self { - &FontFamily::FamilyName(ref name) => dest.write_str(&**name), + &FontFamily::FamilyName(ref name) => dest.write_str(name.as_slice()), } } } @@ -1506,7 +1512,7 @@ pub mod longhands { #[inline] pub fn get_initial_value() -> computed_value::T { - vec![FontFamily::FamilyName("serif".to_owned())] + vec![FontFamily::FamilyName(Atom::from_slice("serif"))] } /// <family-name># /// <family-name> = <string> | [ <ident>+ ] @@ -1516,7 +1522,7 @@ pub mod longhands { } pub fn parse_one_family(input: &mut Parser) -> Result<FontFamily, ()> { if let Ok(value) = input.try(|input| input.expect_string()) { - return Ok(FontFamily::FamilyName(value.into_owned())) + return Ok(FontFamily::FamilyName(Atom::from_slice(value.as_slice()))) } let first_ident = try!(input.expect_ident()); // match_ignore_ascii_case! { first_ident, @@ -1532,7 +1538,7 @@ pub mod longhands { value.push_str(" "); value.push_str(&ident); } - Ok(FontFamily::FamilyName(value)) + Ok(FontFamily::FamilyName(Atom::from_slice(value.as_slice()))) } </%self:longhand> @@ -1592,10 +1598,10 @@ pub mod longhands { } pub mod computed_value { use std::fmt; - #[derive(PartialEq, Eq, Copy, Clone)] + #[derive(PartialEq, Eq, Copy, Clone, Hash)] pub enum T { % for weight in range(100, 901, 100): - Weight${weight}, + Weight${weight} = ${weight}, % endfor } impl fmt::Debug for T { @@ -1608,6 +1614,7 @@ pub mod longhands { } } impl T { + #[inline] pub fn is_bold(self) -> bool { match self { T::Weight900 | T::Weight800 | @@ -4663,6 +4670,9 @@ pub mod style_structs { % for longhand in style_struct.longhands: pub ${longhand.ident}: longhands::${longhand.ident}::computed_value::T, % endfor + % if style_struct.name == "Font": + pub hash: u64, + % endif } % endfor } @@ -4836,6 +4846,9 @@ lazy_static! { % for longhand in style_struct.longhands: ${longhand.ident}: longhands::${longhand.ident}::get_initial_value(), % endfor + % if style_struct.name == "Font": + hash: 0, + % endif }), % endfor shareable: true, @@ -4932,6 +4945,11 @@ fn cascade_with_cached_declarations( } } + if seen.get_font_style() || seen.get_font_weight() || seen.get_font_stretch() || + seen.get_font_family() { + compute_font_hash(&mut *style_font.make_unique()) + } + ComputedValues { writing_mode: get_writing_mode(&*style_inheritedbox), % for style_struct in STYLE_STRUCTS: @@ -5180,6 +5198,11 @@ pub fn cascade(viewport_size: Size2D<Au>, context.root_font_size = context.font_size; } + if seen.get_font_style() || seen.get_font_weight() || seen.get_font_stretch() || + seen.get_font_family() { + compute_font_hash(&mut *style_font.make_unique()) + } + (ComputedValues { writing_mode: get_writing_mode(&*style_inheritedbox), % for style_struct in STYLE_STRUCTS: @@ -5297,3 +5320,13 @@ pub fn longhands_from_shorthand(shorthand: &str) -> Option<Vec<String>> { _ => None, } } + +/// Corresponds to the fields in `gfx::font_template::FontTemplateDescriptor`. +fn compute_font_hash(font: &mut style_structs::Font) { + let mut hasher: FnvHasher = Default::default(); + hasher.write_u16(font.font_weight as u16); + font.font_stretch.hash(&mut hasher); + font.font_family.hash(&mut hasher); + font.hash = hasher.finish() +} + diff --git a/components/style/stylesheets.rs b/components/style/stylesheets.rs index 1e7e78ac9cc..11135ac580e 100644 --- a/components/style/stylesheets.rs +++ b/components/style/stylesheets.rs @@ -318,8 +318,8 @@ pub fn iter_stylesheet_style_rules<F>(stylesheet: &Stylesheet, device: &media_qu #[inline] -pub fn iter_font_face_rules<F>(stylesheet: &Stylesheet, device: &Device, - callback: &F) where F: Fn(&str, &Source) { +pub fn iter_font_face_rules<F>(stylesheet: &Stylesheet, device: &Device, callback: &F) + where F: Fn(&Atom, &Source) { iter_font_face_rules_inner(&stylesheet.rules, device, callback) } diff --git a/components/style/values.rs b/components/style/values.rs index e26c37191a3..80801af930a 100644 --- a/components/style/values.rs +++ b/components/style/values.rs @@ -13,7 +13,7 @@ macro_rules! define_css_keyword_enum { }; ($name: ident: $( $css: expr => $variant: ident ),+) => { #[allow(non_camel_case_types)] - #[derive(Clone, Eq, PartialEq, FromPrimitive, Copy)] + #[derive(Clone, Eq, PartialEq, FromPrimitive, Copy, Hash)] pub enum $name { $( $variant ),+ } diff --git a/ports/cef/Cargo.lock b/ports/cef/Cargo.lock index bc0ed5a0da5..30adc00a7b4 100644 --- a/ports/cef/Cargo.lock +++ b/ports/cef/Cargo.lock @@ -325,6 +325,7 @@ dependencies = [ "script_traits 0.0.1", "skia 0.0.20130412 (git+https://github.com/servo/skia?branch=upstream-2014-06-16)", "stb_image 0.1.0 (git+https://github.com/servo/rust-stb-image)", + "string_cache 0.0.0 (git+https://github.com/servo/string-cache)", "style 0.0.1", "time 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/ports/gonk/Cargo.lock b/ports/gonk/Cargo.lock index db31cfd8db0..0ee174dbc67 100644 --- a/ports/gonk/Cargo.lock +++ b/ports/gonk/Cargo.lock @@ -296,6 +296,7 @@ dependencies = [ "script_traits 0.0.1", "skia 0.0.20130412 (git+https://github.com/servo/skia?branch=upstream-2014-06-16)", "stb_image 0.1.0 (git+https://github.com/servo/rust-stb-image)", + "string_cache 0.0.0 (git+https://github.com/servo/string-cache)", "style 0.0.1", "time 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)", "url 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)", |