diff --git a/components/style/custom_properties.rs b/components/style/custom_properties.rs index 9edeb7a04e3..d3d6e0aa6f7 100644 --- a/components/style/custom_properties.rs +++ b/components/style/custom_properties.rs @@ -9,7 +9,7 @@ use Atom; use cssparser::{Delimiter, Parser, SourcePosition, Token, TokenSerializationType}; use parser::ParserContext; -use properties::DeclaredValue; +use properties::{CSSWideKeyword, DeclaredValue}; use std::ascii::AsciiExt; use std::borrow::Cow; use std::collections::{HashMap, HashSet}; @@ -362,11 +362,13 @@ pub fn cascade<'a>(custom_properties: &mut Option unreachable!(), - DeclaredValue::Initial => { - map.remove(&name); + DeclaredValue::CSSWideKeyword(keyword) => match keyword { + CSSWideKeyword::Initial => { + map.remove(&name); + } + CSSWideKeyword::Unset | // Custom properties are inherited by default. + CSSWideKeyword::Inherit => {} // The inherited value is what we already have. } - DeclaredValue::Unset | // Custom properties are inherited by default. - DeclaredValue::Inherit => {} // The inherited value is what we already have. } } diff --git a/components/style/properties/helpers.mako.rs b/components/style/properties/helpers.mako.rs index 8b674a6c96e..861bcc2eaa6 100644 --- a/components/style/properties/helpers.mako.rs +++ b/components/style/properties/helpers.mako.rs @@ -70,7 +70,7 @@ pub mod single_value { use cssparser::Parser; use parser::{Parse, ParserContext, ParserContextExtraData}; - use properties::{CSSWideKeyword, DeclaredValue, ShorthandId}; + use properties::{DeclaredValue, ShorthandId}; use values::computed::{Context, ToComputedValue}; use values::{computed, specified}; use values::{Auto, Either, None_, Normal}; @@ -210,14 +210,14 @@ % if not property.derived_from: use cssparser::Parser; use parser::{Parse, ParserContext, ParserContextExtraData}; - use properties::{CSSWideKeyword, DeclaredValue, UnparsedValue, ShorthandId}; + use properties::{DeclaredValue, UnparsedValue, ShorthandId}; % endif use values::{Auto, Either, None_, Normal}; use cascade_info::CascadeInfo; use error_reporting::ParseErrorReporter; use properties::longhands; use properties::LonghandIdSet; - use properties::{ComputedValues, PropertyDeclaration}; + use properties::{CSSWideKeyword, ComputedValues, PropertyDeclaration}; use properties::style_structs; use std::boxed::Box as StdBox; use std::collections::HashMap; @@ -267,30 +267,32 @@ % endif } DeclaredValue::WithVariables(_) => unreachable!(), - % if not data.current_style_struct.inherited: - DeclaredValue::Unset | - % endif - DeclaredValue::Initial => { - // We assume that it's faster to use copy_*_from rather than - // set_*(get_initial_value()); - let initial_struct = default_style - .get_${data.current_style_struct.name_lower}(); - context.mutate_style().mutate_${data.current_style_struct.name_lower}() - .copy_${property.ident}_from(initial_struct ${maybe_wm}); - }, - % if data.current_style_struct.inherited: - DeclaredValue::Unset | - % endif - DeclaredValue::Inherit => { - // This is a bit slow, but this is rare so it shouldn't - // matter. - // - // FIXME: is it still? - *cacheable = false; - let inherited_struct = - inherited_style.get_${data.current_style_struct.name_lower}(); - context.mutate_style().mutate_${data.current_style_struct.name_lower}() - .copy_${property.ident}_from(inherited_struct ${maybe_wm}); + DeclaredValue::CSSWideKeyword(keyword) => match keyword { + % if not data.current_style_struct.inherited: + CSSWideKeyword::Unset | + % endif + CSSWideKeyword::Initial => { + // We assume that it's faster to use copy_*_from rather than + // set_*(get_initial_value()); + let initial_struct = default_style + .get_${data.current_style_struct.name_lower}(); + context.mutate_style().mutate_${data.current_style_struct.name_lower}() + .copy_${property.ident}_from(initial_struct ${maybe_wm}); + }, + % if data.current_style_struct.inherited: + CSSWideKeyword::Unset | + % endif + CSSWideKeyword::Inherit => { + // This is a bit slow, but this is rare so it shouldn't + // matter. + // + // FIXME: is it still? + *cacheable = false; + let inherited_struct = + inherited_style.get_${data.current_style_struct.name_lower}(); + context.mutate_style().mutate_${data.current_style_struct.name_lower}() + .copy_${property.ident}_from(inherited_struct ${maybe_wm}); + } } } }, error_reporter); @@ -324,9 +326,7 @@ -> Result, ()> { % endif match input.try(|i| CSSWideKeyword::parse(context, i)) { - Ok(CSSWideKeyword::InheritKeyword) => Ok(DeclaredValue::Inherit), - Ok(CSSWideKeyword::InitialKeyword) => Ok(DeclaredValue::Initial), - Ok(CSSWideKeyword::UnsetKeyword) => Ok(DeclaredValue::Unset), + Ok(keyword) => Ok(DeclaredValue::CSSWideKeyword(keyword)), Err(()) => { input.look_for_var_functions(); let start = input.position(); @@ -483,12 +483,11 @@ #[allow(unused_imports)] use cssparser::Parser; use parser::ParserContext; - use properties::{DeclaredValue, PropertyDeclaration, UnparsedValue}; - use properties::{ShorthandId, longhands}; + use properties::{DeclaredValue, PropertyDeclaration}; + use properties::{ShorthandId, UnparsedValue, longhands}; use properties::declaration_block::Importance; use std::fmt; use style_traits::ToCss; - use super::{SerializeFlags, ALL_INHERIT, ALL_INITIAL, ALL_UNSET}; pub struct Longhands { % for sub_property in shorthand.sub_properties: @@ -502,10 +501,10 @@ % for sub_property in shorthand.sub_properties: % if sub_property.boxed: pub ${sub_property.ident}: - &'a DeclaredValue>, + &'a Box, % else: pub ${sub_property.ident}: - &'a DeclaredValue, + &'a longhands::${sub_property.ident}::SpecifiedValue, % endif % endfor } @@ -525,7 +524,7 @@ for longhand in iter { match *longhand { % for sub_property in shorthand.sub_properties: - PropertyDeclaration::${sub_property.camel_case}(ref value) => { + PropertyDeclaration::${sub_property.camel_case}(DeclaredValue::Value(ref value)) => { ${sub_property.ident} = Some(value) }, % endfor @@ -555,40 +554,6 @@ } } - impl<'a> ToCss for LonghandsToSerialize<'a> { - fn to_css(&self, dest: &mut W) -> fmt::Result - where W: fmt::Write, - { - let mut all_flags = SerializeFlags::all(); - let mut with_variables = false; - % for sub_property in shorthand.sub_properties: - match *self.${sub_property.ident} { - DeclaredValue::Initial => all_flags &= ALL_INITIAL, - DeclaredValue::Inherit => all_flags &= ALL_INHERIT, - DeclaredValue::Unset => all_flags &= ALL_UNSET, - DeclaredValue::WithVariables(_) => with_variables = true, - DeclaredValue::Value(..) => { - all_flags = SerializeFlags::empty(); - } - } - % endfor - - if with_variables { - // We don't serialize shorthands with variables - dest.write_str("") - } else if all_flags == ALL_INHERIT { - dest.write_str("inherit") - } else if all_flags == ALL_INITIAL { - dest.write_str("initial") - } else if all_flags == ALL_UNSET { - dest.write_str("unset") - } else { - self.to_css_declared(dest) - } - } - } - - /// Parse the given shorthand and fill the result into the /// `declarations` vector. pub fn parse(context: &ParserContext, @@ -661,8 +626,8 @@ }) } - impl<'a> LonghandsToSerialize<'a> { - fn to_css_declared(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + impl<'a> ToCss for LonghandsToSerialize<'a> { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { super::serialize_four_sides( dest, self.${to_rust_ident(sub_property_pattern % 'top')}, diff --git a/components/style/properties/helpers/animated_properties.mako.rs b/components/style/properties/helpers/animated_properties.mako.rs index 9b0d2cc6bb3..0a9e5cd3ae6 100644 --- a/components/style/properties/helpers/animated_properties.mako.rs +++ b/components/style/properties/helpers/animated_properties.mako.rs @@ -8,7 +8,7 @@ use app_units::Au; use cssparser::{Color as CSSParserColor, Parser, RGBA}; use euclid::{Point2D, Size2D}; #[cfg(feature = "gecko")] use gecko_bindings::structs::nsCSSPropertyID; -use properties::{DeclaredValue, PropertyDeclaration}; +use properties::{CSSWideKeyword, DeclaredValue, PropertyDeclaration}; use properties::longhands; use properties::longhands::background_size::computed_value::T as BackgroundSize; use properties::longhands::font_weight::computed_value::T as FontWeight; @@ -287,21 +287,23 @@ impl AnimationValue { // https://bugzilla.mozilla.org/show_bug.cgi?id=1326131 DeclaredValue::WithVariables(_) => unimplemented!(), DeclaredValue::Value(ref val) => val.to_computed_value(context), - % if not prop.style_struct.inherited: - DeclaredValue::Unset | - % endif - DeclaredValue::Initial => { - let initial_struct = initial.get_${prop.style_struct.name_lower}(); - initial_struct.clone_${prop.ident}() - }, - % if prop.style_struct.inherited: - DeclaredValue::Unset | - % endif - DeclaredValue::Inherit => { - let inherit_struct = context.inherited_style - .get_${prop.style_struct.name_lower}(); - inherit_struct.clone_${prop.ident}() - }, + DeclaredValue::CSSWideKeyword(keyword) => match keyword { + % if not prop.style_struct.inherited: + CSSWideKeyword::Unset | + % endif + CSSWideKeyword::Initial => { + let initial_struct = initial.get_${prop.style_struct.name_lower}(); + initial_struct.clone_${prop.ident}() + }, + % if prop.style_struct.inherited: + CSSWideKeyword::Unset | + % endif + CSSWideKeyword::Inherit => { + let inherit_struct = context.inherited_style + .get_${prop.style_struct.name_lower}(); + inherit_struct.clone_${prop.ident}() + }, + } }; Some(AnimationValue::${prop.camel_case}(computed)) } diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index d582debeba2..4a7efc2755c 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -102,14 +102,6 @@ pub mod shorthands { use parser::{Parse, ParserContext}; use values::specified; - bitflags! { - flags SerializeFlags: u8 { - const ALL_INHERIT = 0b001, - const ALL_INITIAL = 0b010, - const ALL_UNSET = 0b100, - } - } - /// Parses a property for four different sides per CSS syntax. /// /// * Zero or more than four values is invalid. @@ -365,7 +357,13 @@ impl PropertyDeclarationIdSet { }) .unwrap_or( // Invalid at computed-value time. - DeclaredValue::${"Inherit" if property.style_struct.inherited else "Initial"} + DeclaredValue::CSSWideKeyword( + % if property.style_struct.inherited: + CSSWideKeyword::Inherit + % else: + CSSWideKeyword::Initial + % endif + ) ) ); } @@ -374,13 +372,30 @@ impl PropertyDeclarationIdSet { /// An enum to represent a CSS Wide keyword. #[derive(Copy, Clone, PartialEq, Eq, Debug)] +#[cfg_attr(feature = "servo", derive(HeapSizeOf))] pub enum CSSWideKeyword { /// The `initial` keyword. - InitialKeyword, + Initial, /// The `inherit` keyword. - InheritKeyword, + Inherit, /// The `unset` keyword. - UnsetKeyword, + Unset, +} + +impl CSSWideKeyword { + fn to_str(&self) -> &'static str { + match *self { + CSSWideKeyword::Initial => "initial", + CSSWideKeyword::Inherit => "inherit", + CSSWideKeyword::Unset => "unset", + } + } +} + +impl ToCss for CSSWideKeyword { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + dest.write_str(self.to_str()) + } } impl Parse for CSSWideKeyword { @@ -388,9 +403,9 @@ impl Parse for CSSWideKeyword { let ident = input.expect_ident()?; input.expect_exhausted()?; match_ignore_ascii_case! { &ident, - "initial" => Ok(CSSWideKeyword::InitialKeyword), - "inherit" => Ok(CSSWideKeyword::InheritKeyword), - "unset" => Ok(CSSWideKeyword::UnsetKeyword), + "initial" => Ok(CSSWideKeyword::Initial), + "inherit" => Ok(CSSWideKeyword::Inherit), + "unset" => Ok(CSSWideKeyword::Unset), _ => Err(()) } } @@ -528,7 +543,16 @@ impl ShorthandId { return None; } - if !declarations3.any(|d| d.with_variables()) { + // Check whether they are all the same CSS-wide keyword. + if let Some(keyword) = first_declaration.get_css_wide_keyword() { + if declarations2.all(|d| d.get_css_wide_keyword() == Some(keyword)) { + return Some(AppendableValue::Css(keyword.to_str())); + } + return None; + } + + // Check whether all declarations can be serialized as part of shorthand. + if declarations3.all(|d| d.may_serialize_as_part_of_shorthand()) { return Some(AppendableValue::DeclarationsForShorthand(self, declarations)); } @@ -545,12 +569,8 @@ pub enum DeclaredValue { Value(T), /// An unparsed value that contains `var()` functions. WithVariables(Box), - /// The `initial` keyword. - Initial, - /// The `inherit` keyword. - Inherit, - /// The `unset` keyword. - Unset, + /// An CSS-wide keyword. + CSSWideKeyword(CSSWideKeyword), } /// An unparsed property value that contains `var()` functions. @@ -575,9 +595,7 @@ impl HasViewportPercentage for DeclaredValue { panic!("DeclaredValue::has_viewport_percentage without \ resolving variables!") }, - DeclaredValue::Initial | - DeclaredValue::Inherit | - DeclaredValue::Unset => false, + DeclaredValue::CSSWideKeyword(_) => false, } } } @@ -595,9 +613,7 @@ impl ToCss for DeclaredValue { } Ok(()) }, - DeclaredValue::Initial => dest.write_str("initial"), - DeclaredValue::Inherit => dest.write_str("inherit"), - DeclaredValue::Unset => dest.write_str("unset"), + DeclaredValue::CSSWideKeyword(ref keyword) => keyword.to_css(dest), } } } @@ -918,23 +934,47 @@ impl PropertyDeclaration { } } - /// Return whether this is a pending-substitution value. - /// https://drafts.csswg.org/css-variables/#variables-in-shorthands - pub fn with_variables(&self) -> bool { + /// Returns a CSS-wide keyword if the declaration's value is one. + pub fn get_css_wide_keyword(&self) -> Option { match *self { % for property in data.longhands: PropertyDeclaration::${property.camel_case}(ref value) => match *value { - DeclaredValue::WithVariables(_) => true, - _ => false, + DeclaredValue::CSSWideKeyword(keyword) => Some(keyword), + _ => None, }, % endfor PropertyDeclaration::Custom(_, ref value) => match *value { - DeclaredValue::WithVariables(_) => true, - _ => false, + DeclaredValue::CSSWideKeyword(keyword) => Some(keyword), + _ => None, } } } + /// Returns whether the declaration may be serialized as part of a shorthand. + /// + /// This method returns false if this declaration contains variable or has a + /// CSS-wide keyword value, since these values cannot be serialized as part + /// of a shorthand. + /// + /// Caller should check `with_variables_from_shorthand()` and whether all + /// needed declarations has the same CSS-wide keyword first. + /// + /// Note that, serialization of a shorthand may still fail because of other + /// property-specific requirement even when this method returns true for all + /// the longhand declarations. + pub fn may_serialize_as_part_of_shorthand(&self) -> bool { + match *self { + % for property in data.longhands: + PropertyDeclaration::${property.camel_case}(ref value) => match *value { + DeclaredValue::Value(_) => true, + _ => false, + }, + % endfor + PropertyDeclaration::Custom(..) => + unreachable!("Serialize a custom property as part of shorthand?"), + } + } + /// Return whether the value is stored as it was in the CSS source, /// preserving whitespace (as opposed to being parsed into a more abstract /// data structure). @@ -969,9 +1009,7 @@ impl PropertyDeclaration { match id { PropertyId::Custom(name) => { let value = match input.try(|i| CSSWideKeyword::parse(context, i)) { - Ok(CSSWideKeyword::UnsetKeyword) => DeclaredValue::Unset, - Ok(CSSWideKeyword::InheritKeyword) => DeclaredValue::Inherit, - Ok(CSSWideKeyword::InitialKeyword) => DeclaredValue::Initial, + Ok(keyword) => DeclaredValue::CSSWideKeyword(keyword), Err(()) => match ::custom_properties::SpecifiedValue::parse(context, input) { Ok(value) => DeclaredValue::Value(value), Err(()) => return PropertyDeclarationParseResult::InvalidValue, @@ -1029,26 +1067,11 @@ impl PropertyDeclaration { ${property_pref_check(shorthand)} match input.try(|i| CSSWideKeyword::parse(context, i)) { - Ok(CSSWideKeyword::InheritKeyword) => { + Ok(keyword) => { % for sub_property in shorthand.sub_properties: result_list.push(( PropertyDeclaration::${sub_property.camel_case}( - DeclaredValue::Inherit), Importance::Normal)); - % endfor - PropertyDeclarationParseResult::ValidOrIgnoredDeclaration - }, - Ok(CSSWideKeyword::InitialKeyword) => { - % for sub_property in shorthand.sub_properties: - result_list.push(( - PropertyDeclaration::${sub_property.camel_case}( - DeclaredValue::Initial), Importance::Normal)); - % endfor - PropertyDeclarationParseResult::ValidOrIgnoredDeclaration - }, - Ok(CSSWideKeyword::UnsetKeyword) => { - % for sub_property in shorthand.sub_properties: - result_list.push((PropertyDeclaration::${sub_property.camel_case}( - DeclaredValue::Unset), Importance::Normal)); + DeclaredValue::CSSWideKeyword(keyword)), Importance::Normal)); % endfor PropertyDeclarationParseResult::ValidOrIgnoredDeclaration }, diff --git a/components/style/properties/shorthand/background.mako.rs b/components/style/properties/shorthand/background.mako.rs index 3404f6c9b26..a0747e9ea81 100644 --- a/components/style/properties/shorthand/background.mako.rs +++ b/components/style/properties/shorthand/background.mako.rs @@ -127,63 +127,36 @@ }) } - impl<'a> LonghandsToSerialize<'a> { - fn to_css_declared(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - // mako doesn't like ampersands following `<` - fn extract_value(x: &DeclaredValue) -> Option< &T> { - match *x { - DeclaredValue::Value(ref val) => Some(val), - _ => None, - } - } - - let len = extract_value(self.background_image).map(|i| i.0.len()).unwrap_or(0); + impl<'a> ToCss for LonghandsToSerialize<'a> { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + let len = self.background_image.0.len(); // There should be at least one declared value if len == 0 { - return dest.write_str("") + return Ok(()); } // If a value list length is differs then we don't do a shorthand serialization. // The exceptions to this is color which appears once only and is serialized // with the last item. % for name in "image position_x position_y size repeat origin clip attachment".split(): - if len != extract_value(self.background_${name}).map(|i| i.0.len()).unwrap_or(0) { - return dest.write_str("") + if len != self.background_${name}.0.len() { + return Ok(()); } % endfor - let mut first = true; for i in 0..len { % for name in "image position_x position_y repeat size attachment origin clip".split(): - let ${name} = if let DeclaredValue::Value(ref arr) = *self.background_${name} { - &arr.0[i] - } else { - unreachable!() - }; + let ${name} = &self.background_${name}.0[i]; % endfor - let color = if i == len - 1 { - Some(self.background_color) - } else { - None - }; - - if first { - first = false; - } else { + if i != 0 { try!(write!(dest, ", ")); } - match color { - Some(&DeclaredValue::Value(ref color)) => { - try!(color.to_css(dest)); - try!(write!(dest, " ")); - }, - Some(_) => { - try!(write!(dest, "transparent ")); - } - // Not yet the last one - None => () - }; + + if i == len - 1 { + try!(self.background_color.to_css(dest)); + try!(write!(dest, " ")); + } % for name in "image repeat attachment position_x position_y".split(): try!(${name}.to_css(dest)); @@ -251,49 +224,17 @@ }) } - impl<'a> LonghandsToSerialize<'a> { - fn to_css_declared(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - // mako doesn't like ampersands following `<` - fn extract_value(x: &DeclaredValue) -> Option< &T> { - match *x { - DeclaredValue::Value(ref val) => Some(val), - _ => None, - } + impl<'a> ToCss for LonghandsToSerialize<'a> { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + let len = self.background_position_x.0.len(); + if len == 0 || len != self.background_position_y.0.len() { + return Ok(()); } - use std::cmp; - let mut len = 0; - % for name in "x y".split(): - len = cmp::max(len, extract_value(self.background_position_${name}) - .map(|i| i.0.len()) - .unwrap_or(0)); - % endfor - - // There should be at least one declared value - if len == 0 { - return dest.write_str("") - } - for i in 0..len { - % for name in "x y".split(): - let position_${name} = if let DeclaredValue::Value(ref arr) = - *self.background_position_${name} { - arr.0.get(i % arr.0.len()) - } else { - None - }; - % endfor - - try!(position_x.unwrap_or(&background_position_x::single_value - ::get_initial_position_value()) - .to_css(dest)); - - try!(write!(dest, " ")); - - try!(position_y.unwrap_or(&background_position_y::single_value - ::get_initial_position_value()) - .to_css(dest)); + self.background_position_x.0[i].to_css(dest)?; + dest.write_str(" ")?; + self.background_position_y.0[i].to_css(dest)?; } - Ok(()) } } diff --git a/components/style/properties/shorthand/border.mako.rs b/components/style/properties/shorthand/border.mako.rs index ee023d90e16..a215cf89136 100644 --- a/components/style/properties/shorthand/border.mako.rs +++ b/components/style/properties/shorthand/border.mako.rs @@ -29,8 +29,8 @@ ${helpers.four_sides_shorthand("border-style", "border-%s-style", }) } - impl<'a> LonghandsToSerialize<'a> { - fn to_css_declared(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + impl<'a> ToCss for LonghandsToSerialize<'a> { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { % for side in ["top", "right", "bottom", "left"]: let ${side} = self.border_${side}_width.clone(); % endfor @@ -108,8 +108,8 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser) }) } - impl<'a> LonghandsToSerialize<'a> { - fn to_css_declared(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + impl<'a> ToCss for LonghandsToSerialize<'a> { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { super::serialize_directional_border( dest, self.border_${to_rust_ident(side)}_width, @@ -139,8 +139,8 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser) }) } - impl<'a> LonghandsToSerialize<'a> { - fn to_css_declared(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + impl<'a> ToCss for LonghandsToSerialize<'a> { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { let all_equal = { % for side in PHYSICAL_SIDES: let border_${side}_width = self.border_${side}_width; @@ -198,8 +198,8 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser) // TODO: I do not understand how border radius works with respect to the slashes /, // so putting a default generic impl for now // https://developer.mozilla.org/en-US/docs/Web/CSS/border-radius - impl<'a> LonghandsToSerialize<'a> { - fn to_css_declared(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + impl<'a> ToCss for LonghandsToSerialize<'a> { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { try!(self.border_top_left_radius.to_css(dest)); try!(write!(dest, " ")); @@ -289,55 +289,17 @@ pub fn parse_border(context: &ParserContext, input: &mut Parser) }) } - impl<'a> LonghandsToSerialize<'a> { - fn to_css_declared(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - % for name in "outset repeat slice source width".split(): - let ${name} = if let DeclaredValue::Value(ref value) = *self.border_image_${name} { - Some(value) - } else { - None - }; - % endfor - - if let Some(source) = source { - try!(source.to_css(dest)); - } else { - try!(write!(dest, "none")); - } - - try!(write!(dest, " ")); - - if let Some(slice) = slice { - try!(slice.to_css(dest)); - } else { - try!(write!(dest, "100%")); - } - - try!(write!(dest, " / ")); - - if let Some(width) = width { - try!(width.to_css(dest)); - } else { - try!(write!(dest, "1")); - } - - try!(write!(dest, " / ")); - - if let Some(outset) = outset { - try!(outset.to_css(dest)); - } else { - try!(write!(dest, "0")); - } - - try!(write!(dest, " ")); - - if let Some(repeat) = repeat { - try!(repeat.to_css(dest)); - } else { - try!(write!(dest, "stretch")); - } - - Ok(()) + impl<'a> ToCss for LonghandsToSerialize<'a> { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + self.border_image_source.to_css(dest)?; + dest.write_str(" ")?; + self.border_image_slice.to_css(dest)?; + dest.write_str(" / ")?; + self.border_image_width.to_css(dest)?; + dest.write_str(" / ")?; + self.border_image_outset.to_css(dest)?; + dest.write_str(" ")?; + self.border_image_repeat.to_css(dest) } } diff --git a/components/style/properties/shorthand/box.mako.rs b/components/style/properties/shorthand/box.mako.rs index d1b7ccb62f5..3bb821fe737 100644 --- a/components/style/properties/shorthand/box.mako.rs +++ b/components/style/properties/shorthand/box.mako.rs @@ -16,23 +16,13 @@ }) } - impl<'a> LonghandsToSerialize<'a> { - fn to_css_declared(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - let x_and_y_equal = match (self.overflow_x, self.overflow_y) { - (&DeclaredValue::Value(ref x_value), &DeclaredValue::Value(ref y_container)) => { - *x_value == y_container.0 - }, - (&DeclaredValue::WithVariables(_), &DeclaredValue::WithVariables(_)) => true, - (&DeclaredValue::Initial, &DeclaredValue::Initial) => true, - (&DeclaredValue::Inherit, &DeclaredValue::Inherit) => true, - (&DeclaredValue::Unset, &DeclaredValue::Unset) => true, - _ => false - }; - - if x_and_y_equal { - try!(self.overflow_x.to_css(dest)); + impl<'a> ToCss for LonghandsToSerialize<'a> { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + if *self.overflow_x == self.overflow_y.0 { + self.overflow_x.to_css(dest) + } else { + Ok(()) } - Ok(()) } } @@ -125,50 +115,30 @@ macro_rules! try_parse_one { }) } - impl<'a> LonghandsToSerialize<'a> { - fn to_css_declared(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - fn extract_value(x: &DeclaredValue) -> Option< &T> { - match *x { - DeclaredValue::Value(ref val) => Some(val), - _ => None, - } - } - - let len = extract_value(self.transition_property).map(|i| i.0.len()).unwrap_or(0); + impl<'a> ToCss for LonghandsToSerialize<'a> { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + let len = self.transition_property.0.len(); // There should be at least one declared value if len == 0 { - return dest.write_str("") + return Ok(()); } // If any value list length is differs then we don't do a shorthand serialization // either. % for name in "property duration delay timing_function".split(): - if len != extract_value(self.transition_${name}).map(|i| i.0.len()).unwrap_or(0) { - return dest.write_str("") + if len != self.transition_${name}.0.len() { + return Ok(()); } % endfor - let mut first = true; for i in 0..len { - % for name in "property duration delay timing_function".split(): - let ${name} = if let DeclaredValue::Value(ref arr) = *self.transition_${name} { - &arr.0[i] - } else { - unreachable!() - }; - % endfor - - if first { - first = false; - } else { - try!(write!(dest, ", ")); + if i != 0 { + write!(dest, ", ")?; } - - try!(property.to_css(dest)); - + self.transition_property.0[i].to_css(dest)?; % for name in "duration timing_function delay".split(): - try!(write!(dest, " ")); - try!(${name}.to_css(dest)); + dest.write_str(" ")?; + self.transition_${name}.0[i].to_css(dest)?; % endfor } Ok(()) @@ -287,51 +257,37 @@ macro_rules! try_parse_one { }) } - impl<'a> LonghandsToSerialize<'a> { - fn to_css_declared(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - fn extract_value(x: &DeclaredValue) -> Option< &T> { - match *x { - DeclaredValue::Value(ref val) => Some(val), - _ => None, - } - } - - let len = extract_value(self.animation_name).map(|i| i.0.len()).unwrap_or(0); + impl<'a> ToCss for LonghandsToSerialize<'a> { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + let len = self.animation_name.0.len(); // There should be at least one declared value if len == 0 { - return dest.write_str("") + return Ok(()); } + <% + subproperties = "duration timing_function delay direction \ + fill_mode iteration_count play_state".split() + %> + // If any value list length is differs then we don't do a shorthand serialization // either. - % for name in "duration timing_function delay direction fill_mode iteration_count play_state".split(): - if len != extract_value(self.animation_${name}).map(|i| i.0.len()).unwrap_or(0) { - return dest.write_str("") + % for name in subproperties: + if len != self.animation_${name}.0.len() { + return Ok(()) } % endfor - let mut first = true; for i in 0..len { - % for name in "duration timing_function delay direction fill_mode iteration_count play_state name".split(): - let ${name} = if let DeclaredValue::Value(ref arr) = *self.animation_${name} { - &arr.0[i] - } else { - unreachable!() - }; - % endfor - - if first { - first = false; - } else { + if i != 0 { try!(write!(dest, ", ")); } - % for name in "duration timing_function delay direction fill_mode iteration_count play_state".split(): - try!(${name}.to_css(dest)); - try!(write!(dest, " ")); - % endfor - - try!(name.to_css(dest)); + % for name in subproperties: + self.animation_${name}.0[i].to_css(dest)?; + dest.write_str(" ")?; + % endfor + self.animation_name.0[i].to_css(dest)?; } Ok(()) } @@ -351,21 +307,11 @@ macro_rules! try_parse_one { }) } - impl<'a> LonghandsToSerialize<'a> { + impl<'a> ToCss for LonghandsToSerialize<'a> { // Serializes into the single keyword value if both scroll-snap-type and scroll-snap-type-y are same. // Otherwise into an empty string. This is done to match Gecko's behaviour. - fn to_css_declared(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - let x_and_y_equal = match (self.scroll_snap_type_x, self.scroll_snap_type_y) { - (&DeclaredValue::Value(ref x_value), &DeclaredValue::Value(ref y_value)) => { - *x_value == *y_value - }, - (&DeclaredValue::Initial, &DeclaredValue::Initial) => true, - (&DeclaredValue::Inherit, &DeclaredValue::Inherit) => true, - (&DeclaredValue::Unset, &DeclaredValue::Unset) => true, - (x, y) => { *x == *y }, - }; - - if x_and_y_equal { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + if self.scroll_snap_type_x == self.scroll_snap_type_y { self.scroll_snap_type_x.to_css(dest) } else { Ok(()) diff --git a/components/style/properties/shorthand/column.mako.rs b/components/style/properties/shorthand/column.mako.rs index 0fe39cbb2d1..3e8648d38ba 100644 --- a/components/style/properties/shorthand/column.mako.rs +++ b/components/style/properties/shorthand/column.mako.rs @@ -49,8 +49,8 @@ } } - impl<'a> LonghandsToSerialize<'a> { - fn to_css_declared(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + impl<'a> ToCss for LonghandsToSerialize<'a> { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { try!(self.column_width.to_css(dest)); try!(write!(dest, " ")); @@ -96,30 +96,13 @@ } } - impl<'a> LonghandsToSerialize<'a> { - fn to_css_declared(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - let mut need_space = false; - - if let DeclaredValue::Value(ref width) = *self.column_rule_width { - try!(width.to_css(dest)); - need_space = true; - } - - if let DeclaredValue::Value(ref style) = *self.column_rule_style { - if need_space { - try!(write!(dest, " ")); - } - try!(style.to_css(dest)); - need_space = true; - } - - if let DeclaredValue::Value(ref color) = *self.column_rule_color { - if need_space { - try!(write!(dest, " ")); - } - try!(color.to_css(dest)); - } - Ok(()) + impl<'a> ToCss for LonghandsToSerialize<'a> { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + self.column_rule_width.to_css(dest)?; + dest.write_str(" ")?; + self.column_rule_style.to_css(dest)?; + dest.write_str(" ")?; + self.column_rule_color.to_css(dest) } } diff --git a/components/style/properties/shorthand/font.mako.rs b/components/style/properties/shorthand/font.mako.rs index 22d3001d656..a94c2efa7c1 100644 --- a/components/style/properties/shorthand/font.mako.rs +++ b/components/style/properties/shorthand/font.mako.rs @@ -95,41 +95,27 @@ } // This may be a bit off, unsure, possibly needs changes - impl<'a> LonghandsToSerialize<'a> { - fn to_css_declared(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - if let DeclaredValue::Value(ref style) = *self.font_style { - try!(style.to_css(dest)); - try!(write!(dest, " ")); - } + impl<'a> ToCss for LonghandsToSerialize<'a> { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + self.font_style.to_css(dest)?; + dest.write_str(" ")?; + self.font_variant.to_css(dest)?; + dest.write_str(" ")?; + self.font_weight.to_css(dest)?; + dest.write_str(" ")?; + self.font_stretch.to_css(dest)?; + dest.write_str(" ")?; - if let DeclaredValue::Value(ref variant) = *self.font_variant { - try!(variant.to_css(dest)); - try!(write!(dest, " ")); - } - - if let DeclaredValue::Value(ref weight) = *self.font_weight { - try!(weight.to_css(dest)); - try!(write!(dest, " ")); - } - - if let DeclaredValue::Value(ref stretch) = *self.font_stretch { - try!(stretch.to_css(dest)); - try!(write!(dest, " ")); - } - - try!(self.font_size.to_css(dest)); - if let DeclaredValue::Value(ref height) = *self.line_height { - match *height { - line_height::SpecifiedValue::Normal => {}, - _ => { - try!(write!(dest, "/")); - try!(height.to_css(dest)); - } + self.font_size.to_css(dest)?; + match *self.line_height { + line_height::SpecifiedValue::Normal => {}, + _ => { + dest.write_str("/")?; + self.line_height.to_css(dest)?; } } - try!(write!(dest, " ")); - + dest.write_str(" ")?; self.font_family.to_css(dest) } } diff --git a/components/style/properties/shorthand/inherited_svg.mako.rs b/components/style/properties/shorthand/inherited_svg.mako.rs index 14a5de0cfdf..e33aa3bac16 100644 --- a/components/style/properties/shorthand/inherited_svg.mako.rs +++ b/components/style/properties/shorthand/inherited_svg.mako.rs @@ -20,18 +20,13 @@ }) } - impl<'a> LonghandsToSerialize<'a> { - fn to_css_declared(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - if let DeclaredValue::Value(ref start) = *self.marker_start { - if let DeclaredValue::Value(ref mid) = *self.marker_mid { - if let DeclaredValue::Value(ref end) = *self.marker_end { - if start == mid && mid == end { - start.to_css(dest)?; - } - } - } + impl<'a> ToCss for LonghandsToSerialize<'a> { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + if self.marker_start == self.marker_mid && self.marker_mid == self.marker_end { + self.marker_start.to_css(dest) + } else { + Ok(()) } - Ok(()) } } diff --git a/components/style/properties/shorthand/inherited_text.mako.rs b/components/style/properties/shorthand/inherited_text.mako.rs index 3012f21b7e3..af94643bc3c 100644 --- a/components/style/properties/shorthand/inherited_text.mako.rs +++ b/components/style/properties/shorthand/inherited_text.mako.rs @@ -38,21 +38,11 @@ } } - impl<'a> LonghandsToSerialize<'a> { - fn to_css_declared(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - let mut style_present = false; - if let DeclaredValue::Value(ref value) = *self.text_emphasis_style { - style_present = true; - try!(value.to_css(dest)); - } - - if let DeclaredValue::Value(ref color) = *self.text_emphasis_color { - if style_present { - try!(write!(dest, " ")); - } - try!(color.to_css(dest)); - } - Ok(()) + impl<'a> ToCss for LonghandsToSerialize<'a> { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + self.text_emphasis_style.to_css(dest)?; + dest.write_str(" ")?; + self.text_emphasis_color.to_css(dest) } } @@ -96,22 +86,11 @@ } } - impl<'a> LonghandsToSerialize<'a> { - fn to_css_declared(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - let mut style_present = false; - if let DeclaredValue::Value(ref width) = *self._webkit_text_stroke_width { - style_present = true; - try!(width.to_css(dest)); - } - - if let DeclaredValue::Value(ref color) = *self._webkit_text_stroke_color { - if style_present { - try!(write!(dest, " ")); - } - try!(color.to_css(dest)); - } - - Ok(()) + impl<'a> ToCss for LonghandsToSerialize<'a> { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + self._webkit_text_stroke_width.to_css(dest)?; + dest.write_str(" ")?; + self._webkit_text_stroke_color.to_css(dest) } } diff --git a/components/style/properties/shorthand/list.mako.rs b/components/style/properties/shorthand/list.mako.rs index 6f1c8707fe0..cd8cc0775dd 100644 --- a/components/style/properties/shorthand/list.mako.rs +++ b/components/style/properties/shorthand/list.mako.rs @@ -96,26 +96,13 @@ } } - impl<'a> LonghandsToSerialize<'a> { - fn to_css_declared(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - match *self.list_style_position { - DeclaredValue::Initial => try!(write!(dest, "outside")), - _ => try!(self.list_style_position.to_css(dest)) - } - - try!(write!(dest, " ")); - - match *self.list_style_image { - DeclaredValue::Initial => try!(write!(dest, "none")), - _ => try!(self.list_style_image.to_css(dest)) - }; - - try!(write!(dest, " ")); - - match *self.list_style_type { - DeclaredValue::Initial => write!(dest, "disc"), - _ => self.list_style_type.to_css(dest) - } + impl<'a> ToCss for LonghandsToSerialize<'a> { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + self.list_style_position.to_css(dest)?; + dest.write_str(" ")?; + self.list_style_image.to_css(dest)?; + dest.write_str(" ")?; + self.list_style_type.to_css(dest) } } diff --git a/components/style/properties/shorthand/mask.mako.rs b/components/style/properties/shorthand/mask.mako.rs index 34b4f5308a4..01caeddb9ca 100644 --- a/components/style/properties/shorthand/mask.mako.rs +++ b/components/style/properties/shorthand/mask.mako.rs @@ -120,113 +120,62 @@ }) } - impl<'a> LonghandsToSerialize<'a> { - fn to_css_declared(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - // mako doesn't like ampersands following `<` - fn extract_value(x: &DeclaredValue) -> Option< &T> { - match *x { - DeclaredValue::Value(ref val) => Some(val), - _ => None, - } - } - use std::cmp; - let mut len = 0; - % for name in "image mode position_x position_y size repeat origin clip composite".split(): - len = cmp::max(len, extract_value(self.mask_${name}).map(|i| i.0.len()) - .unwrap_or(0)); - % endfor + impl<'a> ToCss for LonghandsToSerialize<'a> { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + use properties::longhands::mask_origin::single_value::computed_value::T as Origin; + use properties::longhands::mask_clip::single_value::computed_value::T as Clip; - // There should be at least one declared value + let len = self.mask_image.0.len(); if len == 0 { - return dest.write_str("") + return Ok(()); } + % for name in "mode position_x position_y size repeat origin clip composite".split(): + if self.mask_${name}.0.len() != len { + return Ok(()); + } + % endfor for i in 0..len { if i > 0 { - try!(dest.write_str(", ")); + dest.write_str(", ")?; } % for name in "image mode position_x position_y size repeat origin clip composite".split(): - let ${name} = if let DeclaredValue::Value(ref arr) = *self.mask_${name} { - arr.0.get(i % arr.0.len()) - } else { - None - }; + let ${name} = &self.mask_${name}.0[i]; % endfor - if let Some(image) = image { - try!(image.to_css(dest)); - } else { - try!(write!(dest, "none")); - } - - try!(write!(dest, " ")); - - if let Some(mode) = mode { - try!(mode.to_css(dest)); - } else { - try!(write!(dest, "match-source")); - } - - try!(write!(dest, " ")); - - try!(position_x.unwrap_or(&mask_position_x::single_value - ::get_initial_position_value()) - .to_css(dest)); - - try!(write!(dest, " ")); - - try!(position_y.unwrap_or(&mask_position_y::single_value - ::get_initial_position_value()) - .to_css(dest)); - - if let Some(size) = size { - try!(write!(dest, " / ")); - try!(size.to_css(dest)); - } - - try!(write!(dest, " ")); - - if let Some(repeat) = repeat { - try!(repeat.to_css(dest)); - } else { - try!(write!(dest, "repeat")); - } + image.to_css(dest)?; + dest.write_str(" ")?; + mode.to_css(dest)?; + dest.write_str(" ")?; + position_x.to_css(dest)?; + dest.write_str(" ")?; + position_y.to_css(dest)?; + dest.write_str(" / ")?; + size.to_css(dest)?; + dest.write_str(" ")?; + repeat.to_css(dest)?; + dest.write_str(" ")?; match (origin, clip) { - (Some(origin), Some(clip)) => { - use properties::longhands::mask_origin::single_value::computed_value::T as Origin; - use properties::longhands::mask_clip::single_value::computed_value::T as Clip; - - try!(write!(dest, " ")); - - match (origin, clip) { - (&Origin::padding_box, &Clip::padding_box) => { - try!(origin.to_css(dest)); - }, - (&Origin::border_box, &Clip::border_box) => { - try!(origin.to_css(dest)); - }, - (&Origin::content_box, &Clip::content_box) => { - try!(origin.to_css(dest)); - }, - _ => { - try!(origin.to_css(dest)); - try!(write!(dest, " ")); - try!(clip.to_css(dest)); - } - } + (&Origin::padding_box, &Clip::padding_box) => { + try!(origin.to_css(dest)); }, - _ => {} - }; - - try!(write!(dest, " ")); - - if let Some(composite) = composite { - try!(composite.to_css(dest)); - } else { - try!(write!(dest, "add")); + (&Origin::border_box, &Clip::border_box) => { + try!(origin.to_css(dest)); + }, + (&Origin::content_box, &Clip::content_box) => { + try!(origin.to_css(dest)); + }, + _ => { + try!(origin.to_css(dest)); + try!(write!(dest, " ")); + try!(clip.to_css(dest)); + } } + + dest.write_str(" ")?; + composite.to_css(dest)?; } Ok(()) @@ -268,47 +217,16 @@ }) } - impl<'a> LonghandsToSerialize<'a> { - fn to_css_declared(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - // mako doesn't like ampersands following `<` - fn extract_value(x: &DeclaredValue) -> Option< &T> { - match *x { - DeclaredValue::Value(ref val) => Some(val), - _ => None, - } - } - use std::cmp; - let mut len = 0; - % for name in "x y".split(): - len = cmp::max(len, extract_value(self.mask_position_${name}) - .map(|i| i.0.len()) - .unwrap_or(0)); - % endfor - - // There should be at least one declared value - if len == 0 { - return dest.write_str("") + impl<'a> ToCss for LonghandsToSerialize<'a> { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + let len = self.mask_position_x.0.len(); + if len == 0 || self.mask_position_y.0.len() != len { + return Ok(()); } for i in 0..len { - % for name in "x y".split(): - let position_${name} = if let DeclaredValue::Value(ref arr) = - *self.mask_position_${name} { - arr.0.get(i % arr.0.len()) - } else { - None - }; - % endfor - - try!(position_x.unwrap_or(&mask_position_x::single_value - ::get_initial_position_value()) - .to_css(dest)); - - try!(write!(dest, " ")); - - try!(position_y.unwrap_or(&mask_position_y::single_value - ::get_initial_position_value()) - .to_css(dest)); + self.mask_position_x.0[i].to_css(dest)?; + self.mask_position_y.0[i].to_css(dest)?; } Ok(()) diff --git a/components/style/properties/shorthand/outline.mako.rs b/components/style/properties/shorthand/outline.mako.rs index 803a80afff9..25757c28a2d 100644 --- a/components/style/properties/shorthand/outline.mako.rs +++ b/components/style/properties/shorthand/outline.mako.rs @@ -51,23 +51,13 @@ } } - impl<'a> LonghandsToSerialize<'a> { - fn to_css_declared(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + impl<'a> ToCss for LonghandsToSerialize<'a> { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { try!(self.outline_width.to_css(dest)); try!(write!(dest, " ")); - - match *self.outline_style { - DeclaredValue::Initial => try!(write!(dest, "none")), - _ => try!(self.outline_style.to_css(dest)) - }; - - match *self.outline_color { - DeclaredValue::Initial => Ok(()), - _ => { - try!(write!(dest, " ")); - self.outline_color.to_css(dest) - } - } + try!(self.outline_style.to_css(dest)); + try!(write!(dest, " ")); + self.outline_color.to_css(dest) } } @@ -91,8 +81,8 @@ } // TODO: Border radius for the radius shorthand is not implemented correctly yet - impl<'a> LonghandsToSerialize<'a> { - fn to_css_declared(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + impl<'a> ToCss for LonghandsToSerialize<'a> { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { try!(self._moz_outline_radius_topleft.to_css(dest)); try!(write!(dest, " ")); diff --git a/components/style/properties/shorthand/position.mako.rs b/components/style/properties/shorthand/position.mako.rs index 78286951dae..603a810804e 100644 --- a/components/style/properties/shorthand/position.mako.rs +++ b/components/style/properties/shorthand/position.mako.rs @@ -37,19 +37,11 @@ } - impl<'a> LonghandsToSerialize<'a> { - fn to_css_declared(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - match *self.flex_direction { - DeclaredValue::Initial => try!(write!(dest, "row")), - _ => try!(self.flex_direction.to_css(dest)) - }; - - try!(write!(dest, " ")); - - match *self.flex_wrap { - DeclaredValue::Initial => write!(dest, "nowrap"), - _ => self.flex_wrap.to_css(dest) - } + impl<'a> ToCss for LonghandsToSerialize<'a> { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + self.flex_direction.to_css(dest)?; + dest.write_str(" ")?; + self.flex_wrap.to_css(dest) } } @@ -105,8 +97,8 @@ }) } - impl<'a> LonghandsToSerialize<'a> { - fn to_css_declared(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + impl<'a> ToCss for LonghandsToSerialize<'a> { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { try!(self.flex_grow.to_css(dest)); try!(write!(dest, " ")); diff --git a/components/style/properties/shorthand/serialize.mako.rs b/components/style/properties/shorthand/serialize.mako.rs index 660c455f027..5c265f16c9e 100644 --- a/components/style/properties/shorthand/serialize.mako.rs +++ b/components/style/properties/shorthand/serialize.mako.rs @@ -3,7 +3,6 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ use cssparser::Color; -use properties::DeclaredValue; use style_traits::ToCss; use values::specified::{BorderStyle, CSSColor}; use std::fmt; @@ -60,35 +59,16 @@ pub fn serialize_four_sides(dest: &mut W, } fn serialize_directional_border(dest: &mut W, - width: &DeclaredValue, - style: &DeclaredValue, - color: &DeclaredValue) - -> fmt::Result where W: fmt::Write, I: ToCss { - match *width { - DeclaredValue::Value(ref width) => { - try!(width.to_css(dest)); - }, - _ => { - try!(write!(dest, "medium")); - } - }; - - try!(write!(dest, " ")); - - match *style { - DeclaredValue::Value(ref style) => { - try!(style.to_css(dest)); - }, - _ => { - try!(write!(dest, "none")); - } - }; - - match *color { - DeclaredValue::Value(ref color) if color.parsed != Color::CurrentColor => { - try!(write!(dest, " ")); - color.to_css(dest) - }, - _ => Ok(()) + width: &I, + style: &BorderStyle, + color: &CSSColor) + -> fmt::Result where W: fmt::Write, I: ToCss { + width.to_css(dest)?; + dest.write_str(" ")?; + style.to_css(dest)?; + if color.parsed != Color::CurrentColor { + dest.write_str(" ")?; + color.to_css(dest)?; } + Ok(()) } diff --git a/components/style/properties/shorthand/text.mako.rs b/components/style/properties/shorthand/text.mako.rs index 278459a339c..b9bc7013a2c 100644 --- a/components/style/properties/shorthand/text.mako.rs +++ b/components/style/properties/shorthand/text.mako.rs @@ -46,31 +46,15 @@ }) } - impl<'a> LonghandsToSerialize<'a> { - fn to_css_declared(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - match *self.text_decoration_line { - DeclaredValue::Value(ref line) => { - try!(line.to_css(dest)); - }, - _ => { - try!(write!(dest, "none")); - } - }; - - if let DeclaredValue::Value(ref style) = *self.text_decoration_style { - if *style != text_decoration_style::computed_value::T::solid { - try!(write!(dest, " ")); - try!(style.to_css(dest)); - } + impl<'a> ToCss for LonghandsToSerialize<'a> { + fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { + self.text_decoration_line.to_css(dest)?; + dest.write_str(" ")?; + self.text_decoration_style.to_css(dest)?; + if self.text_decoration_color.parsed != CSSParserColor::CurrentColor { + dest.write_str(" ")?; + self.text_decoration_color.to_css(dest)?; } - - if let DeclaredValue::Value(ref color) = *self.text_decoration_color { - if color.parsed != CSSParserColor::CurrentColor { - try!(write!(dest, " ")); - try!(color.to_css(dest)); - } - } - Ok(()) } } diff --git a/tests/unit/style/properties/serialization.rs b/tests/unit/style/properties/serialization.rs index fd16fe3f71b..9e99169c54d 100644 --- a/tests/unit/style/properties/serialization.rs +++ b/tests/unit/style/properties/serialization.rs @@ -7,7 +7,8 @@ use media_queries::CSSErrorReporterTest; use servo_url::ServoUrl; use style::computed_values::display::T::inline_block; use style::parser::ParserContext; -use style::properties::{DeclaredValue, PropertyDeclaration, PropertyDeclarationBlock, Importance, PropertyId}; +use style::properties::{DeclaredValue, PropertyDeclaration}; +use style::properties::{PropertyDeclarationBlock, Importance, PropertyId}; use style::properties::longhands::outline_color::computed_value::T as ComputedColor; use style::properties::parse_property_declaration_list; use style::stylesheets::Origin; @@ -371,33 +372,18 @@ mod shorthand_serialization { assert_eq!(serialization, "border-top: 4px solid rgb(255, 0, 0);"); } - #[test] - fn directional_border_with_no_specified_style_will_show_style_as_none() { - let mut properties = Vec::new(); - - let width = DeclaredValue::Value(BorderWidth::from_length(Length::from_px(4f32))); - let style = DeclaredValue::Initial; - let color = DeclaredValue::Value(CSSColor { - parsed: ComputedColor::RGBA(RGBA::new(255, 0, 0, 255)), - authored: None - }); - - properties.push(PropertyDeclaration::BorderTopWidth(width)); - properties.push(PropertyDeclaration::BorderTopStyle(style)); - properties.push(PropertyDeclaration::BorderTopColor(color)); - - let serialization = shorthand_properties_to_string(properties); - assert_eq!(serialization, "border-top: 4px none rgb(255, 0, 0);"); + fn get_border_property_values() -> (DeclaredValue, + DeclaredValue, + DeclaredValue) { + (DeclaredValue::Value(BorderWidth::from_length(Length::from_px(4f32))), + DeclaredValue::Value(BorderStyle::solid), + DeclaredValue::Value(CSSColor::currentcolor())) } #[test] - fn directional_border_with_no_specified_color_will_not_show_color() { + fn border_top_should_serialize_correctly() { let mut properties = Vec::new(); - - let width = DeclaredValue::Value(BorderWidth::from_length(Length::from_px(4f32))); - let style = DeclaredValue::Value(BorderStyle::solid); - let color = DeclaredValue::Initial; - + let (width, style, color) = get_border_property_values(); properties.push(PropertyDeclaration::BorderTopWidth(width)); properties.push(PropertyDeclaration::BorderTopStyle(style)); properties.push(PropertyDeclaration::BorderTopColor(color)); @@ -409,11 +395,7 @@ mod shorthand_serialization { #[test] fn border_right_should_serialize_correctly() { let mut properties = Vec::new(); - - let width = DeclaredValue::Value(BorderWidth::from_length(Length::from_px(4f32))); - let style = DeclaredValue::Value(BorderStyle::solid); - let color = DeclaredValue::Initial; - + let (width, style, color) = get_border_property_values(); properties.push(PropertyDeclaration::BorderRightWidth(width)); properties.push(PropertyDeclaration::BorderRightStyle(style)); properties.push(PropertyDeclaration::BorderRightColor(color)); @@ -425,11 +407,7 @@ mod shorthand_serialization { #[test] fn border_bottom_should_serialize_correctly() { let mut properties = Vec::new(); - - let width = DeclaredValue::Value(BorderWidth::from_length(Length::from_px(4f32))); - let style = DeclaredValue::Value(BorderStyle::solid); - let color = DeclaredValue::Initial; - + let (width, style, color) = get_border_property_values(); properties.push(PropertyDeclaration::BorderBottomWidth(width)); properties.push(PropertyDeclaration::BorderBottomStyle(style)); properties.push(PropertyDeclaration::BorderBottomColor(color)); @@ -441,11 +419,7 @@ mod shorthand_serialization { #[test] fn border_left_should_serialize_correctly() { let mut properties = Vec::new(); - - let width = DeclaredValue::Value(BorderWidth::from_length(Length::from_px(4f32))); - let style = DeclaredValue::Value(BorderStyle::solid); - let color = DeclaredValue::Initial; - + let (width, style, color) = get_border_property_values(); properties.push(PropertyDeclaration::BorderLeftWidth(width)); properties.push(PropertyDeclaration::BorderLeftStyle(style)); properties.push(PropertyDeclaration::BorderLeftColor(color)); @@ -457,38 +431,23 @@ mod shorthand_serialization { #[test] fn border_should_serialize_correctly() { let mut properties = Vec::new(); + let (width, style, color) = get_border_property_values(); - let top_width = DeclaredValue::Value(BorderWidth::from_length(Length::from_px(4f32))); - let top_style = DeclaredValue::Value(BorderStyle::solid); - let top_color = DeclaredValue::Initial; + properties.push(PropertyDeclaration::BorderTopWidth(width.clone())); + properties.push(PropertyDeclaration::BorderTopStyle(style.clone())); + properties.push(PropertyDeclaration::BorderTopColor(color.clone())); - properties.push(PropertyDeclaration::BorderTopWidth(top_width)); - properties.push(PropertyDeclaration::BorderTopStyle(top_style)); - properties.push(PropertyDeclaration::BorderTopColor(top_color)); + properties.push(PropertyDeclaration::BorderRightWidth(width.clone())); + properties.push(PropertyDeclaration::BorderRightStyle(style.clone())); + properties.push(PropertyDeclaration::BorderRightColor(color.clone())); - let right_width = DeclaredValue::Value(BorderWidth::from_length(Length::from_px(4f32))); - let right_style = DeclaredValue::Value(BorderStyle::solid); - let right_color = DeclaredValue::Initial; + properties.push(PropertyDeclaration::BorderBottomWidth(width.clone())); + properties.push(PropertyDeclaration::BorderBottomStyle(style.clone())); + properties.push(PropertyDeclaration::BorderBottomColor(color.clone())); - properties.push(PropertyDeclaration::BorderRightWidth(right_width)); - properties.push(PropertyDeclaration::BorderRightStyle(right_style)); - properties.push(PropertyDeclaration::BorderRightColor(right_color)); - - let bottom_width = DeclaredValue::Value(BorderWidth::from_length(Length::from_px(4f32))); - let bottom_style = DeclaredValue::Value(BorderStyle::solid); - let bottom_color = DeclaredValue::Initial; - - properties.push(PropertyDeclaration::BorderBottomWidth(bottom_width)); - properties.push(PropertyDeclaration::BorderBottomStyle(bottom_style)); - properties.push(PropertyDeclaration::BorderBottomColor(bottom_color)); - - let left_width = DeclaredValue::Value(BorderWidth::from_length(Length::from_px(4f32))); - let left_style = DeclaredValue::Value(BorderStyle::solid); - let left_color = DeclaredValue::Initial; - - properties.push(PropertyDeclaration::BorderLeftWidth(left_width)); - properties.push(PropertyDeclaration::BorderLeftStyle(left_style)); - properties.push(PropertyDeclaration::BorderLeftColor(left_color)); + properties.push(PropertyDeclaration::BorderLeftWidth(width.clone())); + properties.push(PropertyDeclaration::BorderLeftStyle(style.clone())); + properties.push(PropertyDeclaration::BorderLeftColor(color.clone())); let serialization = shorthand_properties_to_string(properties); assert_eq!(serialization, "border: 4px solid;"); @@ -517,22 +476,6 @@ mod shorthand_serialization { let serialization = shorthand_properties_to_string(properties); assert_eq!(serialization, "list-style: inside url(\"http://servo/test.png\") disc;"); } - - #[test] - fn list_style_should_show_all_properties_even_if_only_one_is_set() { - let mut properties = Vec::new(); - - let position = DeclaredValue::Initial; - let image = DeclaredValue::Initial; - let style_type = DeclaredValue::Value(ListStyleType::disc); - - properties.push(PropertyDeclaration::ListStylePosition(position)); - properties.push(PropertyDeclaration::ListStyleImage(image)); - properties.push(PropertyDeclaration::ListStyleType(style_type)); - - let serialization = shorthand_properties_to_string(properties); - assert_eq!(serialization, "list-style: outside none disc;"); - } } mod outline { @@ -559,40 +502,6 @@ mod shorthand_serialization { assert_eq!(serialization, "outline: 4px solid rgb(255, 0, 0);"); } - #[test] - fn outline_should_not_show_color_if_not_set() { - let mut properties = Vec::new(); - - let width = DeclaredValue::Value(WidthContainer(Length::from_px(4f32))); - let style = DeclaredValue::Value(Either::Second(BorderStyle::solid)); - let color = DeclaredValue::Initial; - - properties.push(PropertyDeclaration::OutlineWidth(width)); - properties.push(PropertyDeclaration::OutlineStyle(style)); - properties.push(PropertyDeclaration::OutlineColor(color)); - - let serialization = shorthand_properties_to_string(properties); - assert_eq!(serialization, "outline: 4px solid;"); - } - - #[test] - fn outline_should_serialize_correctly_when_style_is_not_set() { - let mut properties = Vec::new(); - - let width = DeclaredValue::Value(WidthContainer(Length::from_px(4f32))); - let style = DeclaredValue::Initial; - let color = DeclaredValue::Value(CSSColor { - parsed: ComputedColor::RGBA(RGBA::new(255, 0, 0, 255)), - authored: None - }); - properties.push(PropertyDeclaration::OutlineWidth(width)); - properties.push(PropertyDeclaration::OutlineStyle(style)); - properties.push(PropertyDeclaration::OutlineColor(color)); - - let serialization = shorthand_properties_to_string(properties); - assert_eq!(serialization, "outline: 4px none rgb(255, 0, 0);"); - } - #[test] fn outline_should_serialize_correctly_when_style_is_auto() { let mut properties = Vec::new(); diff --git a/tests/unit/style/stylesheets.rs b/tests/unit/style/stylesheets.rs index f391b7d429f..83166e019e5 100644 --- a/tests/unit/style/stylesheets.rs +++ b/tests/unit/style/stylesheets.rs @@ -17,7 +17,8 @@ use style::error_reporting::ParseErrorReporter; use style::keyframes::{Keyframe, KeyframeSelector, KeyframePercentage}; use style::parser::ParserContextExtraData; use style::properties::Importance; -use style::properties::{PropertyDeclaration, PropertyDeclarationBlock, DeclaredValue, longhands}; +use style::properties::{CSSWideKeyword, PropertyDeclaration, PropertyDeclarationBlock}; +use style::properties::{DeclaredValue, longhands}; use style::properties::longhands::animation_play_state; use style::stylesheets::{Origin, Namespaces}; use style::stylesheets::{Stylesheet, NamespaceRule, CssRule, CssRules, StyleRule, KeyframesRule}; @@ -102,7 +103,8 @@ fn test_parse_stylesheet() { (PropertyDeclaration::Display(DeclaredValue::Value( longhands::display::SpecifiedValue::none)), Importance::Important), - (PropertyDeclaration::Custom(Atom::from("a"), DeclaredValue::Inherit), + (PropertyDeclaration::Custom(Atom::from("a"), + DeclaredValue::CSSWideKeyword(CSSWideKeyword::Inherit)), Importance::Important), ], important_count: 2,