From a4c2e9dcf1a2f357a85484ad86e3162e0dbc841a Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 17 Oct 2013 17:32:33 +0100 Subject: [PATCH 1/7] CSS: rexport types and variants for computed values. --- src/components/style/common_types.rs | 48 ++++----- src/components/style/properties.rs.mako | 127 +++++++++++++++--------- src/components/style/style.rc | 9 +- 3 files changed, 109 insertions(+), 75 deletions(-) diff --git a/src/components/style/common_types.rs b/src/components/style/common_types.rs index 48cbafa51ed..60e2014f1a1 100644 --- a/src/components/style/common_types.rs +++ b/src/components/style/common_types.rs @@ -4,34 +4,34 @@ pub use servo_util::geometry::Au; -pub type Float = f64; +pub type CSSFloat = f64; pub mod specified { use std::ascii::StrAsciiExt; use cssparser::*; - use super::{Au, Float}; + use super::{Au, CSSFloat}; pub use CSSColor = cssparser::Color; #[deriving(Clone)] pub enum Length { Au_(Au), // application units - Em(Float), - Ex(Float), + Em(CSSFloat), + Ex(CSSFloat), // XXX uncomment when supported: -// Ch(Float), -// Rem(Float), -// Vw(Float), -// Vh(Float), -// Vmin(Float), -// Vmax(Float), +// Ch(CSSFloat), +// Rem(CSSFloat), +// Vw(CSSFloat), +// Vh(CSSFloat), +// Vmin(CSSFloat), +// Vmax(CSSFloat), } - static AU_PER_PX: Float = 60.; - static AU_PER_IN: Float = AU_PER_PX * 96.; - static AU_PER_CM: Float = AU_PER_IN / 2.54; - static AU_PER_MM: Float = AU_PER_IN / 25.4; - static AU_PER_PT: Float = AU_PER_IN / 72.; - static AU_PER_PC: Float = AU_PER_PT * 12.; + static AU_PER_PX: CSSFloat = 60.; + static AU_PER_IN: CSSFloat = AU_PER_PX * 96.; + static AU_PER_CM: CSSFloat = AU_PER_IN / 2.54; + static AU_PER_MM: CSSFloat = AU_PER_IN / 25.4; + static AU_PER_PT: CSSFloat = AU_PER_IN / 72.; + static AU_PER_PC: CSSFloat = AU_PER_PT * 12.; impl Length { #[inline] fn parse_internal(input: &ComponentValue, negative_ok: bool) -> Option { @@ -48,7 +48,7 @@ pub mod specified { pub fn parse_non_negative(input: &ComponentValue) -> Option { Length::parse_internal(input, /* negative_ok = */ false) } - pub fn parse_dimension(value: Float, unit: &str) -> Option { + pub fn parse_dimension(value: CSSFloat, unit: &str) -> Option { match unit.to_ascii_lower().as_slice() { "px" => Some(Length::from_px(value)), "in" => Some(Au_(Au((value * AU_PER_IN) as i32))), @@ -62,7 +62,7 @@ pub mod specified { } } #[inline] - pub fn from_px(px_value: Float) -> Length { + pub fn from_px(px_value: CSSFloat) -> Length { Au_(Au((px_value * AU_PER_PX) as i32)) } } @@ -70,7 +70,7 @@ pub mod specified { #[deriving(Clone)] pub enum LengthOrPercentage { LP_Length(Length), - LP_Percentage(Float), // [0 .. 100%] maps to [0.0 .. 1.0] + LP_Percentage(CSSFloat), // [0 .. 100%] maps to [0.0 .. 1.0] } impl LengthOrPercentage { fn parse_internal(input: &ComponentValue, negative_ok: bool) @@ -97,7 +97,7 @@ pub mod specified { #[deriving(Clone)] pub enum LengthOrPercentageOrAuto { LPA_Length(Length), - LPA_Percentage(Float), // [0 .. 100%] maps to [0.0 .. 1.0] + LPA_Percentage(CSSFloat), // [0 .. 100%] maps to [0.0 .. 1.0] LPA_Auto, } impl LengthOrPercentageOrAuto { @@ -135,7 +135,7 @@ pub mod computed { pub struct Context { current_color: cssparser::RGBA, font_size: Au, - font_weight: longhands::font_weight::ComputedValue, + font_weight: longhands::font_weight::computed_value::T, position: longhands::position::SpecifiedValue, float: longhands::float::SpecifiedValue, is_root_element: bool, @@ -147,7 +147,7 @@ pub mod computed { } #[inline] - fn mul(a: Au, b: Float) -> Au { Au(((*a as Float) * b) as i32) } + fn mul(a: Au, b: CSSFloat) -> Au { Au(((*a as CSSFloat) * b) as i32) } pub fn compute_Au(value: specified::Length, context: &Context) -> Au { match value { @@ -163,7 +163,7 @@ pub mod computed { #[deriving(Clone)] pub enum LengthOrPercentage { LP_Length(Au), - LP_Percentage(Float), + LP_Percentage(CSSFloat), } pub fn compute_LengthOrPercentage(value: specified::LengthOrPercentage, context: &Context) -> LengthOrPercentage { @@ -176,7 +176,7 @@ pub mod computed { #[deriving(Clone)] pub enum LengthOrPercentageOrAuto { LPA_Length(Au), - LPA_Percentage(Float), + LPA_Percentage(CSSFloat), LPA_Auto, } pub fn compute_LengthOrPercentageOrAuto(value: specified::LengthOrPercentageOrAuto, diff --git a/src/components/style/properties.rs.mako b/src/components/style/properties.rs.mako index b8ea608b212..4d7973f7f65 100644 --- a/src/components/style/properties.rs.mako +++ b/src/components/style/properties.rs.mako @@ -68,6 +68,7 @@ pub mod longhands { % if not no_super: use super::*; % endif + pub use self::computed_value::*; ${caller.body()} pub fn parse_declared(input: &[ComponentValue]) -> Option> { @@ -104,14 +105,16 @@ pub mod longhands { <%self:single_component_value name="${name}" inherited="${inherited}"> // The computed value is the same as the specified value. pub use to_computed_value = super::computed_as_specified; - #[deriving(Clone)] - pub enum SpecifiedValue { - % for value in values.split(): - ${to_rust_ident(value)}, - % endfor + pub mod computed_value { + #[deriving(Clone)] + pub enum T { + % for value in values.split(): + ${to_rust_ident(value)}, + % endfor + } } - pub type ComputedValue = SpecifiedValue; - #[inline] pub fn get_initial_value() -> ComputedValue { + pub type SpecifiedValue = computed_value::T; + #[inline] pub fn get_initial_value() -> computed_value::T { ${to_rust_ident(values.split()[0])} } pub fn from_component_value(v: &ComponentValue) -> Option { @@ -131,8 +134,10 @@ pub mod longhands { <%self:single_component_value name="${name}" inherited="${inherited}"> pub use to_computed_value = super::super::common_types::computed::compute_${type}; pub type SpecifiedValue = specified::${type}; - pub type ComputedValue = computed::${type}; - #[inline] pub fn get_initial_value() -> ComputedValue { ${initial_value} } + pub mod computed_value { + pub type T = super::super::computed::${type}; + } + #[inline] pub fn get_initial_value() -> computed_value::T { ${initial_value} } #[inline] pub fn from_component_value(v: &ComponentValue) -> Option { specified::${type}::${parse_method}(v) } @@ -169,7 +174,9 @@ pub mod longhands { <%self:longhand name="border-${side}-style", no_super="True"> pub use super::border_top_style::*; pub type SpecifiedValue = super::border_top_style::SpecifiedValue; - pub type ComputedValue = super::border_top_style::ComputedValue; + pub mod computed_value { + pub type T = super::super::border_top_style::computed_value::T; + } % endfor @@ -187,15 +194,18 @@ pub mod longhands { % for side in ["top", "right", "bottom", "left"]: <%self:longhand name="border-${side}-width"> pub type SpecifiedValue = specified::Length; - pub type ComputedValue = Au; - #[inline] pub fn get_initial_value() -> ComputedValue { + pub mod computed_value { + use super::super::Au; + pub type T = Au; + } + #[inline] pub fn get_initial_value() -> computed_value::T { Au::from_px(3) // medium } pub fn parse(input: &[ComponentValue]) -> Option { one_component_value(input).chain(parse_border_width) } pub fn to_computed_value(value: SpecifiedValue, context: &computed::Context) - -> ComputedValue { + -> computed_value::T { if context.has_border_${side} { computed::compute_Au(value, context) } else { Au(0) } } @@ -231,7 +241,7 @@ pub mod longhands { pub enum SpecifiedValue { SpecifiedNormal, SpecifiedLength(specified::Length), - SpecifiedNumber(Float), + SpecifiedNumber(CSSFloat), // percentage are the same as em. } /// normal | | | @@ -249,15 +259,18 @@ pub mod longhands { _ => None, } } - #[deriving(Clone)] - pub enum ComputedValue { - Normal, - Length(Au), - Number(Float), + pub mod computed_value { + use super::super::{Au, CSSFloat}; + #[deriving(Clone)] + pub enum T { + Normal, + Length(Au), + Number(CSSFloat), + } } - #[inline] pub fn get_initial_value() -> ComputedValue { Normal } + #[inline] pub fn get_initial_value() -> computed_value::T { Normal } pub fn to_computed_value(value: SpecifiedValue, context: &computed::Context) - -> ComputedValue { + -> computed_value::T { match value { SpecifiedNormal => Normal, SpecifiedLength(value) => Length(computed::compute_Au(value, context)), @@ -290,17 +303,20 @@ pub mod longhands { .map_move(SpecifiedLengthOrPercentage) } } - #[deriving(Clone)] - pub enum ComputedValue { - % for keyword in vertical_align_keywords: - ${to_rust_ident(keyword)}, - % endfor - Length(Au), - Percentage(Float), + pub mod computed_value { + use super::super::{Au, CSSFloat}; + #[deriving(Clone)] + pub enum T { + % for keyword in vertical_align_keywords: + ${to_rust_ident(keyword)}, + % endfor + Length(Au), + Percentage(CSSFloat), + } } - #[inline] pub fn get_initial_value() -> ComputedValue { baseline } + #[inline] pub fn get_initial_value() -> computed_value::T { baseline } pub fn to_computed_value(value: SpecifiedValue, context: &computed::Context) - -> ComputedValue { + -> computed_value::T { match value { % for keyword in vertical_align_keywords: Specified_${to_rust_ident(keyword)} => ${to_rust_ident(keyword)}, @@ -334,8 +350,10 @@ pub mod longhands { <%self:raw_longhand name="color" inherited="True"> pub use to_computed_value = super::computed_as_specified; pub type SpecifiedValue = RGBA; - pub type ComputedValue = SpecifiedValue; - #[inline] pub fn get_initial_value() -> ComputedValue { + pub mod computed_value { + pub type T = super::SpecifiedValue; + } + #[inline] pub fn get_initial_value() -> computed_value::T { RGBA { red: 0., green: 0., blue: 0., alpha: 1. } /* black */ } pub fn parse_specified(input: &[ComponentValue]) -> Option> { @@ -364,8 +382,10 @@ pub mod longhands { // Monospace, } pub type SpecifiedValue = ~[FontFamily]; - pub type ComputedValue = SpecifiedValue; - #[inline] pub fn get_initial_value() -> ComputedValue { ~[FamilyName(~"serif")] } + pub mod computed_value { + pub type T = super::SpecifiedValue; + } + #[inline] pub fn get_initial_value() -> computed_value::T { ~[FamilyName(~"serif")] } /// # /// = | [ + ] /// TODO: @@ -462,15 +482,17 @@ pub mod longhands { _ => None } } - #[deriving(Clone)] - pub enum ComputedValue { - % for weight in range(100, 901, 100): - Weight${weight}, - % endfor + pub mod computed_value { + #[deriving(Clone)] + pub enum T { + % for weight in range(100, 901, 100): + Weight${weight}, + % endfor + } } - #[inline] pub fn get_initial_value() -> ComputedValue { Weight400 } // normal + #[inline] pub fn get_initial_value() -> computed_value::T { Weight400 } // normal pub fn to_computed_value(value: SpecifiedValue, context: &computed::Context) - -> ComputedValue { + -> computed_value::T { match value { % for weight in range(100, 901, 100): SpecifiedWeight${weight} => Weight${weight}, @@ -504,8 +526,11 @@ pub mod longhands { <%self:single_component_value name="font-size" inherited="True"> pub use to_computed_value = super::super::common_types::computed::compute_Au; pub type SpecifiedValue = specified::Length; // Percentages are the same as em. - pub type ComputedValue = Au; - #[inline] pub fn get_initial_value() -> ComputedValue { + pub mod computed_value { + use super::super::Au; + pub type T = Au; + } + #[inline] pub fn get_initial_value() -> computed_value::T { Au::from_px(16) // medium } /// | @@ -537,8 +562,10 @@ pub mod longhands { // 'blink' is accepted in the parser but ignored. // Just not blinking the text is a conforming implementation per CSS 2.1. } - pub type ComputedValue = SpecifiedValue; - #[inline] pub fn get_initial_value() -> ComputedValue { + pub mod computed_value { + pub type T = super::SpecifiedValue; + } + #[inline] pub fn get_initial_value() -> computed_value::T { SpecifiedValue { underline: false, overline: false, line_through: false } // none } /// none | [ underline || overline || line-through || blink ] @@ -902,7 +929,7 @@ pub mod style_structs { % for name, longhands in LONGHANDS_PER_STYLE_STRUCT: pub struct ${name} { % for longhand in longhands: - ${longhand.ident}: longhands::${longhand.ident}::ComputedValue, + ${longhand.ident}: longhands::${longhand.ident}::computed_value::T, % endfor } % endfor @@ -1017,3 +1044,11 @@ pub fn cascade(applicable_declarations: &[@[PropertyDeclaration]], % endfor } } + + +// Only re-export the types for computed values. +pub mod computed_values { + % for property in LONGHANDS: + pub use ${property.ident} = super::longhands::${property.ident}::computed_value; + % endfor +} diff --git a/src/components/style/style.rc b/src/components/style/style.rc index 3527f3e9fea..553b550bd2b 100644 --- a/src/components/style/style.rc +++ b/src/components/style/style.rc @@ -18,11 +18,10 @@ extern mod servo_util (name = "util"); // The "real" public API -pub use self::selector_matching::{Stylist, StylesheetOrigin}; -pub use self::properties::cascade; -pub use self::properties::{PropertyDeclarationBlock, - parse_property_declaration_list}; // Style attributes - +pub use selector_matching::{Stylist, StylesheetOrigin}; +pub use properties::{cascade, computed_values}; +pub use properties::{PropertyDeclarationBlock, + parse_property_declaration_list}; // Style attributes // Things that need to be public to make the compiler happy pub mod stylesheets; From 6ddc2c37d15e9d641b2ae96d4189ec7820f48c29 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 17 Oct 2013 22:44:55 +0100 Subject: [PATCH 2/7] Add parsing a stylesheet form an iterator, a style attr form a string. --- src/components/style/properties.rs.mako | 9 +- src/components/style/selector_matching.rs | 5 +- src/components/style/style.rc | 6 +- src/components/style/stylesheets.rs | 134 ++++++++++++---------- 4 files changed, 87 insertions(+), 67 deletions(-) diff --git a/src/components/style/properties.rs.mako b/src/components/style/properties.rs.mako index 4d7973f7f65..0cc9b33da1b 100644 --- a/src/components/style/properties.rs.mako +++ b/src/components/style/properties.rs.mako @@ -815,10 +815,15 @@ pub struct PropertyDeclarationBlock { } -pub fn parse_property_declaration_list(input: ~[Node]) -> PropertyDeclarationBlock { +pub fn parse_style_attribute(input: &str) -> PropertyDeclarationBlock { + parse_property_declaration_list(tokenize(input)) +} + + +pub fn parse_property_declaration_list>(input: I) -> PropertyDeclarationBlock { let mut important = ~[]; let mut normal = ~[]; - for item in ErrorLoggerIterator(parse_declaration_list(input.move_iter())) { + for item in ErrorLoggerIterator(parse_declaration_list(input)) { match item { Decl_AtRule(rule) => log_css_error( rule.location, fmt!("Unsupported at-rule in declaration list: @%s", rule.name)), diff --git a/src/components/style/selector_matching.rs b/src/components/style/selector_matching.rs index f40cfe5c8e6..10de6d6117f 100644 --- a/src/components/style/selector_matching.rs +++ b/src/components/style/selector_matching.rs @@ -6,7 +6,7 @@ use std::ascii::StrAsciiExt; use extra::sort::tim_sort; use selectors::*; -use stylesheets::parse_stylesheet; +use stylesheets::Stylesheet; use media_queries::{Device, Screen}; use properties::{PropertyDeclaration, PropertyDeclarationBlock}; use servo_util::tree::{TreeNodeRefAsElement, TreeNode, ElementLike}; @@ -36,8 +36,7 @@ impl Stylist { } } - pub fn add_stylesheet(&mut self, css_source: &str, origin: StylesheetOrigin) { - let stylesheet = parse_stylesheet(css_source); + pub fn add_stylesheet(&mut self, stylesheet: Stylesheet, origin: StylesheetOrigin) { let rules = match origin { UserAgentOrigin => &mut self.ua_rules, AuthorOrigin => &mut self.author_rules, diff --git a/src/components/style/style.rc b/src/components/style/style.rc index 553b550bd2b..c926e41649d 100644 --- a/src/components/style/style.rc +++ b/src/components/style/style.rc @@ -18,10 +18,10 @@ extern mod servo_util (name = "util"); // The "real" public API +pub use stylesheets::Stylesheet; pub use selector_matching::{Stylist, StylesheetOrigin}; -pub use properties::{cascade, computed_values}; -pub use properties::{PropertyDeclarationBlock, - parse_property_declaration_list}; // Style attributes +pub use properties::{cascade, ComputedValues, computed_values}; +pub use properties::{PropertyDeclarationBlock, parse_style_attribute}; // Style attributes // Things that need to be public to make the compiler happy pub mod stylesheets; diff --git a/src/components/style/stylesheets.rs b/src/components/style/stylesheets.rs index c0c1394456c..c6a210f5ff4 100644 --- a/src/components/style/stylesheets.rs +++ b/src/components/style/stylesheets.rs @@ -2,6 +2,7 @@ * 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 std::str; use std::iterator::Iterator; use std::ascii::StrAsciiExt; use cssparser::*; @@ -31,65 +32,80 @@ pub struct StyleRule { } -pub fn parse_stylesheet(css: &str) -> Stylesheet { - static STATE_CHARSET: uint = 1; - static STATE_IMPORTS: uint = 2; - static STATE_NAMESPACES: uint = 3; - static STATE_BODY: uint = 4; - let mut state: uint = STATE_CHARSET; - - let mut rules = ~[]; - let mut namespaces = NamespaceMap::new(); - - for rule in ErrorLoggerIterator(parse_stylesheet_rules(tokenize(css))) { - let next_state; // Unitialized to force each branch to set it. - match rule { - QualifiedRule(rule) => { - next_state = STATE_BODY; - parse_style_rule(rule, &mut rules, &namespaces) - }, - AtRule(rule) => { - let lower_name = rule.name.to_ascii_lower(); - match lower_name.as_slice() { - "charset" => { - if state > STATE_CHARSET { - log_css_error(rule.location, "@charset must be the first rule") - } - // Valid @charset rules are just ignored - next_state = STATE_IMPORTS; - }, - "import" => { - if state > STATE_IMPORTS { - next_state = state; - log_css_error(rule.location, - "@import must be before any rule but @charset") - } else { - next_state = STATE_IMPORTS; - log_css_error(rule.location, "@import is not supported yet") // TODO - } - }, - "namespace" => { - if state > STATE_NAMESPACES { - next_state = state; - log_css_error( - rule.location, - "@namespace must be before any rule but @charset and @import" - ) - } else { - next_state = STATE_NAMESPACES; - parse_namespace_rule(rule, &mut namespaces) - } - }, - _ => { - next_state = STATE_BODY; - parse_nested_at_rule(lower_name, rule, &mut rules, &namespaces) - }, - } - }, +impl Stylesheet { + pub fn from_iter>(input: I) -> Stylesheet { + let mut string = ~""; + let mut input = input; + // TODO: incremental tokinization/parsing + for chunk in input { + // Assume UTF-8. This fails on invalid UTF-8 + // TODO: support character encodings (use rust-encodings in rust-cssparser) + string.push_str(str::from_utf8_owned(chunk)) } - state = next_state; + Stylesheet::from_str(string) + } + + pub fn from_str(css: &str) -> Stylesheet { + static STATE_CHARSET: uint = 1; + static STATE_IMPORTS: uint = 2; + static STATE_NAMESPACES: uint = 3; + static STATE_BODY: uint = 4; + let mut state: uint = STATE_CHARSET; + + let mut rules = ~[]; + let mut namespaces = NamespaceMap::new(); + + for rule in ErrorLoggerIterator(parse_stylesheet_rules(tokenize(css))) { + let next_state; // Unitialized to force each branch to set it. + match rule { + QualifiedRule(rule) => { + next_state = STATE_BODY; + parse_style_rule(rule, &mut rules, &namespaces) + }, + AtRule(rule) => { + let lower_name = rule.name.to_ascii_lower(); + match lower_name.as_slice() { + "charset" => { + if state > STATE_CHARSET { + log_css_error(rule.location, "@charset must be the first rule") + } + // Valid @charset rules are just ignored + next_state = STATE_IMPORTS; + }, + "import" => { + if state > STATE_IMPORTS { + next_state = state; + log_css_error(rule.location, + "@import must be before any rule but @charset") + } else { + next_state = STATE_IMPORTS; + // TODO: support @import + log_css_error(rule.location, "@import is not supported yet") + } + }, + "namespace" => { + if state > STATE_NAMESPACES { + next_state = state; + log_css_error( + rule.location, + "@namespace must be before any rule but @charset and @import" + ) + } else { + next_state = STATE_NAMESPACES; + parse_namespace_rule(rule, &mut namespaces) + } + }, + _ => { + next_state = STATE_BODY; + parse_nested_at_rule(lower_name, rule, &mut rules, &namespaces) + }, + } + }, + } + state = next_state; + } + Stylesheet{ rules: rules, namespaces: namespaces } } - Stylesheet{ rules: rules, namespaces: namespaces } } @@ -99,7 +115,7 @@ pub fn parse_style_rule(rule: QualifiedRule, parent_rules: &mut ~[CSSRule], match selectors::parse_selector_list(prelude, namespaces) { Some(selectors) => parent_rules.push(CSSStyleRule(StyleRule{ selectors: selectors, - declarations: properties::parse_property_declaration_list(block) + declarations: properties::parse_property_declaration_list(block.move_iter()) })), None => log_css_error(location, "Unsupported CSS selector."), } @@ -125,7 +141,7 @@ impl Stylesheet { struct StyleRuleIterator<'self> { device: &'self media_queries::Device, - // FIXME: I couldn’t get this to borrow-check with a stack of VecIterator + // FIXME: I couldn't get this to borrow-check with a stack of VecIterator stack: ~[(&'self [CSSRule], uint)], } From e30a950e4042ae36ed89de5494939011fbc4225d Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 17 Oct 2013 22:45:20 +0100 Subject: [PATCH 3/7] Add supported border styles to the CSS parser. --- src/components/style/properties.rs.mako | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/components/style/properties.rs.mako b/src/components/style/properties.rs.mako index 0cc9b33da1b..d7d72d593ad 100644 --- a/src/components/style/properties.rs.mako +++ b/src/components/style/properties.rs.mako @@ -168,8 +168,8 @@ pub mod longhands { ${predefined_type("border-%s-color" % side, "CSSColor", "CurrentColor")} % endfor - // dotted dashed double groove ridge insed outset - ${single_keyword("border-top-style", "none solid hidden")} + // double groove ridge insed outset + ${single_keyword("border-top-style", "none solid dotted dashed hidden")} % for side in ["right", "bottom", "left"]: <%self:longhand name="border-${side}-style", no_super="True"> pub use super::border_top_style::*; @@ -1056,4 +1056,6 @@ pub mod computed_values { % for property in LONGHANDS: pub use ${property.ident} = super::longhands::${property.ident}::computed_value; % endfor + // Don't use a side-specific name needlessly: + pub use border_style = super::longhands::border_top_style::computed_value; } From acb11343cebe82e077d55dc8e5af846c73a055d5 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Fri, 18 Oct 2013 14:25:11 +0100 Subject: [PATCH 4/7] Remove @pointers from Stylesheet to make it Sendable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit … at the cost some extra copying. This fixes #1081. --- src/components/style/properties.rs.mako | 13 ++++++------- src/components/style/selector_matching.rs | 12 ++++++++---- src/components/style/selectors.rs | 13 +++++++++---- src/components/style/stylesheets.rs | 2 +- 4 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/components/style/properties.rs.mako b/src/components/style/properties.rs.mako index d7d72d593ad..cf941fae432 100644 --- a/src/components/style/properties.rs.mako +++ b/src/components/style/properties.rs.mako @@ -5,7 +5,6 @@ // This file is a Mako template: http://www.makotemplates.org/ use std::ascii::StrAsciiExt; -use std::at_vec; pub use std::iterator; pub use cssparser::*; pub use errors::{ErrorLoggerIterator, log_css_error}; @@ -810,8 +809,8 @@ pub mod shorthands { pub struct PropertyDeclarationBlock { - important: @[PropertyDeclaration], - normal: @[PropertyDeclaration], + important: ~[PropertyDeclaration], + normal: ~[PropertyDeclaration], } @@ -837,9 +836,8 @@ pub fn parse_property_declaration_list>(input: I) -> PropertyD } } PropertyDeclarationBlock { - // TODO avoid copying? - important: at_vec::to_managed_move(important), - normal: at_vec::to_managed_move(normal), + important: important, + normal: normal, } } @@ -872,6 +870,7 @@ pub enum DeclaredValue { CSSWideKeyword(CSSWideKeyword), } +#[deriving(Clone)] pub enum PropertyDeclaration { % for property in LONGHANDS: ${property.ident}_declaration(DeclaredValue), @@ -961,7 +960,7 @@ fn get_initial_values() -> ComputedValues { // Most specific/important declarations last -pub fn cascade(applicable_declarations: &[@[PropertyDeclaration]], +pub fn cascade(applicable_declarations: &[~[PropertyDeclaration]], parent_style: Option< &ComputedValues>) -> ComputedValues { let initial_keep_alive; diff --git a/src/components/style/selector_matching.rs b/src/components/style/selector_matching.rs index 10de6d6117f..490d15c68ac 100644 --- a/src/components/style/selector_matching.rs +++ b/src/components/style/selector_matching.rs @@ -2,6 +2,7 @@ * 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 std::at_vec; use std::ascii::StrAsciiExt; use extra::sort::tim_sort; @@ -50,9 +51,10 @@ impl Stylist { if style_rule.declarations.$priority.len() > 0 { $flag = true; for selector in style_rule.selectors.iter() { + // TODO: avoid copying? rules.$priority.push(Rule { - selector: *selector, - declarations: style_rule.declarations.$priority, + selector: @(*selector).clone(), + declarations:at_vec::to_managed(style_rule.declarations.$priority), }) } } @@ -99,10 +101,12 @@ impl Stylist { // Style attributes have author origin but higher specificity than style rules. append!(self.author_rules.normal); - style_attribute.map(|sa| applicable_declarations.push(sa.normal)); + // TODO: avoid copying? + style_attribute.map(|sa| applicable_declarations.push(at_vec::to_managed(sa.normal))); append!(self.author_rules.important); - style_attribute.map(|sa| applicable_declarations.push(sa.important)); + // TODO: avoid copying? + style_attribute.map(|sa| applicable_declarations.push(at_vec::to_managed(sa.important))); append!(self.user_rules.important); append!(self.ua_rules.important); diff --git a/src/components/style/selectors.rs b/src/components/style/selectors.rs index e5d5666c40c..4a2ed8caed3 100644 --- a/src/components/style/selectors.rs +++ b/src/components/style/selectors.rs @@ -8,6 +8,7 @@ use cssparser::*; use namespaces::NamespaceMap; +#[deriving(Clone)] pub struct Selector { compound_selectors: CompoundSelector, pseudo_element: Option, @@ -17,7 +18,7 @@ pub struct Selector { pub static STYLE_ATTRIBUTE_SPECIFICITY: u32 = 1 << 31; -#[deriving(Eq)] +#[deriving(Eq, Clone)] pub enum PseudoElement { Before, After, @@ -26,11 +27,13 @@ pub enum PseudoElement { } +#[deriving(Clone)] pub struct CompoundSelector { simple_selectors: ~[SimpleSelector], next: Option<(~CompoundSelector, Combinator)>, // c.next is left of c } +#[deriving(Eq, Clone)] pub enum Combinator { Child, // > Descendant, // space @@ -38,6 +41,7 @@ pub enum Combinator { LaterSibling, // ~ } +#[deriving(Clone)] pub enum SimpleSelector { IDSelector(~str), ClassSelector(~str), @@ -62,6 +66,7 @@ pub enum SimpleSelector { // ... } +#[deriving(Clone)] pub struct AttrSelector { name: ~str, namespace: Option<~str>, @@ -73,7 +78,7 @@ type Iter = iterator::Peekable // None means invalid selector pub fn parse_selector_list(input: ~[ComponentValue], namespaces: &NamespaceMap) - -> Option<~[@Selector]> { + -> Option<~[Selector]> { let iter = &mut input.move_iter().peekable(); let first = match parse_selector(iter, namespaces) { None => return None, @@ -99,7 +104,7 @@ pub fn parse_selector_list(input: ~[ComponentValue], namespaces: &NamespaceMap) // None means invalid selector fn parse_selector(iter: &mut Iter, namespaces: &NamespaceMap) - -> Option<@Selector> { + -> Option { let (first, pseudo_element) = match parse_simple_selectors(iter, namespaces) { None => return None, Some(result) => result @@ -130,7 +135,7 @@ fn parse_selector(iter: &mut Iter, namespaces: &NamespaceMap) } } } - Some(@Selector { + Some(Selector { specificity: compute_specificity(&compound, &pseudo_element), compound_selectors: compound, pseudo_element: pseudo_element, diff --git a/src/components/style/stylesheets.rs b/src/components/style/stylesheets.rs index c6a210f5ff4..e3c8d5a6ad8 100644 --- a/src/components/style/stylesheets.rs +++ b/src/components/style/stylesheets.rs @@ -27,7 +27,7 @@ pub enum CSSRule { pub struct StyleRule { - selectors: ~[@selectors::Selector], + selectors: ~[selectors::Selector], declarations: properties::PropertyDeclarationBlock, } From 6178451ce0999800b031007b7778f6d748d5f502 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Fri, 18 Oct 2013 16:57:35 +0100 Subject: [PATCH 5/7] CSS: Add a ComputedValues::resolve_color() helper, for currentColor. --- src/components/style/properties.rs.mako | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/components/style/properties.rs.mako b/src/components/style/properties.rs.mako index cf941fae432..ff47ebfc852 100644 --- a/src/components/style/properties.rs.mako +++ b/src/components/style/properties.rs.mako @@ -945,6 +945,22 @@ pub struct ComputedValues { % endfor } +impl ComputedValues { + /// Resolves the currentColor keyword. + /// Any color value form computed values (except for the 'color' property itself) + /// should go through this method. + /// + /// Usage example: + /// let top_color = style.resolve_color(style.Border.border_top_color); + #[inline] + pub fn resolve_color(&self, color: computed::CSSColor) -> RGBA { + match color { + RGBA(rgba) => rgba, + CurrentColor => self.Color.color, + } + } +} + #[inline] fn get_initial_values() -> ComputedValues { ComputedValues { From 168261074c88459283fefd8e27acb4db273b16b1 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Fri, 18 Oct 2013 18:06:51 +0100 Subject: [PATCH 6/7] CSS: Make sure computed values implement Eq and Clone. --- src/components/style/common_types.rs | 4 ++-- src/components/style/properties.rs.mako | 14 ++++++++------ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/src/components/style/common_types.rs b/src/components/style/common_types.rs index 60e2014f1a1..96341e5d286 100644 --- a/src/components/style/common_types.rs +++ b/src/components/style/common_types.rs @@ -160,7 +160,7 @@ pub mod computed { } } - #[deriving(Clone)] + #[deriving(Eq, Clone)] pub enum LengthOrPercentage { LP_Length(Au), LP_Percentage(CSSFloat), @@ -173,7 +173,7 @@ pub mod computed { } } - #[deriving(Clone)] + #[deriving(Eq, Clone)] pub enum LengthOrPercentageOrAuto { LPA_Length(Au), LPA_Percentage(CSSFloat), diff --git a/src/components/style/properties.rs.mako b/src/components/style/properties.rs.mako index ff47ebfc852..7e5425f78ed 100644 --- a/src/components/style/properties.rs.mako +++ b/src/components/style/properties.rs.mako @@ -105,7 +105,7 @@ pub mod longhands { // The computed value is the same as the specified value. pub use to_computed_value = super::computed_as_specified; pub mod computed_value { - #[deriving(Clone)] + #[deriving(Eq, Clone)] pub enum T { % for value in values.split(): ${to_rust_ident(value)}, @@ -260,7 +260,7 @@ pub mod longhands { } pub mod computed_value { use super::super::{Au, CSSFloat}; - #[deriving(Clone)] + #[deriving(Eq, Clone)] pub enum T { Normal, Length(Au), @@ -304,7 +304,7 @@ pub mod longhands { } pub mod computed_value { use super::super::{Au, CSSFloat}; - #[deriving(Clone)] + #[deriving(Eq, Clone)] pub enum T { % for keyword in vertical_align_keywords: ${to_rust_ident(keyword)}, @@ -370,7 +370,7 @@ pub mod longhands { <%self:longhand name="font-family" inherited="True"> pub use to_computed_value = super::computed_as_specified; - #[deriving(Clone)] + #[deriving(Eq, Clone)] enum FontFamily { FamilyName(~str), // Generic @@ -482,7 +482,7 @@ pub mod longhands { } } pub mod computed_value { - #[deriving(Clone)] + #[deriving(Eq, Clone)] pub enum T { % for weight in range(100, 901, 100): Weight${weight}, @@ -553,7 +553,7 @@ pub mod longhands { <%self:longhand name="text-decoration"> pub use to_computed_value = super::computed_as_specified; - #[deriving(Clone)] + #[deriving(Eq, Clone)] pub struct SpecifiedValue { underline: bool, overline: bool, @@ -931,6 +931,7 @@ impl PropertyDeclaration { pub mod style_structs { use super::longhands; % for name, longhands in LONGHANDS_PER_STYLE_STRUCT: + #[deriving(Eq, Clone)] pub struct ${name} { % for longhand in longhands: ${longhand.ident}: longhands::${longhand.ident}::computed_value::T, @@ -939,6 +940,7 @@ pub mod style_structs { % endfor } +#[deriving(Eq, Clone)] pub struct ComputedValues { % for name, longhands in LONGHANDS_PER_STYLE_STRUCT: ${name}: style_structs::${name}, From ec711dac78750a8417c181cba0285f0753e82ff8 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Fri, 18 Oct 2013 20:57:16 +0100 Subject: [PATCH 7/7] CSS: fix tests. --- src/components/style/tests/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/style/tests/mod.rs b/src/components/style/tests/mod.rs index 8c2771a9a0a..e9a67a302c1 100644 --- a/src/components/style/tests/mod.rs +++ b/src/components/style/tests/mod.rs @@ -2,11 +2,11 @@ * 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 super::stylesheets::parse_stylesheet; +use super::stylesheets::Stylesheet; #[test] fn test_bootstrap() { // Test that parsing bootstrap does not trigger an assertion or otherwise fail. - let stylesheet = parse_stylesheet(include_str!("bootstrap-v3.0.0.css")); + let stylesheet = Stylesheet::from_str(include_str!("bootstrap-v3.0.0.css")); assert!(stylesheet.rules.len() > 100); // This depends on whet selectors are supported. }