aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbors-servo <release+servo@mozilla.com>2013-10-18 14:25:34 -0700
committerbors-servo <release+servo@mozilla.com>2013-10-18 14:25:34 -0700
commit8f7f70cb5c26c6787e322fdff729b3e5054398bd (patch)
treef88dbc964ebb91fc027bb84c5121cc58c8a41472
parent284ad5ee8eb43274036b05ae400fccb823313d15 (diff)
parentec711dac78750a8417c181cba0285f0753e82ff8 (diff)
downloadservo-8f7f70cb5c26c6787e322fdff729b3e5054398bd.tar.gz
servo-8f7f70cb5c26c6787e322fdff729b3e5054398bd.zip
auto merge of #1087 : SimonSapin/servo/newnewcss, r=kmcallister
This is still not the big switch yet, but preparatory changes contained to the 'style' crate. The current status of the actual port can be seen here: https://github.com/SimonSapin/servo/compare/newnewcss...break-all-the-things (moving as I push and rebase stuff.)
-rw-r--r--src/components/style/common_types.rs52
-rw-r--r--src/components/style/properties.rs.mako177
-rw-r--r--src/components/style/selector_matching.rs17
-rw-r--r--src/components/style/selectors.rs13
-rw-r--r--src/components/style/style.rc9
-rw-r--r--src/components/style/stylesheets.rs134
-rw-r--r--src/components/style/tests/mod.rs4
7 files changed, 244 insertions, 162 deletions
diff --git a/src/components/style/common_types.rs b/src/components/style/common_types.rs
index 48cbafa51ed..96341e5d286 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<Length> {
@@ -48,7 +48,7 @@ pub mod specified {
pub fn parse_non_negative(input: &ComponentValue) -> Option<Length> {
Length::parse_internal(input, /* negative_ok = */ false)
}
- pub fn parse_dimension(value: Float, unit: &str) -> Option<Length> {
+ pub fn parse_dimension(value: CSSFloat, unit: &str) -> Option<Length> {
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 {
@@ -160,10 +160,10 @@ pub mod computed {
}
}
- #[deriving(Clone)]
+ #[deriving(Eq, Clone)]
pub enum LengthOrPercentage {
LP_Length(Au),
- LP_Percentage(Float),
+ LP_Percentage(CSSFloat),
}
pub fn compute_LengthOrPercentage(value: specified::LengthOrPercentage, context: &Context)
-> LengthOrPercentage {
@@ -173,10 +173,10 @@ pub mod computed {
}
}
- #[deriving(Clone)]
+ #[deriving(Eq, 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..7e5425f78ed 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};
@@ -68,6 +67,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<DeclaredValue<SpecifiedValue>> {
@@ -104,14 +104,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(Eq, 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<SpecifiedValue> {
@@ -131,8 +133,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<SpecifiedValue> {
specified::${type}::${parse_method}(v)
}
@@ -163,13 +167,15 @@ 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::*;
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;
+ }
</%self:longhand>
% endfor
@@ -187,15 +193,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<SpecifiedValue> {
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 +240,7 @@ pub mod longhands {
pub enum SpecifiedValue {
SpecifiedNormal,
SpecifiedLength(specified::Length),
- SpecifiedNumber(Float),
+ SpecifiedNumber(CSSFloat),
// percentage are the same as em.
}
/// normal | <number> | <length> | <percentage>
@@ -249,15 +258,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(Eq, 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 +302,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(Eq, 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 +349,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<DeclaredValue<SpecifiedValue>> {
@@ -353,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
@@ -364,8 +381,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")] }
/// <familiy-name>#
/// <familiy-name> = <string> | [ <ident>+ ]
/// TODO: <generic-familiy>
@@ -462,15 +481,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(Eq, 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 +525,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
}
/// <length> | <percentage>
@@ -529,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,
@@ -537,8 +561,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 ]
@@ -783,15 +809,20 @@ pub mod shorthands {
pub struct PropertyDeclarationBlock {
- important: @[PropertyDeclaration],
- normal: @[PropertyDeclaration],
+ important: ~[PropertyDeclaration],
+ normal: ~[PropertyDeclaration],
}
-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<I: Iterator<Node>>(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)),
@@ -805,9 +836,8 @@ pub fn parse_property_declaration_list(input: ~[Node]) -> PropertyDeclarationBlo
}
}
PropertyDeclarationBlock {
- // TODO avoid copying?
- important: at_vec::to_managed_move(important),
- normal: at_vec::to_managed_move(normal),
+ important: important,
+ normal: normal,
}
}
@@ -840,6 +870,7 @@ pub enum DeclaredValue<T> {
CSSWideKeyword(CSSWideKeyword),
}
+#[deriving(Clone)]
pub enum PropertyDeclaration {
% for property in LONGHANDS:
${property.ident}_declaration(DeclaredValue<longhands::${property.ident}::SpecifiedValue>),
@@ -900,20 +931,38 @@ 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}::ComputedValue,
+ ${longhand.ident}: longhands::${longhand.ident}::computed_value::T,
% endfor
}
% endfor
}
+#[deriving(Eq, Clone)]
pub struct ComputedValues {
% for name, longhands in LONGHANDS_PER_STYLE_STRUCT:
${name}: style_structs::${name},
% 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 {
@@ -929,7 +978,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;
@@ -1017,3 +1066,13 @@ 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
+ // Don't use a side-specific name needlessly:
+ pub use border_style = super::longhands::border_top_style::computed_value;
+}
diff --git a/src/components/style/selector_matching.rs b/src/components/style/selector_matching.rs
index f40cfe5c8e6..490d15c68ac 100644
--- a/src/components/style/selector_matching.rs
+++ b/src/components/style/selector_matching.rs
@@ -2,11 +2,12 @@
* 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;
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 +37,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,
@@ -51,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),
})
}
}
@@ -100,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<PseudoElement>,
@@ -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<ComponentValue, vec::MoveIterator<ComponentValue>
// 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<Selector> {
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/style.rc b/src/components/style/style.rc
index 3527f3e9fea..c926e41649d 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 stylesheets::Stylesheet;
+pub use selector_matching::{Stylist, StylesheetOrigin};
+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..e3c8d5a6ad8 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::*;
@@ -26,70 +27,85 @@ pub enum CSSRule {
pub struct StyleRule {
- selectors: ~[@selectors::Selector],
+ selectors: ~[selectors::Selector],
declarations: properties::PropertyDeclarationBlock,
}
-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 {
+impl Stylesheet {
+ pub fn from_iter<I: Iterator<~[u8]>>(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))
+ }
+ 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;
- 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)
- },
- }
- },
+ },
+ "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;
}
- 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)],
}
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.
}