mirror of
https://github.com/servo/servo.git
synced 2025-07-23 15:23:42 +01:00
auto merge of #5278 : pcwalton/servo/font-group-caching, r=glennw
There are several optimizations here: * We make font families atoms, to allow for quicker comparisons. * We precalculate an FNV hash of the relevant fields of the font style structure. * When obtaining a platform font group, we first check pointer equality for the font style. If there's no match, we go to the FNV hash. Only if both caches miss do we construct and cache a font group. Note that individual fonts are *also* cached; thus there are two layers of caching here. 15% improvement in total layout thread time for Facebook Timeline. r? @glennw (since you last worked on `get_layout_font_group_for_style()` IIRC)
This commit is contained in:
commit
ba0d28e002
14 changed files with 144 additions and 62 deletions
|
@ -66,6 +66,9 @@ branch = "upstream-2014-06-16"
|
||||||
[dependencies.script_traits]
|
[dependencies.script_traits]
|
||||||
path = "../script_traits"
|
path = "../script_traits"
|
||||||
|
|
||||||
|
[dependencies.string_cache]
|
||||||
|
git = "https://github.com/servo/string-cache"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
url = "0.2.16"
|
url = "0.2.16"
|
||||||
time = "0.1.12"
|
time = "0.1.12"
|
||||||
|
|
|
@ -9,16 +9,17 @@ use platform::font_list::get_last_resort_font_families;
|
||||||
use platform::font_context::FontContextHandle;
|
use platform::font_context::FontContextHandle;
|
||||||
|
|
||||||
use collections::str::Str;
|
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::borrow::ToOwned;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::mpsc::{Sender, Receiver, channel};
|
use std::sync::mpsc::{Sender, Receiver, channel};
|
||||||
use font_template::{FontTemplate, FontTemplateDescriptor};
|
use string_cache::Atom;
|
||||||
use platform::font_template::FontTemplateData;
|
|
||||||
use net::resource_task::{ResourceTask, load_whole_resource};
|
|
||||||
use util::task::spawn_named;
|
|
||||||
use util::str::LowercaseString;
|
|
||||||
use style::font_face::Source;
|
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.
|
/// A list of font templates that make up a given font family.
|
||||||
struct FontFamily {
|
struct FontFamily {
|
||||||
|
@ -77,7 +78,7 @@ impl FontFamily {
|
||||||
pub enum Command {
|
pub enum Command {
|
||||||
GetFontTemplate(String, FontTemplateDescriptor, Sender<Reply>),
|
GetFontTemplate(String, FontTemplateDescriptor, Sender<Reply>),
|
||||||
GetLastResortFontTemplate(FontTemplateDescriptor, Sender<Reply>),
|
GetLastResortFontTemplate(FontTemplateDescriptor, Sender<Reply>),
|
||||||
AddWebFont(String, Source, Sender<()>),
|
AddWebFont(Atom, Source, Sender<()>),
|
||||||
Exit(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();
|
let (response_chan, response_port) = channel();
|
||||||
self.chan.send(Command::AddWebFont(family, src, response_chan)).unwrap();
|
self.chan.send(Command::AddWebFont(family, src, response_chan)).unwrap();
|
||||||
response_port.recv().unwrap();
|
response_port.recv().unwrap();
|
||||||
|
|
|
@ -7,19 +7,24 @@ use font::SpecifiedFontStyle;
|
||||||
use platform::font_context::FontContextHandle;
|
use platform::font_context::FontContextHandle;
|
||||||
use style::computed_values::{font_style, font_variant};
|
use style::computed_values::{font_style, font_variant};
|
||||||
|
|
||||||
|
use font::FontHandleMethods;
|
||||||
use font_cache_task::FontCacheTask;
|
use font_cache_task::FontCacheTask;
|
||||||
use font_template::FontTemplateDescriptor;
|
use font_template::FontTemplateDescriptor;
|
||||||
use platform::font_template::FontTemplateData;
|
|
||||||
use font::FontHandleMethods;
|
|
||||||
use platform::font::FontHandle;
|
use platform::font::FontHandle;
|
||||||
use util::cache::HashCache;
|
use platform::font_template::FontTemplateData;
|
||||||
use util::smallvec::{SmallVec, SmallVec8};
|
|
||||||
use util::geometry::Au;
|
|
||||||
use util::arc_ptr_eq;
|
use util::arc_ptr_eq;
|
||||||
|
use util::cache::HashCache;
|
||||||
|
use util::fnv::FnvHasher;
|
||||||
|
use util::geometry::Au;
|
||||||
|
use util::smallvec::{SmallVec, SmallVec8};
|
||||||
|
|
||||||
use std::borrow::ToOwned;
|
use std::borrow::{self, ToOwned};
|
||||||
use std::rc::Rc;
|
|
||||||
use std::cell::RefCell;
|
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 std::sync::Arc;
|
||||||
|
|
||||||
use azure::AzFloat;
|
use azure::AzFloat;
|
||||||
|
@ -76,8 +81,8 @@ pub struct FontContext {
|
||||||
/// per frame. TODO: Make this weak when incremental redraw is done.
|
/// per frame. TODO: Make this weak when incremental redraw is done.
|
||||||
paint_font_cache: Vec<PaintFontCacheEntry>,
|
paint_font_cache: Vec<PaintFontCacheEntry>,
|
||||||
|
|
||||||
last_style: Option<Arc<SpecifiedFontStyle>>,
|
layout_font_group_cache:
|
||||||
last_fontgroup: Option<Rc<FontGroup>>,
|
HashMap<LayoutFontGroupCacheKey,Rc<FontGroup>,DefaultState<FnvHasher>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FontContext {
|
impl FontContext {
|
||||||
|
@ -89,8 +94,7 @@ impl FontContext {
|
||||||
layout_font_cache: vec!(),
|
layout_font_cache: vec!(),
|
||||||
fallback_font_cache: vec!(),
|
fallback_font_cache: vec!(),
|
||||||
paint_font_cache: vec!(),
|
paint_font_cache: vec!(),
|
||||||
last_style: None,
|
layout_font_group_cache: HashMap::with_hash_state(Default::default()),
|
||||||
last_fontgroup: None,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,14 +136,21 @@ impl FontContext {
|
||||||
/// this context.
|
/// this context.
|
||||||
pub fn get_layout_font_group_for_style(&mut self, style: Arc<SpecifiedFontStyle>)
|
pub fn get_layout_font_group_for_style(&mut self, style: Arc<SpecifiedFontStyle>)
|
||||||
-> Rc<FontGroup> {
|
-> Rc<FontGroup> {
|
||||||
let matches = match self.last_style {
|
let address = &*style as *const SpecifiedFontStyle as usize;
|
||||||
Some(ref last_style) => arc_ptr_eq(&style, last_style),
|
if let Some(ref cached_font_group) = self.layout_font_group_cache.get(&address) {
|
||||||
None => false,
|
return (*cached_font_group).clone()
|
||||||
};
|
|
||||||
if matches {
|
|
||||||
return self.last_fontgroup.as_ref().unwrap().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
|
// 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.
|
// 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_stretch,
|
||||||
style.font_style == font_style::T::italic ||
|
style.font_style == font_style::T::italic ||
|
||||||
style.font_style == font_style::T::oblique);
|
style.font_style == font_style::T::oblique);
|
||||||
|
|
||||||
let mut fonts = SmallVec8::new();
|
let mut fonts = SmallVec8::new();
|
||||||
|
|
||||||
for family in style.font_family.iter() {
|
for family in style.font_family.iter() {
|
||||||
|
@ -160,7 +172,7 @@ impl FontContext {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Some(ref cached_font_ref) => {
|
Some(ref cached_font_ref) => {
|
||||||
let cached_font = cached_font_ref.borrow();
|
let cached_font = (*cached_font_ref).borrow();
|
||||||
if cached_font.descriptor == desc &&
|
if cached_font.descriptor == desc &&
|
||||||
cached_font.requested_pt_size == style.font_size &&
|
cached_font.requested_pt_size == style.font_size &&
|
||||||
cached_font.variant == style.font_variant {
|
cached_font.variant == style.font_variant {
|
||||||
|
@ -243,8 +255,7 @@ impl FontContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
let font_group = Rc::new(FontGroup::new(fonts));
|
let font_group = Rc::new(FontGroup::new(fonts));
|
||||||
self.last_style = Some(style);
|
self.layout_font_group_cache.insert(layout_font_group_cache_key, font_group.clone());
|
||||||
self.last_fontgroup = Some(font_group.clone());
|
|
||||||
font_group
|
font_group
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -275,3 +286,34 @@ impl FontContext {
|
||||||
self.font_cache_task.clone()
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,11 +11,11 @@ use std::borrow::ToOwned;
|
||||||
use std::sync::{Arc, Weak};
|
use std::sync::{Arc, Weak};
|
||||||
use style::computed_values::{font_stretch, font_weight};
|
use style::computed_values::{font_stretch, font_weight};
|
||||||
|
|
||||||
/// Describes how to select a font from a given family.
|
/// Describes how to select a font from a given family. This is very basic at the moment and needs
|
||||||
/// This is very basic at the moment and needs to be
|
/// to be expanded or refactored when we support more of the font styling parameters.
|
||||||
/// 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)]
|
#[derive(Clone, Copy, Eq, Hash)]
|
||||||
pub struct FontTemplateDescriptor {
|
pub struct FontTemplateDescriptor {
|
||||||
pub weight: font_weight::T,
|
pub weight: font_weight::T,
|
||||||
pub stretch: font_stretch::T,
|
pub stretch: font_stretch::T,
|
||||||
|
|
|
@ -35,6 +35,7 @@ extern crate net;
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate util;
|
extern crate util;
|
||||||
extern crate msg;
|
extern crate msg;
|
||||||
|
extern crate string_cache;
|
||||||
extern crate style;
|
extern crate style;
|
||||||
extern crate skia;
|
extern crate skia;
|
||||||
extern crate time;
|
extern crate time;
|
||||||
|
|
|
@ -597,7 +597,7 @@ impl LayoutTask {
|
||||||
|
|
||||||
if mq.evaluate(&rw_data.stylist.device) {
|
if mq.evaluate(&rw_data.stylist.device) {
|
||||||
iter_font_face_rules(&sheet, &rw_data.stylist.device, &|family, src| {
|
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);
|
rw_data.stylist.add_stylesheet(sheet);
|
||||||
}
|
}
|
||||||
|
|
1
components/servo/Cargo.lock
generated
1
components/servo/Cargo.lock
generated
|
@ -320,6 +320,7 @@ dependencies = [
|
||||||
"script_traits 0.0.1",
|
"script_traits 0.0.1",
|
||||||
"skia 0.0.20130412 (git+https://github.com/servo/skia?branch=upstream-2014-06-16)",
|
"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)",
|
"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",
|
"style 0.0.1",
|
||||||
"time 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"url 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
|
|
@ -2,18 +2,18 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* 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/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use cssparser::{Token, Parser, DeclarationListParser, AtRuleParser, DeclarationParser};
|
|
||||||
use std::ascii::AsciiExt;
|
|
||||||
use stylesheets::CSSRule;
|
|
||||||
use properties::longhands::font_family::parse_one_family;
|
|
||||||
use computed_values::font_family::FontFamily;
|
use computed_values::font_family::FontFamily;
|
||||||
|
use cssparser::{Token, Parser, DeclarationListParser, AtRuleParser, DeclarationParser};
|
||||||
use media_queries::Device;
|
use media_queries::Device;
|
||||||
use url::{Url, UrlParser};
|
|
||||||
use parser::{ParserContext, log_css_error};
|
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 url::{Url, UrlParser};
|
||||||
|
|
||||||
|
pub fn iter_font_face_rules_inner<F>(rules: &[CSSRule], device: &Device, callback: &F)
|
||||||
pub fn iter_font_face_rules_inner<F>(rules: &[CSSRule], device: &Device,
|
where F: Fn(&Atom, &Source) {
|
||||||
callback: &F) where F: Fn(&str, &Source) {
|
|
||||||
for rule in rules.iter() {
|
for rule in rules.iter() {
|
||||||
match *rule {
|
match *rule {
|
||||||
CSSRule::Style(..) |
|
CSSRule::Style(..) |
|
||||||
|
@ -34,7 +34,7 @@ pub fn iter_font_face_rules_inner<F>(rules: &[CSSRule], device: &Device,
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
pub enum Source {
|
pub enum Source {
|
||||||
Url(UrlSource),
|
Url(UrlSource),
|
||||||
Local(String),
|
Local(Atom),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||||
|
@ -45,11 +45,10 @@ pub struct UrlSource {
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, Eq)]
|
#[derive(Debug, PartialEq, Eq)]
|
||||||
pub struct FontFaceRule {
|
pub struct FontFaceRule {
|
||||||
pub family: String,
|
pub family: Atom,
|
||||||
pub sources: Vec<Source>,
|
pub sources: Vec<Source>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn parse_font_face_block(context: &ParserContext, input: &mut Parser)
|
pub fn parse_font_face_block(context: &ParserContext, input: &mut Parser)
|
||||||
-> Result<FontFaceRule, ()> {
|
-> Result<FontFaceRule, ()> {
|
||||||
let mut family = None;
|
let mut family = None;
|
||||||
|
@ -83,7 +82,7 @@ pub fn parse_font_face_block(context: &ParserContext, input: &mut Parser)
|
||||||
}
|
}
|
||||||
|
|
||||||
enum FontFaceDescriptorDeclaration {
|
enum FontFaceDescriptorDeclaration {
|
||||||
Family(String),
|
Family(Atom),
|
||||||
Src(Vec<Source>),
|
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, ()> {
|
fn parse_value(&self, name: &str, input: &mut Parser) -> Result<FontFaceDescriptorDeclaration, ()> {
|
||||||
match_ignore_ascii_case! { name,
|
match_ignore_ascii_case! { name,
|
||||||
"font-family" => {
|
"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" => {
|
"src" => {
|
||||||
Ok(FontFaceDescriptorDeclaration::Src(try!(input.parse_comma_separated(|input| {
|
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) {
|
match parse_one_family(input) {
|
||||||
Ok(FontFamily::FamilyName(name)) => Ok(name),
|
Ok(FontFamily::FamilyName(name)) => Ok(name.clone()),
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,6 @@ use log;
|
||||||
|
|
||||||
use stylesheets::Origin;
|
use stylesheets::Origin;
|
||||||
|
|
||||||
|
|
||||||
pub struct ParserContext<'a> {
|
pub struct ParserContext<'a> {
|
||||||
pub base_url: &'a Url,
|
pub base_url: &'a Url,
|
||||||
pub selector_context: SelectorParserContext,
|
pub selector_context: SelectorParserContext,
|
||||||
|
|
|
@ -8,10 +8,13 @@
|
||||||
|
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
use std::borrow::ToOwned;
|
use std::borrow::ToOwned;
|
||||||
|
use std::default::Default;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::fmt::Debug;
|
use std::fmt::Debug;
|
||||||
|
use std::hash::{Hash, Hasher};
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use util::fnv::FnvHasher;
|
||||||
use util::logical_geometry::{WritingMode, LogicalMargin};
|
use util::logical_geometry::{WritingMode, LogicalMargin};
|
||||||
use util::geometry::Au;
|
use util::geometry::Au;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
@ -1456,18 +1459,20 @@ pub mod longhands {
|
||||||
${new_style_struct("Font", is_inherited=True)}
|
${new_style_struct("Font", is_inherited=True)}
|
||||||
|
|
||||||
<%self:longhand name="font-family">
|
<%self:longhand name="font-family">
|
||||||
use std::borrow::ToOwned;
|
|
||||||
use self::computed_value::FontFamily;
|
use self::computed_value::FontFamily;
|
||||||
|
use std::borrow::ToOwned;
|
||||||
|
use string_cache::Atom;
|
||||||
use values::computed::ComputedValueAsSpecified;
|
use values::computed::ComputedValueAsSpecified;
|
||||||
|
|
||||||
impl ComputedValueAsSpecified for SpecifiedValue {}
|
impl ComputedValueAsSpecified for SpecifiedValue {}
|
||||||
pub mod computed_value {
|
pub mod computed_value {
|
||||||
use cssparser::ToCss;
|
use cssparser::ToCss;
|
||||||
|
use string_cache::Atom;
|
||||||
use text_writer::{self, TextWriter};
|
use text_writer::{self, TextWriter};
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Clone)]
|
#[derive(PartialEq, Eq, Clone, Hash)]
|
||||||
pub enum FontFamily {
|
pub enum FontFamily {
|
||||||
FamilyName(String),
|
FamilyName(Atom),
|
||||||
// Generic
|
// Generic
|
||||||
// Serif,
|
// Serif,
|
||||||
// SansSerif,
|
// SansSerif,
|
||||||
|
@ -1476,16 +1481,17 @@ pub mod longhands {
|
||||||
// Monospace,
|
// Monospace,
|
||||||
}
|
}
|
||||||
impl FontFamily {
|
impl FontFamily {
|
||||||
|
#[inline]
|
||||||
pub fn name(&self) -> &str {
|
pub fn name(&self) -> &str {
|
||||||
match *self {
|
match *self {
|
||||||
FontFamily::FamilyName(ref name) => name,
|
FontFamily::FamilyName(ref name) => name.as_slice(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl ToCss for FontFamily {
|
impl ToCss for FontFamily {
|
||||||
fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
|
fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
|
||||||
match self {
|
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]
|
#[inline]
|
||||||
pub fn get_initial_value() -> computed_value::T {
|
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>#
|
||||||
/// <family-name> = <string> | [ <ident>+ ]
|
/// <family-name> = <string> | [ <ident>+ ]
|
||||||
|
@ -1516,7 +1522,7 @@ pub mod longhands {
|
||||||
}
|
}
|
||||||
pub fn parse_one_family(input: &mut Parser) -> Result<FontFamily, ()> {
|
pub fn parse_one_family(input: &mut Parser) -> Result<FontFamily, ()> {
|
||||||
if let Ok(value) = input.try(|input| input.expect_string()) {
|
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());
|
let first_ident = try!(input.expect_ident());
|
||||||
// match_ignore_ascii_case! { first_ident,
|
// match_ignore_ascii_case! { first_ident,
|
||||||
|
@ -1532,7 +1538,7 @@ pub mod longhands {
|
||||||
value.push_str(" ");
|
value.push_str(" ");
|
||||||
value.push_str(&ident);
|
value.push_str(&ident);
|
||||||
}
|
}
|
||||||
Ok(FontFamily::FamilyName(value))
|
Ok(FontFamily::FamilyName(Atom::from_slice(value.as_slice())))
|
||||||
}
|
}
|
||||||
</%self:longhand>
|
</%self:longhand>
|
||||||
|
|
||||||
|
@ -1592,10 +1598,10 @@ pub mod longhands {
|
||||||
}
|
}
|
||||||
pub mod computed_value {
|
pub mod computed_value {
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
#[derive(PartialEq, Eq, Copy, Clone)]
|
#[derive(PartialEq, Eq, Copy, Clone, Hash)]
|
||||||
pub enum T {
|
pub enum T {
|
||||||
% for weight in range(100, 901, 100):
|
% for weight in range(100, 901, 100):
|
||||||
Weight${weight},
|
Weight${weight} = ${weight},
|
||||||
% endfor
|
% endfor
|
||||||
}
|
}
|
||||||
impl fmt::Debug for T {
|
impl fmt::Debug for T {
|
||||||
|
@ -1608,6 +1614,7 @@ pub mod longhands {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl T {
|
impl T {
|
||||||
|
#[inline]
|
||||||
pub fn is_bold(self) -> bool {
|
pub fn is_bold(self) -> bool {
|
||||||
match self {
|
match self {
|
||||||
T::Weight900 | T::Weight800 |
|
T::Weight900 | T::Weight800 |
|
||||||
|
@ -4663,6 +4670,9 @@ pub mod style_structs {
|
||||||
% for longhand in style_struct.longhands:
|
% for longhand in style_struct.longhands:
|
||||||
pub ${longhand.ident}: longhands::${longhand.ident}::computed_value::T,
|
pub ${longhand.ident}: longhands::${longhand.ident}::computed_value::T,
|
||||||
% endfor
|
% endfor
|
||||||
|
% if style_struct.name == "Font":
|
||||||
|
pub hash: u64,
|
||||||
|
% endif
|
||||||
}
|
}
|
||||||
% endfor
|
% endfor
|
||||||
}
|
}
|
||||||
|
@ -4836,6 +4846,9 @@ lazy_static! {
|
||||||
% for longhand in style_struct.longhands:
|
% for longhand in style_struct.longhands:
|
||||||
${longhand.ident}: longhands::${longhand.ident}::get_initial_value(),
|
${longhand.ident}: longhands::${longhand.ident}::get_initial_value(),
|
||||||
% endfor
|
% endfor
|
||||||
|
% if style_struct.name == "Font":
|
||||||
|
hash: 0,
|
||||||
|
% endif
|
||||||
}),
|
}),
|
||||||
% endfor
|
% endfor
|
||||||
shareable: true,
|
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 {
|
ComputedValues {
|
||||||
writing_mode: get_writing_mode(&*style_inheritedbox),
|
writing_mode: get_writing_mode(&*style_inheritedbox),
|
||||||
% for style_struct in STYLE_STRUCTS:
|
% for style_struct in STYLE_STRUCTS:
|
||||||
|
@ -5180,6 +5198,11 @@ pub fn cascade(viewport_size: Size2D<Au>,
|
||||||
context.root_font_size = context.font_size;
|
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 {
|
(ComputedValues {
|
||||||
writing_mode: get_writing_mode(&*style_inheritedbox),
|
writing_mode: get_writing_mode(&*style_inheritedbox),
|
||||||
% for style_struct in STYLE_STRUCTS:
|
% for style_struct in STYLE_STRUCTS:
|
||||||
|
@ -5297,3 +5320,13 @@ pub fn longhands_from_shorthand(shorthand: &str) -> Option<Vec<String>> {
|
||||||
_ => None,
|
_ => 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()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -318,8 +318,8 @@ pub fn iter_stylesheet_style_rules<F>(stylesheet: &Stylesheet, device: &media_qu
|
||||||
|
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn iter_font_face_rules<F>(stylesheet: &Stylesheet, device: &Device,
|
pub fn iter_font_face_rules<F>(stylesheet: &Stylesheet, device: &Device, callback: &F)
|
||||||
callback: &F) where F: Fn(&str, &Source) {
|
where F: Fn(&Atom, &Source) {
|
||||||
iter_font_face_rules_inner(&stylesheet.rules, device, callback)
|
iter_font_face_rules_inner(&stylesheet.rules, device, callback)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ macro_rules! define_css_keyword_enum {
|
||||||
};
|
};
|
||||||
($name: ident: $( $css: expr => $variant: ident ),+) => {
|
($name: ident: $( $css: expr => $variant: ident ),+) => {
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[derive(Clone, Eq, PartialEq, FromPrimitive, Copy)]
|
#[derive(Clone, Eq, PartialEq, FromPrimitive, Copy, Hash)]
|
||||||
pub enum $name {
|
pub enum $name {
|
||||||
$( $variant ),+
|
$( $variant ),+
|
||||||
}
|
}
|
||||||
|
|
1
ports/cef/Cargo.lock
generated
1
ports/cef/Cargo.lock
generated
|
@ -325,6 +325,7 @@ dependencies = [
|
||||||
"script_traits 0.0.1",
|
"script_traits 0.0.1",
|
||||||
"skia 0.0.20130412 (git+https://github.com/servo/skia?branch=upstream-2014-06-16)",
|
"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)",
|
"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",
|
"style 0.0.1",
|
||||||
"time 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"url 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
|
1
ports/gonk/Cargo.lock
generated
1
ports/gonk/Cargo.lock
generated
|
@ -296,6 +296,7 @@ dependencies = [
|
||||||
"script_traits 0.0.1",
|
"script_traits 0.0.1",
|
||||||
"skia 0.0.20130412 (git+https://github.com/servo/skia?branch=upstream-2014-06-16)",
|
"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)",
|
"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",
|
"style 0.0.1",
|
||||||
"time 0.1.19 (registry+https://github.com/rust-lang/crates.io-index)",
|
"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)",
|
"url 0.2.23 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue