Auto merge of #15411 - canaltinova:property-declaration, r=SimonSapin

Box larger specified values to avoid memmove impact

<!-- Please describe your changes on the following line: -->
Box larger specified values to avoid memmove impact.

---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->
- [X] `./mach build -d` does not report any errors
- [X] `./mach test-tidy` does not report any errors
- [X] These changes fix #15322 (github issue number if applicable).

<!-- Either: -->
- [ ] There are tests for these changes OR
- [ ] These changes do not require tests because _____

<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/15411)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2017-02-09 02:21:36 -08:00 committed by GitHub
commit 5c609213d6
36 changed files with 359 additions and 215 deletions

View file

@ -407,7 +407,7 @@ impl LayoutElementHelpers for LayoutJS<Element> {
if let Some(color) = bgcolor { if let Some(color) = bgcolor {
hints.push(from_declaration( hints.push(from_declaration(
PropertyDeclaration::BackgroundColor(DeclaredValue::Value( PropertyDeclaration::BackgroundColor(DeclaredValue::Value(
CSSColor { parsed: Color::RGBA(color), authored: None })))); Box::new(CSSColor { parsed: Color::RGBA(color), authored: None })))));
} }
let background = if let Some(this) = self.downcast::<HTMLBodyElement>() { let background = if let Some(this) = self.downcast::<HTMLBodyElement>() {
@ -440,10 +440,10 @@ impl LayoutElementHelpers for LayoutJS<Element> {
if let Some(color) = color { if let Some(color) = color {
hints.push(from_declaration( hints.push(from_declaration(
PropertyDeclaration::Color(DeclaredValue::Value(CSSRGBA { PropertyDeclaration::Color(DeclaredValue::Value(Box::new(CSSRGBA {
parsed: color, parsed: color,
authored: None, authored: None,
})))); })))));
} }
let font_family = if let Some(this) = self.downcast::<HTMLFontElement>() { let font_family = if let Some(this) = self.downcast::<HTMLFontElement>() {
@ -480,10 +480,10 @@ impl LayoutElementHelpers for LayoutJS<Element> {
let width_value = specified::Length::from_px(cellspacing as f32); let width_value = specified::Length::from_px(cellspacing as f32);
hints.push(from_declaration( hints.push(from_declaration(
PropertyDeclaration::BorderSpacing(DeclaredValue::Value( PropertyDeclaration::BorderSpacing(DeclaredValue::Value(
border_spacing::SpecifiedValue { Box::new(border_spacing::SpecifiedValue {
horizontal: width_value.clone(), horizontal: width_value.clone(),
vertical: width_value, vertical: width_value,
})))); })))));
} }

View file

@ -8,7 +8,7 @@
use Atom; use Atom;
use cssparser::{Delimiter, Parser, SourcePosition, Token, TokenSerializationType}; use cssparser::{Delimiter, Parser, SourcePosition, Token, TokenSerializationType};
use parser::{Parse, ParserContext}; use parser::ParserContext;
use properties::DeclaredValue; use properties::DeclaredValue;
use std::ascii::AsciiExt; use std::ascii::AsciiExt;
use std::borrow::Cow; use std::borrow::Cow;
@ -129,16 +129,17 @@ impl ComputedValue {
} }
} }
impl Parse for SpecifiedValue { impl SpecifiedValue {
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> { /// Parse a custom property SpecifiedValue.
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Box<Self>, ()> {
let mut references = Some(HashSet::new()); let mut references = Some(HashSet::new());
let (first, css, last) = try!(parse_self_contained_declaration_value(input, &mut references)); let (first, css, last) = try!(parse_self_contained_declaration_value(input, &mut references));
Ok(SpecifiedValue { Ok(Box::new(SpecifiedValue {
css: css.into_owned(), css: css.into_owned(),
first_token_type: first, first_token_type: first,
last_token_type: last, last_token_type: last,
references: references.unwrap(), references: references.unwrap(),
}) }))
} }
} }
@ -328,7 +329,7 @@ pub fn cascade<'a>(custom_properties: &mut Option<HashMap<&'a Name, BorrowedSpec
inherited: &'a Option<Arc<HashMap<Name, ComputedValue>>>, inherited: &'a Option<Arc<HashMap<Name, ComputedValue>>>,
seen: &mut HashSet<&'a Name>, seen: &mut HashSet<&'a Name>,
name: &'a Name, name: &'a Name,
specified_value: &'a DeclaredValue<SpecifiedValue>) { specified_value: &'a DeclaredValue<Box<SpecifiedValue>>) {
let was_already_present = !seen.insert(name); let was_already_present = !seen.insert(name);
if was_already_present { if was_already_present {
return; return;
@ -360,7 +361,7 @@ pub fn cascade<'a>(custom_properties: &mut Option<HashMap<&'a Name, BorrowedSpec
references: Some(&specified_value.references), references: Some(&specified_value.references),
}); });
}, },
DeclaredValue::WithVariables { .. } => unreachable!(), DeclaredValue::WithVariables(_) => unreachable!(),
DeclaredValue::Initial => { DeclaredValue::Initial => {
map.remove(&name); map.remove(&name);
} }

View file

@ -96,7 +96,7 @@ class Longhand(object):
predefined_type=None, custom_cascade=False, experimental=False, internal=False, predefined_type=None, custom_cascade=False, experimental=False, internal=False,
need_clone=False, need_index=False, gecko_ffi_name=None, depend_on_viewport_size=False, need_clone=False, need_index=False, gecko_ffi_name=None, depend_on_viewport_size=False,
allowed_in_keyframe_block=True, complex_color=False, cast_type='u8', allowed_in_keyframe_block=True, complex_color=False, cast_type='u8',
has_uncacheable_values=False, logical=False, alias=None, extra_prefixes=None): has_uncacheable_values=False, logical=False, alias=None, extra_prefixes=None, boxed=False):
self.name = name self.name = name
if not spec: if not spec:
raise TypeError("Spec should be specified for %s" % name) raise TypeError("Spec should be specified for %s" % name)
@ -119,6 +119,7 @@ class Longhand(object):
self.logical = arg_to_bool(logical) self.logical = arg_to_bool(logical)
self.alias = alias.split() if alias else [] self.alias = alias.split() if alias else []
self.extra_prefixes = extra_prefixes.split() if extra_prefixes else [] self.extra_prefixes = extra_prefixes.split() if extra_prefixes else []
self.boxed = arg_to_bool(boxed)
# https://drafts.csswg.org/css-animations/#keyframes # https://drafts.csswg.org/css-animations/#keyframes
# > The <declaration-list> inside of <keyframe-block> accepts any CSS property # > The <declaration-list> inside of <keyframe-block> accepts any CSS property

View file

@ -168,8 +168,16 @@ impl ComputedValues {
PropertyDeclarationBlock { PropertyDeclarationBlock {
declarations: vec![ declarations: vec![
(PropertyDeclaration::${prop.camel_case}(DeclaredValue::Value( (PropertyDeclaration::${prop.camel_case}(DeclaredValue::Value(
% if prop.boxed:
Box::new(
% endif
longhands::${prop.ident}::SpecifiedValue::from_computed_value( longhands::${prop.ident}::SpecifiedValue::from_computed_value(
&self.get_${prop.style_struct.ident.strip("_")}().clone_${prop.ident}()))), &self.get_${prop.style_struct.ident.strip("_")}().clone_${prop.ident}())
% if prop.boxed:
)
% endif
)),
Importance::Normal) Importance::Normal)
], ],
important_count: 0 important_count: 0

View file

@ -9,8 +9,13 @@
${caller.body()} ${caller.body()}
% if not data.longhands_by_name[name].derived_from: % if not data.longhands_by_name[name].derived_from:
pub fn parse_specified(context: &ParserContext, input: &mut Parser) pub fn parse_specified(context: &ParserContext, input: &mut Parser)
% if data.longhands_by_name[name].boxed:
-> Result<DeclaredValue<Box<SpecifiedValue>>, ()> {
parse(context, input).map(|result| DeclaredValue::Value(Box::new(result)))
% else:
-> Result<DeclaredValue<SpecifiedValue>, ()> { -> Result<DeclaredValue<SpecifiedValue>, ()> {
parse(context, input).map(DeclaredValue::Value) parse(context, input).map(DeclaredValue::Value)
% endif
} }
% endif % endif
</%call> </%call>
@ -191,7 +196,7 @@
% if not property.derived_from: % if not property.derived_from:
use cssparser::Parser; use cssparser::Parser;
use parser::{Parse, ParserContext, ParserContextExtraData}; use parser::{Parse, ParserContext, ParserContextExtraData};
use properties::{CSSWideKeyword, DeclaredValue, ShorthandId}; use properties::{CSSWideKeyword, DeclaredValue, UnparsedValue, ShorthandId};
% endif % endif
use values::{Auto, Either, None_, Normal}; use values::{Auto, Either, None_, Normal};
use cascade_info::CascadeInfo; use cascade_info::CascadeInfo;
@ -254,7 +259,7 @@
.set_${property.ident}(computed ${maybe_wm}); .set_${property.ident}(computed ${maybe_wm});
% endif % endif
} }
DeclaredValue::WithVariables { .. } => unreachable!(), DeclaredValue::WithVariables(_) => unreachable!(),
% if not data.current_style_struct.inherited: % if not data.current_style_struct.inherited:
DeclaredValue::Unset | DeclaredValue::Unset |
% endif % endif
@ -298,7 +303,11 @@
} }
% if not property.derived_from: % if not property.derived_from:
pub fn parse_declared(context: &ParserContext, input: &mut Parser) pub fn parse_declared(context: &ParserContext, input: &mut Parser)
% if property.boxed:
-> Result<DeclaredValue<Box<SpecifiedValue>>, ()> {
% else:
-> Result<DeclaredValue<SpecifiedValue>, ()> { -> Result<DeclaredValue<SpecifiedValue>, ()> {
% endif
match input.try(|i| CSSWideKeyword::parse(context, i)) { match input.try(|i| CSSWideKeyword::parse(context, i)) {
Ok(CSSWideKeyword::InheritKeyword) => Ok(DeclaredValue::Inherit), Ok(CSSWideKeyword::InheritKeyword) => Ok(DeclaredValue::Inherit),
Ok(CSSWideKeyword::InitialKeyword) => Ok(DeclaredValue::Initial), Ok(CSSWideKeyword::InitialKeyword) => Ok(DeclaredValue::Initial),
@ -315,12 +324,12 @@
input.reset(start); input.reset(start);
let (first_token_type, css) = try!( let (first_token_type, css) = try!(
::custom_properties::parse_non_custom_with_var(input)); ::custom_properties::parse_non_custom_with_var(input));
return Ok(DeclaredValue::WithVariables { return Ok(DeclaredValue::WithVariables(Box::new(UnparsedValue {
css: css.into_owned(), css: css.into_owned(),
first_token_type: first_token_type, first_token_type: first_token_type,
base_url: context.base_url.clone(), base_url: context.base_url.clone(),
from_shorthand: None, from_shorthand: None,
}) })))
} }
specified specified
} }
@ -333,9 +342,9 @@
<%def name="single_keyword(name, values, vector=False, **kwargs)"> <%def name="single_keyword(name, values, vector=False, **kwargs)">
<%call expr="single_keyword_computed(name, values, vector, **kwargs)"> <%call expr="single_keyword_computed(name, values, vector, **kwargs)">
use values::computed::ComputedValueAsSpecified; use values::computed::ComputedValueAsSpecified;
use values::NoViewportPercentage; use values::HasViewportPercentage;
impl ComputedValueAsSpecified for SpecifiedValue {} impl ComputedValueAsSpecified for SpecifiedValue {}
impl NoViewportPercentage for SpecifiedValue {} no_viewport_percentage!(SpecifiedValue);
</%call> </%call>
</%def> </%def>
@ -412,7 +421,8 @@
#[allow(unused_imports)] #[allow(unused_imports)]
use cssparser::Parser; use cssparser::Parser;
use parser::ParserContext; use parser::ParserContext;
use properties::{longhands, PropertyDeclaration, DeclaredValue, ShorthandId}; use properties::{DeclaredValue, PropertyDeclaration, UnparsedValue};
use properties::{ShorthandId, longhands};
use properties::declaration_block::Importance; use properties::declaration_block::Importance;
use std::fmt; use std::fmt;
use style_traits::ToCss; use style_traits::ToCss;
@ -429,7 +439,13 @@
/// correspond to a shorthand. /// correspond to a shorthand.
pub struct LonghandsToSerialize<'a> { pub struct LonghandsToSerialize<'a> {
% for sub_property in shorthand.sub_properties: % for sub_property in shorthand.sub_properties:
pub ${sub_property.ident}: &'a DeclaredValue<longhands::${sub_property.ident}::SpecifiedValue>, % if sub_property.boxed:
pub ${sub_property.ident}:
&'a DeclaredValue<Box<longhands::${sub_property.ident}::SpecifiedValue>>,
% else:
pub ${sub_property.ident}:
&'a DeclaredValue<longhands::${sub_property.ident}::SpecifiedValue>,
% endif
% endfor % endfor
} }
@ -489,7 +505,7 @@
DeclaredValue::Initial => all_flags &= ALL_INITIAL, DeclaredValue::Initial => all_flags &= ALL_INITIAL,
DeclaredValue::Inherit => all_flags &= ALL_INHERIT, DeclaredValue::Inherit => all_flags &= ALL_INHERIT,
DeclaredValue::Unset => all_flags &= ALL_UNSET, DeclaredValue::Unset => all_flags &= ALL_UNSET,
DeclaredValue::WithVariables {..} => with_variables = true, DeclaredValue::WithVariables(_) => with_variables = true,
DeclaredValue::Value(..) => { DeclaredValue::Value(..) => {
all_flags = SerializeFlags::empty(); all_flags = SerializeFlags::empty();
} }
@ -529,7 +545,11 @@
% for sub_property in shorthand.sub_properties: % for sub_property in shorthand.sub_properties:
declarations.push((PropertyDeclaration::${sub_property.camel_case}( declarations.push((PropertyDeclaration::${sub_property.camel_case}(
match value.${sub_property.ident} { match value.${sub_property.ident} {
% if sub_property.boxed:
Some(value) => DeclaredValue::Value(Box::new(value)),
% else:
Some(value) => DeclaredValue::Value(value), Some(value) => DeclaredValue::Value(value),
% endif
None => DeclaredValue::Initial, None => DeclaredValue::Initial,
} }
), Importance::Normal)); ), Importance::Normal));
@ -541,12 +561,12 @@
::custom_properties::parse_non_custom_with_var(input)); ::custom_properties::parse_non_custom_with_var(input));
% for sub_property in shorthand.sub_properties: % for sub_property in shorthand.sub_properties:
declarations.push((PropertyDeclaration::${sub_property.camel_case}( declarations.push((PropertyDeclaration::${sub_property.camel_case}(
DeclaredValue::WithVariables { DeclaredValue::WithVariables(Box::new(UnparsedValue {
css: css.clone().into_owned(), css: css.clone().into_owned(),
first_token_type: first_token_type, first_token_type: first_token_type,
base_url: context.base_url.clone(), base_url: context.base_url.clone(),
from_shorthand: Some(ShorthandId::${shorthand.camel_case}), from_shorthand: Some(ShorthandId::${shorthand.camel_case}),
} }))
), Importance::Normal)); ), Importance::Normal));
% endfor % endfor
Ok(()) Ok(())

View file

@ -278,7 +278,11 @@ impl AnimationValue {
AnimationValue::${prop.camel_case}(ref from) => { AnimationValue::${prop.camel_case}(ref from) => {
PropertyDeclaration::${prop.camel_case}( PropertyDeclaration::${prop.camel_case}(
DeclaredValue::Value( DeclaredValue::Value(
% if prop.boxed:
Box::new(longhands::${prop.ident}::SpecifiedValue::from_computed_value(from))))
% else:
longhands::${prop.ident}::SpecifiedValue::from_computed_value(from))) longhands::${prop.ident}::SpecifiedValue::from_computed_value(from)))
% endif
} }
% endif % endif
% endfor % endfor
@ -293,7 +297,7 @@ impl AnimationValue {
PropertyDeclaration::${prop.camel_case}(ref val) => { PropertyDeclaration::${prop.camel_case}(ref val) => {
let computed = match *val { let computed = match *val {
// https://bugzilla.mozilla.org/show_bug.cgi?id=1326131 // https://bugzilla.mozilla.org/show_bug.cgi?id=1326131
DeclaredValue::WithVariables{..} => unimplemented!(), DeclaredValue::WithVariables(_) => unimplemented!(),
DeclaredValue::Value(ref val) => val.to_computed_value(context), DeclaredValue::Value(ref val) => val.to_computed_value(context),
% if not prop.style_struct.inherited: % if not prop.style_struct.inherited:
DeclaredValue::Unset | DeclaredValue::Unset |

View file

@ -9,15 +9,15 @@
${helpers.predefined_type("background-color", "CSSColor", ${helpers.predefined_type("background-color", "CSSColor",
"::cssparser::Color::RGBA(::cssparser::RGBA { red: 0., green: 0., blue: 0., alpha: 0. }) /* transparent */", "::cssparser::Color::RGBA(::cssparser::RGBA { red: 0., green: 0., blue: 0., alpha: 0. }) /* transparent */",
spec="https://drafts.csswg.org/css-backgrounds/#background-color", spec="https://drafts.csswg.org/css-backgrounds/#background-color",
animatable=True, complex_color=True)} animatable=True, complex_color=True, boxed=True)}
<%helpers:vector_longhand name="background-image" animatable="False" <%helpers:vector_longhand name="background-image" animatable="False"
spec="https://drafts.csswg.org/css-backgrounds/#the-background-image" spec="https://drafts.csswg.org/css-backgrounds/#the-background-image"
has_uncacheable_values="${product == 'gecko'}"> has_uncacheable_values="${product == 'gecko'}">
use std::fmt; use std::fmt;
use style_traits::ToCss; use style_traits::ToCss;
use values::HasViewportPercentage;
use values::specified::Image; use values::specified::Image;
use values::NoViewportPercentage;
pub mod computed_value { pub mod computed_value {
use values::computed; use values::computed;
@ -35,7 +35,7 @@ ${helpers.predefined_type("background-color", "CSSColor",
} }
} }
impl NoViewportPercentage for SpecifiedValue {} no_viewport_percentage!(SpecifiedValue);
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]

View file

@ -20,7 +20,7 @@
"::cssparser::Color::CurrentColor", "::cssparser::Color::CurrentColor",
alias=maybe_moz_logical_alias(product, side, "-moz-border-%s-color"), alias=maybe_moz_logical_alias(product, side, "-moz-border-%s-color"),
spec=maybe_logical_spec(side, "color"), spec=maybe_logical_spec(side, "color"),
animatable=True, logical = side[1])} animatable=True, logical = side[1], boxed=True)}
% endfor % endfor
% for side in ALL_SIDES: % for side in ALL_SIDES:
@ -83,14 +83,14 @@ ${helpers.single_keyword("-moz-float-edge", "content-box margin-box",
spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-float-edge)", spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-float-edge)",
animatable=False)} animatable=False)}
<%helpers:longhand name="border-image-source" products="gecko" animatable="False" <%helpers:longhand name="border-image-source" products="gecko" animatable="False" boxed="True"
spec="https://drafts.csswg.org/css-backgrounds/#border-image-source"> spec="https://drafts.csswg.org/css-backgrounds/#border-image-source">
use std::fmt; use std::fmt;
use style_traits::ToCss; use style_traits::ToCss;
use values::NoViewportPercentage; use values::HasViewportPercentage;
use values::specified::Image; use values::specified::Image;
impl NoViewportPercentage for SpecifiedValue {} no_viewport_percentage!(SpecifiedValue);
pub mod computed_value { pub mod computed_value {
use values::computed; use values::computed;
@ -279,9 +279,9 @@ ${helpers.single_keyword("-moz-float-edge", "content-box margin-box",
spec="https://drafts.csswg.org/css-backgrounds/#border-image-repeat"> spec="https://drafts.csswg.org/css-backgrounds/#border-image-repeat">
use std::fmt; use std::fmt;
use style_traits::ToCss; use style_traits::ToCss;
use values::NoViewportPercentage; use values::HasViewportPercentage;
impl NoViewportPercentage for SpecifiedValue {} no_viewport_percentage!(SpecifiedValue);
pub mod computed_value { pub mod computed_value {
pub use super::RepeatKeyword; pub use super::RepeatKeyword;
@ -557,10 +557,10 @@ ${helpers.single_keyword("-moz-float-edge", "content-box margin-box",
spec="https://drafts.csswg.org/css-backgrounds/#border-image-slice"> spec="https://drafts.csswg.org/css-backgrounds/#border-image-slice">
use std::fmt; use std::fmt;
use style_traits::ToCss; use style_traits::ToCss;
use values::NoViewportPercentage; use values::HasViewportPercentage;
use values::specified::{Number, Percentage}; use values::specified::{Number, Percentage};
impl NoViewportPercentage for SpecifiedValue {} no_viewport_percentage!(SpecifiedValue);
pub mod computed_value { pub mod computed_value {
use values::computed::Number; use values::computed::Number;

View file

@ -31,8 +31,8 @@
%> %>
use values::computed::ComputedValueAsSpecified; use values::computed::ComputedValueAsSpecified;
use style_traits::ToCss; use style_traits::ToCss;
use values::NoViewportPercentage; use values::HasViewportPercentage;
impl NoViewportPercentage for SpecifiedValue {} no_viewport_percentage!(SpecifiedValue);
pub mod computed_value { pub mod computed_value {
pub use super::SpecifiedValue as T; pub use super::SpecifiedValue as T;
@ -113,8 +113,8 @@ ${helpers.single_keyword("-moz-top-layer", "none top",
} }
} }
use values::NoViewportPercentage; use values::HasViewportPercentage;
impl NoViewportPercentage for SpecifiedValue {} no_viewport_percentage!(SpecifiedValue);
impl ToComputedValue for SpecifiedValue { impl ToComputedValue for SpecifiedValue {
type ComputedValue = computed_value::T; type ComputedValue = computed_value::T;
@ -152,8 +152,8 @@ ${helpers.single_keyword("-moz-top-layer", "none top",
gecko_inexhaustive="True" gecko_inexhaustive="True"
gecko_ffi_name="mFloat" gecko_ffi_name="mFloat"
spec="https://drafts.csswg.org/css-box/#propdef-float"> spec="https://drafts.csswg.org/css-box/#propdef-float">
use values::NoViewportPercentage; use values::HasViewportPercentage;
impl NoViewportPercentage for SpecifiedValue {} no_viewport_percentage!(SpecifiedValue);
impl ToComputedValue for SpecifiedValue { impl ToComputedValue for SpecifiedValue {
type ComputedValue = computed_value::T; type ComputedValue = computed_value::T;
@ -194,8 +194,8 @@ ${helpers.single_keyword("-moz-top-layer", "none top",
gecko_enum_prefix="StyleClear" gecko_enum_prefix="StyleClear"
gecko_ffi_name="mBreakType" gecko_ffi_name="mBreakType"
spec="https://www.w3.org/TR/CSS2/visuren.html#flow-control"> spec="https://www.w3.org/TR/CSS2/visuren.html#flow-control">
use values::NoViewportPercentage; use values::HasViewportPercentage;
impl NoViewportPercentage for SpecifiedValue {} no_viewport_percentage!(SpecifiedValue);
impl ToComputedValue for SpecifiedValue { impl ToComputedValue for SpecifiedValue {
type ComputedValue = computed_value::T; type ComputedValue = computed_value::T;
@ -396,9 +396,9 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
use std::fmt; use std::fmt;
use style_traits::ToCss; use style_traits::ToCss;
use values::computed::ComputedValueAsSpecified; use values::computed::ComputedValueAsSpecified;
use values::NoViewportPercentage; use values::HasViewportPercentage;
impl NoViewportPercentage for SpecifiedValue {} no_viewport_percentage!(SpecifiedValue);
impl ToCss for SpecifiedValue { impl ToCss for SpecifiedValue {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
@ -442,8 +442,8 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
use values::specified::Time; use values::specified::Time;
pub use values::specified::Time as SpecifiedValue; pub use values::specified::Time as SpecifiedValue;
use values::NoViewportPercentage; use values::HasViewportPercentage;
impl NoViewportPercentage for SpecifiedValue {} no_viewport_percentage!(SpecifiedValue);
pub mod computed_value { pub mod computed_value {
pub use values::computed::Time as T; pub use values::computed::Time as T;
@ -703,8 +703,8 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
} }
} }
use values::NoViewportPercentage; use values::HasViewportPercentage;
impl NoViewportPercentage for SpecifiedValue {} no_viewport_percentage!(SpecifiedValue);
#[inline] #[inline]
pub fn get_initial_value() -> computed_value::T { pub fn get_initial_value() -> computed_value::T {
@ -745,8 +745,8 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
SpecifiedValue::parse(input) SpecifiedValue::parse(input)
} }
use values::NoViewportPercentage; use values::HasViewportPercentage;
impl NoViewportPercentage for SpecifiedValue {} no_viewport_percentage!(SpecifiedValue);
impl ComputedValueAsSpecified for SpecifiedValue { } impl ComputedValueAsSpecified for SpecifiedValue { }
</%helpers:vector_longhand> </%helpers:vector_longhand>
@ -773,7 +773,7 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
use std::ops::Deref; use std::ops::Deref;
use style_traits::ToCss; use style_traits::ToCss;
use values::computed::ComputedValueAsSpecified; use values::computed::ComputedValueAsSpecified;
use values::NoViewportPercentage; use values::HasViewportPercentage;
pub mod computed_value { pub mod computed_value {
pub use super::SpecifiedValue as T; pub use super::SpecifiedValue as T;
@ -805,7 +805,7 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
}) })
} }
} }
impl NoViewportPercentage for SpecifiedValue {} no_viewport_percentage!(SpecifiedValue);
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> { pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
SpecifiedValue::parse(context, input) SpecifiedValue::parse(context, input)
@ -847,7 +847,7 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
use std::fmt; use std::fmt;
use style_traits::ToCss; use style_traits::ToCss;
use values::computed::ComputedValueAsSpecified; use values::computed::ComputedValueAsSpecified;
use values::NoViewportPercentage; use values::HasViewportPercentage;
pub mod computed_value { pub mod computed_value {
pub use super::SpecifiedValue as T; pub use super::SpecifiedValue as T;
@ -885,7 +885,7 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
} }
} }
impl NoViewportPercentage for SpecifiedValue {} no_viewport_percentage!(SpecifiedValue);
#[inline] #[inline]
pub fn get_initial_value() -> computed_value::T { pub fn get_initial_value() -> computed_value::T {
@ -1755,7 +1755,7 @@ ${helpers.single_keyword("transform-style",
extra_prefixes="moz webkit", extra_prefixes="moz webkit",
animatable=False)} animatable=False)}
<%helpers:longhand name="transform-origin" animatable="True" extra_prefixes="moz webkit" <%helpers:longhand name="transform-origin" animatable="True" extra_prefixes="moz webkit" boxed="True"
spec="https://drafts.csswg.org/css-transforms/#transform-origin-property"> spec="https://drafts.csswg.org/css-transforms/#transform-origin-property">
use app_units::Au; use app_units::Au;
use std::fmt; use std::fmt;
@ -1896,7 +1896,8 @@ ${helpers.predefined_type("-moz-binding", "UrlOrNone", "Either::Second(None_)",
products="gecko", products="gecko",
animatable="False", animatable="False",
spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-binding)", spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-binding)",
disable_when_testing="True")} disable_when_testing="True",
boxed=True)}
${helpers.single_keyword("-moz-orient", ${helpers.single_keyword("-moz-orient",
"inline block horizontal vertical", "inline block horizontal vertical",

View file

@ -6,7 +6,7 @@
<% data.new_style_struct("Color", inherited=True) %> <% data.new_style_struct("Color", inherited=True) %>
<%helpers:raw_longhand name="color" need_clone="True" animatable="True" <%helpers:raw_longhand name="color" need_clone="True" animatable="True" boxed="True"
spec="https://drafts.csswg.org/css-color/#color"> spec="https://drafts.csswg.org/css-color/#color">
use cssparser::Color as CSSParserColor; use cssparser::Color as CSSParserColor;
use cssparser::RGBA; use cssparser::RGBA;
@ -39,15 +39,15 @@
RGBA { red: 0., green: 0., blue: 0., alpha: 1. } /* black */ RGBA { red: 0., green: 0., blue: 0., alpha: 1. } /* black */
} }
pub fn parse_specified(context: &ParserContext, input: &mut Parser) pub fn parse_specified(context: &ParserContext, input: &mut Parser)
-> Result<DeclaredValue<SpecifiedValue>, ()> { -> Result<DeclaredValue<Box<SpecifiedValue>>, ()> {
let value = try!(CSSColor::parse(context, input)); let value = try!(CSSColor::parse(context, input));
let rgba = match value.parsed { let rgba = match value.parsed {
CSSParserColor::RGBA(rgba) => rgba, CSSParserColor::RGBA(rgba) => rgba,
CSSParserColor::CurrentColor => return Ok(DeclaredValue::Inherit) CSSParserColor::CurrentColor => return Ok(DeclaredValue::Inherit)
}; };
Ok(DeclaredValue::Value(CSSRGBA { Ok(DeclaredValue::Value(Box::new(CSSRGBA {
parsed: rgba, parsed: rgba,
authored: value.authored, authored: value.authored,
})) })))
} }
</%helpers:raw_longhand> </%helpers:raw_longhand>

View file

@ -22,9 +22,9 @@ ${helpers.predefined_type("column-width",
spec="https://drafts.csswg.org/css-multicol/#propdef-column-count"> spec="https://drafts.csswg.org/css-multicol/#propdef-column-count">
use std::fmt; use std::fmt;
use style_traits::ToCss; use style_traits::ToCss;
use values::NoViewportPercentage; use values::HasViewportPercentage;
impl NoViewportPercentage for SpecifiedValue {} no_viewport_percentage!(SpecifiedValue);
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Clone, Copy, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
@ -147,7 +147,7 @@ ${helpers.single_keyword("column-fill", "auto balance", extra_prefixes="moz",
${helpers.predefined_type("column-rule-color", "CSSColor", ${helpers.predefined_type("column-rule-color", "CSSColor",
"::cssparser::Color::CurrentColor", "::cssparser::Color::CurrentColor",
products="gecko", animatable=True, extra_prefixes="moz", products="gecko", animatable=True, extra_prefixes="moz",
complex_color=True, need_clone=True, complex_color=True, need_clone=True, boxed=True,
spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-color")} spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-color")}
// It's not implemented in servo or gecko yet. // It's not implemented in servo or gecko yet.

View file

@ -10,7 +10,7 @@
use cssparser::Token; use cssparser::Token;
use std::ascii::AsciiExt; use std::ascii::AsciiExt;
use values::computed::ComputedValueAsSpecified; use values::computed::ComputedValueAsSpecified;
use values::NoViewportPercentage; use values::HasViewportPercentage;
use super::list_style_type; use super::list_style_type;
@ -18,7 +18,7 @@
pub use self::computed_value::ContentItem; pub use self::computed_value::ContentItem;
impl ComputedValueAsSpecified for SpecifiedValue {} impl ComputedValueAsSpecified for SpecifiedValue {}
impl NoViewportPercentage for SpecifiedValue {} no_viewport_percentage!(SpecifiedValue);
pub mod computed_value { pub mod computed_value {
use super::super::list_style_type; use super::super::list_style_type;
@ -179,7 +179,7 @@
use std::fmt; use std::fmt;
use style_traits::ToCss; use style_traits::ToCss;
use super::content; use super::content;
use values::NoViewportPercentage; use values::HasViewportPercentage;
use values::computed::ComputedValueAsSpecified; use values::computed::ComputedValueAsSpecified;
use cssparser::{Token, serialize_identifier}; use cssparser::{Token, serialize_identifier};
@ -199,7 +199,7 @@
} }
impl ComputedValueAsSpecified for SpecifiedValue {} impl ComputedValueAsSpecified for SpecifiedValue {}
impl NoViewportPercentage for SpecifiedValue {} no_viewport_percentage!(SpecifiedValue);
impl ToCss for SpecifiedValue { impl ToCss for SpecifiedValue {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {

View file

@ -77,7 +77,7 @@ ${helpers.predefined_type("opacity",
</%helpers:vector_longhand> </%helpers:vector_longhand>
// FIXME: This prop should be animatable // FIXME: This prop should be animatable
<%helpers:longhand name="clip" products="servo" animatable="False" <%helpers:longhand name="clip" products="servo" animatable="False" boxed="True"
spec="https://drafts.fxtf.org/css-masking/#clip-property"> spec="https://drafts.fxtf.org/css-masking/#clip-property">
use std::fmt; use std::fmt;
use style_traits::ToCss; use style_traits::ToCss;

View file

@ -11,12 +11,12 @@
<%helpers:longhand name="font-family" animatable="False" need_index="True" <%helpers:longhand name="font-family" animatable="False" need_index="True"
spec="https://drafts.csswg.org/css-fonts/#propdef-font-family"> spec="https://drafts.csswg.org/css-fonts/#propdef-font-family">
use self::computed_value::{FontFamily, FamilyName}; use self::computed_value::{FontFamily, FamilyName};
use values::NoViewportPercentage; use values::HasViewportPercentage;
use values::computed::ComputedValueAsSpecified; use values::computed::ComputedValueAsSpecified;
pub use self::computed_value::T as SpecifiedValue; pub use self::computed_value::T as SpecifiedValue;
impl ComputedValueAsSpecified for SpecifiedValue {} impl ComputedValueAsSpecified for SpecifiedValue {}
impl NoViewportPercentage for SpecifiedValue {} no_viewport_percentage!(SpecifiedValue);
pub mod computed_value { pub mod computed_value {
use cssparser::CssStringWriter; use cssparser::CssStringWriter;
@ -223,9 +223,9 @@ ${helpers.single_keyword("font-variant-caps",
spec="https://drafts.csswg.org/css-fonts/#propdef-font-weight"> spec="https://drafts.csswg.org/css-fonts/#propdef-font-weight">
use std::fmt; use std::fmt;
use style_traits::ToCss; use style_traits::ToCss;
use values::NoViewportPercentage; use values::HasViewportPercentage;
impl NoViewportPercentage for SpecifiedValue {} no_viewport_percentage!(SpecifiedValue);
#[derive(Debug, Clone, PartialEq, Eq, Copy)] #[derive(Debug, Clone, PartialEq, Eq, Copy)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
@ -458,12 +458,12 @@ ${helpers.single_keyword("font-variant-caps",
<%helpers:longhand products="gecko" name="font-size-adjust" animatable="True" <%helpers:longhand products="gecko" name="font-size-adjust" animatable="True"
spec="https://drafts.csswg.org/css-fonts/#propdef-font-size-adjust"> spec="https://drafts.csswg.org/css-fonts/#propdef-font-size-adjust">
use values::NoViewportPercentage; use values::HasViewportPercentage;
use values::computed::ComputedValueAsSpecified; use values::computed::ComputedValueAsSpecified;
use values::specified::Number; use values::specified::Number;
impl ComputedValueAsSpecified for SpecifiedValue {} impl ComputedValueAsSpecified for SpecifiedValue {}
impl NoViewportPercentage for SpecifiedValue {} no_viewport_percentage!(SpecifiedValue);
#[derive(Copy, Clone, Debug, PartialEq)] #[derive(Copy, Clone, Debug, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
@ -520,11 +520,11 @@ ${helpers.single_keyword("font-variant-caps",
spec="https://drafts.csswg.org/css-fonts/#propdef-font-synthesis"> spec="https://drafts.csswg.org/css-fonts/#propdef-font-synthesis">
use std::fmt; use std::fmt;
use style_traits::ToCss; use style_traits::ToCss;
use values::NoViewportPercentage; use values::HasViewportPercentage;
use values::computed::ComputedValueAsSpecified; use values::computed::ComputedValueAsSpecified;
impl ComputedValueAsSpecified for SpecifiedValue {} impl ComputedValueAsSpecified for SpecifiedValue {}
impl NoViewportPercentage for SpecifiedValue {} no_viewport_percentage!(SpecifiedValue);
pub mod computed_value { pub mod computed_value {
pub use super::SpecifiedValue as T; pub use super::SpecifiedValue as T;
@ -610,12 +610,12 @@ ${helpers.single_keyword("font-variant-position",
spec="https://drafts.csswg.org/css-fonts/#propdef-font-feature-settings"> spec="https://drafts.csswg.org/css-fonts/#propdef-font-feature-settings">
use std::fmt; use std::fmt;
use style_traits::ToCss; use style_traits::ToCss;
use values::NoViewportPercentage; use values::HasViewportPercentage;
use values::computed::ComputedValueAsSpecified; use values::computed::ComputedValueAsSpecified;
pub use self::computed_value::T as SpecifiedValue; pub use self::computed_value::T as SpecifiedValue;
impl ComputedValueAsSpecified for SpecifiedValue {} impl ComputedValueAsSpecified for SpecifiedValue {}
impl NoViewportPercentage for SpecifiedValue {} no_viewport_percentage!(SpecifiedValue);
pub mod computed_value { pub mod computed_value {
use cssparser::Parser; use cssparser::Parser;
@ -719,12 +719,12 @@ ${helpers.single_keyword("font-variant-position",
// https://www.w3.org/TR/css-fonts-3/#propdef-font-language-override // https://www.w3.org/TR/css-fonts-3/#propdef-font-language-override
<%helpers:longhand name="font-language-override" products="none" animatable="False" extra_prefixes="moz" <%helpers:longhand name="font-language-override" products="none" animatable="False" extra_prefixes="moz"
spec="https://drafts.csswg.org/css-fonts-3/#propdef-font-language-override"> spec="https://drafts.csswg.org/css-fonts-3/#propdef-font-language-override">
use values::NoViewportPercentage; use values::HasViewportPercentage;
use values::computed::ComputedValueAsSpecified; use values::computed::ComputedValueAsSpecified;
pub use self::computed_value::T as SpecifiedValue; pub use self::computed_value::T as SpecifiedValue;
impl ComputedValueAsSpecified for SpecifiedValue {} impl ComputedValueAsSpecified for SpecifiedValue {}
impl NoViewportPercentage for SpecifiedValue {} no_viewport_percentage!(SpecifiedValue);
pub mod computed_value { pub mod computed_value {
use std::fmt; use std::fmt;

View file

@ -35,8 +35,8 @@ ${helpers.single_keyword("direction", "ltr rtl", need_clone=True, animatable=Fal
animatable="False" animatable="False"
spec="https://drafts.csswg.org/css-writing-modes/#propdef-text-orientation" spec="https://drafts.csswg.org/css-writing-modes/#propdef-text-orientation"
> >
use values::NoViewportPercentage; use values::HasViewportPercentage;
impl NoViewportPercentage for SpecifiedValue {} no_viewport_percentage!(SpecifiedValue);
impl ToComputedValue for SpecifiedValue { impl ToComputedValue for SpecifiedValue {
type ComputedValue = computed_value::T; type ComputedValue = computed_value::T;
@ -91,8 +91,8 @@ ${helpers.single_keyword("image-rendering",
use style_traits::ToCss; use style_traits::ToCss;
use values::specified::Angle; use values::specified::Angle;
use values::NoViewportPercentage; use values::HasViewportPercentage;
impl NoViewportPercentage for SpecifiedValue {} no_viewport_percentage!(SpecifiedValue);
use std::f32::consts::PI; use std::f32::consts::PI;
use values::CSSFloat; use values::CSSFloat;
@ -225,9 +225,9 @@ ${helpers.single_keyword("image-rendering",
use std::fmt; use std::fmt;
use style_traits::ToCss; use style_traits::ToCss;
use values::computed::ComputedValueAsSpecified; use values::computed::ComputedValueAsSpecified;
use values::NoViewportPercentage; use values::HasViewportPercentage;
impl NoViewportPercentage for SpecifiedValue {} no_viewport_percentage!(SpecifiedValue);
#[derive(Copy, Clone, Debug, Eq, PartialEq)] #[derive(Copy, Clone, Debug, Eq, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))] #[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))]

View file

@ -19,7 +19,7 @@ ${helpers.single_keyword("caption-side", "top bottom",
animatable=False, animatable=False,
spec="https://drafts.csswg.org/css-tables/#propdef-caption-side")} spec="https://drafts.csswg.org/css-tables/#propdef-caption-side")}
<%helpers:longhand name="border-spacing" animatable="False" <%helpers:longhand name="border-spacing" animatable="False" boxed="True"
spec="https://drafts.csswg.org/css-tables/#propdef-border-spacing"> spec="https://drafts.csswg.org/css-tables/#propdef-border-spacing">
use app_units::Au; use app_units::Au;
use std::fmt; use std::fmt;

View file

@ -204,9 +204,9 @@ ${helpers.single_keyword("text-align-last",
<%helpers:longhand name="text-align" animatable="False" spec="https://drafts.csswg.org/css-text/#propdef-text-align"> <%helpers:longhand name="text-align" animatable="False" spec="https://drafts.csswg.org/css-text/#propdef-text-align">
pub use self::computed_value::T as SpecifiedValue; pub use self::computed_value::T as SpecifiedValue;
use values::computed::ComputedValueAsSpecified; use values::computed::ComputedValueAsSpecified;
use values::NoViewportPercentage; use values::HasViewportPercentage;
impl ComputedValueAsSpecified for SpecifiedValue {} impl ComputedValueAsSpecified for SpecifiedValue {}
impl NoViewportPercentage for SpecifiedValue {} no_viewport_percentage!(SpecifiedValue);
pub mod computed_value { pub mod computed_value {
use style_traits::ToCss; use style_traits::ToCss;
macro_rules! define_text_align { macro_rules! define_text_align {
@ -429,16 +429,16 @@ ${helpers.single_keyword("text-align-last",
<%helpers:longhand name="-servo-text-decorations-in-effect" <%helpers:longhand name="-servo-text-decorations-in-effect"
derived_from="display text-decoration" derived_from="display text-decoration"
need_clone="True" products="servo" need_clone="True" products="servo"
animatable="False" animatable="False" boxed="True"
spec="Nonstandard (Internal property used by Servo)"> spec="Nonstandard (Internal property used by Servo)">
use cssparser::RGBA; use cssparser::RGBA;
use std::fmt; use std::fmt;
use style_traits::ToCss; use style_traits::ToCss;
use values::NoViewportPercentage; use values::HasViewportPercentage;
use values::computed::ComputedValueAsSpecified; use values::computed::ComputedValueAsSpecified;
impl ComputedValueAsSpecified for SpecifiedValue {} impl ComputedValueAsSpecified for SpecifiedValue {}
impl NoViewportPercentage for SpecifiedValue {} no_viewport_percentage!(SpecifiedValue);
#[derive(Clone, PartialEq, Copy, Debug)] #[derive(Clone, PartialEq, Copy, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
@ -518,9 +518,9 @@ ${helpers.single_keyword("text-align-last",
animatable="False" animatable="False"
spec="https://drafts.csswg.org/css-text/#propdef-white-space"> spec="https://drafts.csswg.org/css-text/#propdef-white-space">
use values::computed::ComputedValueAsSpecified; use values::computed::ComputedValueAsSpecified;
use values::NoViewportPercentage; use values::HasViewportPercentage;
impl ComputedValueAsSpecified for SpecifiedValue {} impl ComputedValueAsSpecified for SpecifiedValue {}
impl NoViewportPercentage for SpecifiedValue {} no_viewport_percentage!(SpecifiedValue);
impl SpecifiedValue { impl SpecifiedValue {
pub fn allow_wrap(&self) -> bool { pub fn allow_wrap(&self) -> bool {
@ -771,9 +771,9 @@ ${helpers.single_keyword("text-align-last",
use std::fmt; use std::fmt;
use style_traits::ToCss; use style_traits::ToCss;
use unicode_segmentation::UnicodeSegmentation; use unicode_segmentation::UnicodeSegmentation;
use values::NoViewportPercentage; use values::HasViewportPercentage;
impl NoViewportPercentage for SpecifiedValue {} no_viewport_percentage!(SpecifiedValue);
pub mod computed_value { pub mod computed_value {
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
@ -977,7 +977,7 @@ ${helpers.single_keyword("text-align-last",
spec="https://drafts.csswg.org/css-text-decor/#propdef-text-emphasis-position"> spec="https://drafts.csswg.org/css-text-decor/#propdef-text-emphasis-position">
use std::fmt; use std::fmt;
use values::computed::ComputedValueAsSpecified; use values::computed::ComputedValueAsSpecified;
use values::NoViewportPercentage; use values::HasViewportPercentage;
use style_traits::ToCss; use style_traits::ToCss;
define_css_keyword_enum!(HorizontalWritingModeValue: define_css_keyword_enum!(HorizontalWritingModeValue:
@ -996,7 +996,7 @@ ${helpers.single_keyword("text-align-last",
} }
impl ComputedValueAsSpecified for SpecifiedValue {} impl ComputedValueAsSpecified for SpecifiedValue {}
impl NoViewportPercentage for SpecifiedValue {} no_viewport_percentage!(SpecifiedValue);
pub fn get_initial_value() -> computed_value::T { pub fn get_initial_value() -> computed_value::T {
SpecifiedValue(HorizontalWritingModeValue::Over, VerticalWritingModeValue::Right) SpecifiedValue(HorizontalWritingModeValue::Over, VerticalWritingModeValue::Right)
@ -1027,6 +1027,7 @@ ${helpers.predefined_type("text-emphasis-color", "CSSColor",
"::cssparser::Color::CurrentColor", "::cssparser::Color::CurrentColor",
products="gecko",animatable=True, products="gecko",animatable=True,
complex_color=True, need_clone=True, complex_color=True, need_clone=True,
boxed=True,
spec="https://drafts.csswg.org/css-text-decor/#propdef-text-emphasis-color")} spec="https://drafts.csswg.org/css-text-decor/#propdef-text-emphasis-color")}
// CSS Compatibility // CSS Compatibility
@ -1035,14 +1036,14 @@ ${helpers.predefined_type(
"-webkit-text-fill-color", "CSSColor", "-webkit-text-fill-color", "CSSColor",
"CSSParserColor::CurrentColor", "CSSParserColor::CurrentColor",
products="gecko", animatable=True, products="gecko", animatable=True,
complex_color=True, need_clone=True, complex_color=True, need_clone=True, boxed=True,
spec="https://compat.spec.whatwg.org/#the-webkit-text-fill-color")} spec="https://compat.spec.whatwg.org/#the-webkit-text-fill-color")}
${helpers.predefined_type( ${helpers.predefined_type(
"-webkit-text-stroke-color", "CSSColor", "-webkit-text-stroke-color", "CSSColor",
"CSSParserColor::CurrentColor", "CSSParserColor::CurrentColor",
products="gecko", animatable=True, products="gecko", animatable=True,
complex_color=True, need_clone=True, complex_color=True, need_clone=True, boxed=True,
spec="https://compat.spec.whatwg.org/#the-webkit-text-stroke-color")} spec="https://compat.spec.whatwg.org/#the-webkit-text-stroke-color")}
<%helpers:longhand products="gecko" name="-webkit-text-stroke-width" animatable="False" <%helpers:longhand products="gecko" name="-webkit-text-stroke-width" animatable="False"

View file

@ -29,7 +29,7 @@ ${helpers.single_keyword("list-style-type", """
spec="https://drafts.csswg.org/css-lists/#propdef-list-style-type")} spec="https://drafts.csswg.org/css-lists/#propdef-list-style-type")}
${helpers.predefined_type("list-style-image", "UrlOrNone", "Either::Second(None_)", ${helpers.predefined_type("list-style-image", "UrlOrNone", "Either::Second(None_)",
animatable="False", animatable=False,
spec="https://drafts.csswg.org/css-lists/#propdef-list-style-image")} spec="https://drafts.csswg.org/css-lists/#propdef-list-style-image")}
<%helpers:longhand name="quotes" animatable="False" <%helpers:longhand name="quotes" animatable="False"
@ -39,7 +39,7 @@ ${helpers.predefined_type("list-style-image", "UrlOrNone", "Either::Second(None_
use std::fmt; use std::fmt;
use style_traits::ToCss; use style_traits::ToCss;
use values::computed::ComputedValueAsSpecified; use values::computed::ComputedValueAsSpecified;
use values::NoViewportPercentage; use values::HasViewportPercentage;
pub use self::computed_value::T as SpecifiedValue; pub use self::computed_value::T as SpecifiedValue;
@ -50,7 +50,7 @@ ${helpers.predefined_type("list-style-image", "UrlOrNone", "Either::Second(None_
} }
impl ComputedValueAsSpecified for SpecifiedValue {} impl ComputedValueAsSpecified for SpecifiedValue {}
impl NoViewportPercentage for SpecifiedValue {} no_viewport_percentage!(SpecifiedValue);
impl ToCss for SpecifiedValue { impl ToCss for SpecifiedValue {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {

View file

@ -11,7 +11,7 @@
// TODO(pcwalton): `invert` // TODO(pcwalton): `invert`
${helpers.predefined_type("outline-color", "CSSColor", "::cssparser::Color::CurrentColor", ${helpers.predefined_type("outline-color", "CSSColor", "::cssparser::Color::CurrentColor",
animatable=True, complex_color=True, need_clone=True, animatable=True, complex_color=True, need_clone=True, boxed=True,
spec="https://drafts.csswg.org/css-ui/#propdef-outline-color")} spec="https://drafts.csswg.org/css-ui/#propdef-outline-color")}
<%helpers:longhand name="outline-style" need_clone="True" animatable="False" <%helpers:longhand name="outline-style" need_clone="True" animatable="False"
@ -20,7 +20,6 @@ ${helpers.predefined_type("outline-color", "CSSColor", "::cssparser::Color::Curr
use std::fmt; use std::fmt;
use style_traits::ToCss; use style_traits::ToCss;
use values::specified::BorderStyle; use values::specified::BorderStyle;
use values::NoViewportPercentage;
use values::computed::ComputedValueAsSpecified; use values::computed::ComputedValueAsSpecified;
pub type SpecifiedValue = Either<Auto, BorderStyle>; pub type SpecifiedValue = Either<Auto, BorderStyle>;

View file

@ -8,12 +8,12 @@
<%helpers:longhand name="cursor" animatable="False" spec="https://drafts.csswg.org/css-ui/#cursor"> <%helpers:longhand name="cursor" animatable="False" spec="https://drafts.csswg.org/css-ui/#cursor">
pub use self::computed_value::T as SpecifiedValue; pub use self::computed_value::T as SpecifiedValue;
use values::NoViewportPercentage; use values::HasViewportPercentage;
use values::computed::ComputedValueAsSpecified; use values::computed::ComputedValueAsSpecified;
use values::specified::url::SpecifiedUrl; use values::specified::url::SpecifiedUrl;
impl ComputedValueAsSpecified for SpecifiedValue {} impl ComputedValueAsSpecified for SpecifiedValue {}
impl NoViewportPercentage for SpecifiedValue {} no_viewport_percentage!(SpecifiedValue);
pub mod computed_value { pub mod computed_value {
use std::fmt; use std::fmt;

View file

@ -24,11 +24,11 @@
% endfor % endfor
<%helpers:longhand name="z-index" spec="https://www.w3.org/TR/CSS2/visuren.html#z-index" animatable="True"> <%helpers:longhand name="z-index" spec="https://www.w3.org/TR/CSS2/visuren.html#z-index" animatable="True">
use values::NoViewportPercentage; use values::HasViewportPercentage;
use values::computed::ComputedValueAsSpecified; use values::computed::ComputedValueAsSpecified;
impl ComputedValueAsSpecified for SpecifiedValue {} impl ComputedValueAsSpecified for SpecifiedValue {}
impl NoViewportPercentage for SpecifiedValue {} no_viewport_percentage!(SpecifiedValue);
pub type SpecifiedValue = computed_value::T; pub type SpecifiedValue = computed_value::T;
pub mod computed_value { pub mod computed_value {
use std::fmt; use std::fmt;
@ -218,5 +218,6 @@ ${helpers.single_keyword("object-fit", "fill contain cover none scale-down",
"Default::default()", "Default::default()",
animatable=False, animatable=False,
spec="https://drafts.csswg.org/css-grid/#propdef-%s" % longhand, spec="https://drafts.csswg.org/css-grid/#propdef-%s" % longhand,
products="gecko")} products="gecko",
boxed=True)}
% endfor % endfor

View file

@ -25,6 +25,7 @@ ${helpers.predefined_type(
"CSSParserColor::RGBA(RGBA { red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0 })", "CSSParserColor::RGBA(RGBA { red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0 })",
products="gecko", products="gecko",
animatable=False, animatable=False,
boxed=True,
spec="https://www.w3.org/TR/SVGTiny12/painting.html#StopColorProperty")} spec="https://www.w3.org/TR/SVGTiny12/painting.html#StopColorProperty")}
${helpers.predefined_type("stop-opacity", "Opacity", "1.0", ${helpers.predefined_type("stop-opacity", "Opacity", "1.0",
@ -39,6 +40,7 @@ ${helpers.predefined_type(
"CSSParserColor::RGBA(RGBA { red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0 })", "CSSParserColor::RGBA(RGBA { red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0 })",
products="gecko", products="gecko",
animatable=False, animatable=False,
boxed=True,
spec="https://www.w3.org/TR/SVG/filters.html#FloodColorProperty")} spec="https://www.w3.org/TR/SVG/filters.html#FloodColorProperty")}
${helpers.predefined_type("flood-opacity", "Opacity", ${helpers.predefined_type("flood-opacity", "Opacity",
@ -50,6 +52,7 @@ ${helpers.predefined_type(
"CSSParserColor::RGBA(RGBA { red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0 })", "CSSParserColor::RGBA(RGBA { red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0 })",
products="gecko", products="gecko",
animatable=False, animatable=False,
boxed=True,
spec="https://www.w3.org/TR/SVG/filters.html#LightingColorProperty")} spec="https://www.w3.org/TR/SVG/filters.html#LightingColorProperty")}
// CSS Masking Module Level 1 // CSS Masking Module Level 1
@ -58,11 +61,11 @@ ${helpers.single_keyword("mask-type", "luminance alpha",
products="gecko", animatable=False, products="gecko", animatable=False,
spec="https://drafts.fxtf.org/css-masking/#propdef-mask-type")} spec="https://drafts.fxtf.org/css-masking/#propdef-mask-type")}
<%helpers:longhand name="clip-path" animatable="False" products="gecko" <%helpers:longhand name="clip-path" animatable="False" products="gecko" boxed="True"
spec="https://drafts.fxtf.org/css-masking/#propdef-clip-path"> spec="https://drafts.fxtf.org/css-masking/#propdef-clip-path">
use std::fmt; use std::fmt;
use style_traits::ToCss; use style_traits::ToCss;
use values::NoViewportPercentage; use values::HasViewportPercentage;
use values::specified::basic_shape::{ShapeSource, GeometryBox}; use values::specified::basic_shape::{ShapeSource, GeometryBox};
pub mod computed_value { pub mod computed_value {
@ -83,7 +86,7 @@ ${helpers.single_keyword("mask-type", "luminance alpha",
ShapeSource::parse(context, input) ShapeSource::parse(context, input)
} }
impl NoViewportPercentage for SpecifiedValue {} no_viewport_percentage!(SpecifiedValue);
</%helpers:longhand> </%helpers:longhand>
${helpers.single_keyword("mask-mode", ${helpers.single_keyword("mask-mode",
@ -196,7 +199,7 @@ ${helpers.single_keyword("mask-composite",
use std::sync::Arc; use std::sync::Arc;
use values::specified::Image; use values::specified::Image;
use values::specified::url::SpecifiedUrl; use values::specified::url::SpecifiedUrl;
use values::NoViewportPercentage; use values::HasViewportPercentage;
pub mod computed_value { pub mod computed_value {
use std::fmt; use std::fmt;
@ -222,7 +225,7 @@ ${helpers.single_keyword("mask-composite",
} }
} }
impl NoViewportPercentage for SpecifiedValue {} no_viewport_percentage!(SpecifiedValue);
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]

View file

@ -12,16 +12,16 @@
Method("has_overline", "bool"), Method("has_overline", "bool"),
Method("has_line_through", "bool")]) %> Method("has_line_through", "bool")]) %>
<%helpers:longhand name="text-overflow" animatable="False" <%helpers:longhand name="text-overflow" animatable="False" boxed="True"
spec="https://drafts.csswg.org/css-ui/#propdef-text-overflow"> spec="https://drafts.csswg.org/css-ui/#propdef-text-overflow">
use std::fmt; use std::fmt;
use style_traits::ToCss; use style_traits::ToCss;
use values::NoViewportPercentage; use values::HasViewportPercentage;
use values::computed::ComputedValueAsSpecified; use values::computed::ComputedValueAsSpecified;
use cssparser; use cssparser;
impl ComputedValueAsSpecified for SpecifiedValue {} impl ComputedValueAsSpecified for SpecifiedValue {}
impl NoViewportPercentage for SpecifiedValue {} no_viewport_percentage!(SpecifiedValue);
#[derive(PartialEq, Eq, Clone, Debug)] #[derive(PartialEq, Eq, Clone, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
@ -108,11 +108,11 @@ ${helpers.single_keyword("unicode-bidi",
spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-line"> spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-line">
use std::fmt; use std::fmt;
use style_traits::ToCss; use style_traits::ToCss;
use values::NoViewportPercentage; use values::HasViewportPercentage;
use values::computed::ComputedValueAsSpecified; use values::computed::ComputedValueAsSpecified;
impl ComputedValueAsSpecified for SpecifiedValue {} impl ComputedValueAsSpecified for SpecifiedValue {}
impl NoViewportPercentage for SpecifiedValue {} no_viewport_percentage!(SpecifiedValue);
#[derive(PartialEq, Eq, Copy, Clone, Debug)] #[derive(PartialEq, Eq, Copy, Clone, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
@ -214,4 +214,5 @@ ${helpers.predefined_type(
complex_color=True, complex_color=True,
products="gecko", products="gecko",
animatable=True, animatable=True,
boxed=True,
spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-color")} spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-color")}

View file

@ -246,23 +246,29 @@ mod property_bit_field {
/// the resulting declared value. /// the resulting declared value.
#[allow(non_snake_case)] #[allow(non_snake_case)]
fn substitute_variables_${property.ident}<F>( fn substitute_variables_${property.ident}<F>(
% if property.boxed:
value: &DeclaredValue<Box<longhands::${property.ident}::SpecifiedValue>>,
% else:
value: &DeclaredValue<longhands::${property.ident}::SpecifiedValue>, value: &DeclaredValue<longhands::${property.ident}::SpecifiedValue>,
% endif
custom_properties: &Option<Arc<::custom_properties::ComputedValuesMap>>, custom_properties: &Option<Arc<::custom_properties::ComputedValuesMap>>,
f: F, f: F,
error_reporter: &mut StdBox<ParseErrorReporter + Send>) error_reporter: &mut StdBox<ParseErrorReporter + Send>)
% if property.boxed:
where F: FnOnce(&DeclaredValue<Box<longhands::${property.ident}::SpecifiedValue>>)
% else:
where F: FnOnce(&DeclaredValue<longhands::${property.ident}::SpecifiedValue>) where F: FnOnce(&DeclaredValue<longhands::${property.ident}::SpecifiedValue>)
% endif
{ {
if let DeclaredValue::WithVariables { if let DeclaredValue::WithVariables(ref with_variables) = *value {
ref css, first_token_type, ref base_url, from_shorthand
} = *value {
// FIXME(heycam): A ParserContextExtraData should be built from data // FIXME(heycam): A ParserContextExtraData should be built from data
// stored in the WithVariables, in case variable expansion results in // stored in the WithVariables, in case variable expansion results in
// a url() value. // a url() value.
let extra_data = ParserContextExtraData::default(); let extra_data = ParserContextExtraData::default();
substitute_variables_${property.ident}_slow(css, substitute_variables_${property.ident}_slow(&with_variables.css,
first_token_type, with_variables.first_token_type,
base_url, &with_variables.base_url,
from_shorthand, with_variables.from_shorthand,
custom_properties, custom_properties,
f, f,
error_reporter, error_reporter,
@ -283,7 +289,11 @@ mod property_bit_field {
f: F, f: F,
error_reporter: &mut StdBox<ParseErrorReporter + Send>, error_reporter: &mut StdBox<ParseErrorReporter + Send>,
extra_data: ParserContextExtraData) extra_data: ParserContextExtraData)
% if property.boxed:
where F: FnOnce(&DeclaredValue<Box<longhands::${property.ident}::SpecifiedValue>>)
% else:
where F: FnOnce(&DeclaredValue<longhands::${property.ident}::SpecifiedValue>) where F: FnOnce(&DeclaredValue<longhands::${property.ident}::SpecifiedValue>)
% endif
{ {
f(& f(&
::custom_properties::substitute(css, first_token_type, custom_properties) ::custom_properties::substitute(css, first_token_type, custom_properties)
@ -305,7 +315,11 @@ mod property_bit_field {
Some(ShorthandId::${shorthand.camel_case}) => { Some(ShorthandId::${shorthand.camel_case}) => {
shorthands::${shorthand.ident}::parse_value(&context, input) shorthands::${shorthand.ident}::parse_value(&context, input)
.map(|result| match result.${property.ident} { .map(|result| match result.${property.ident} {
% if property.boxed:
Some(value) => DeclaredValue::Value(Box::new(value)),
% else:
Some(value) => DeclaredValue::Value(value), Some(value) => DeclaredValue::Value(value),
% endif
None => DeclaredValue::Initial, None => DeclaredValue::Initial,
}) })
} }
@ -598,17 +612,8 @@ impl ShorthandId {
pub enum DeclaredValue<T> { pub enum DeclaredValue<T> {
/// A known specified value from the stylesheet. /// A known specified value from the stylesheet.
Value(T), Value(T),
/// A value that contained any css variables. /// An unparsed value that contains `var()` functions.
WithVariables { WithVariables(Box<UnparsedValue>),
/// The css serialization for this value.
css: String,
/// The first token type for this serialization.
first_token_type: TokenSerializationType,
/// The base url.
base_url: ServoUrl,
/// The shorthand this came from.
from_shorthand: Option<ShorthandId>,
},
/// The `initial` keyword. /// The `initial` keyword.
Initial, Initial,
/// The `inherit` keyword. /// The `inherit` keyword.
@ -617,11 +622,25 @@ pub enum DeclaredValue<T> {
Unset, Unset,
} }
/// An unparsed property value that contains `var()` functions.
#[derive(Clone, PartialEq, Eq, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct UnparsedValue {
/// The css serialization for this value.
css: String,
/// The first token type for this serialization.
first_token_type: TokenSerializationType,
/// The base url.
base_url: ServoUrl,
/// The shorthand this came from.
from_shorthand: Option<ShorthandId>,
}
impl<T: HasViewportPercentage> HasViewportPercentage for DeclaredValue<T> { impl<T: HasViewportPercentage> HasViewportPercentage for DeclaredValue<T> {
fn has_viewport_percentage(&self) -> bool { fn has_viewport_percentage(&self) -> bool {
match *self { match *self {
DeclaredValue::Value(ref v) => v.has_viewport_percentage(), DeclaredValue::Value(ref v) => v.has_viewport_percentage(),
DeclaredValue::WithVariables { .. } => { DeclaredValue::WithVariables(_) => {
panic!("DeclaredValue::has_viewport_percentage without \ panic!("DeclaredValue::has_viewport_percentage without \
resolving variables!") resolving variables!")
}, },
@ -638,11 +657,13 @@ impl<T: ToCss> ToCss for DeclaredValue<T> {
{ {
match *self { match *self {
DeclaredValue::Value(ref inner) => inner.to_css(dest), DeclaredValue::Value(ref inner) => inner.to_css(dest),
DeclaredValue::WithVariables { ref css, from_shorthand: None, .. } => { DeclaredValue::WithVariables(ref with_variables) => {
dest.write_str(css)
}
// https://drafts.csswg.org/css-variables/#variables-in-shorthands // https://drafts.csswg.org/css-variables/#variables-in-shorthands
DeclaredValue::WithVariables { .. } => Ok(()), if with_variables.from_shorthand.is_none() {
dest.write_str(&*with_variables.css)?
}
Ok(())
},
DeclaredValue::Initial => dest.write_str("initial"), DeclaredValue::Initial => dest.write_str("initial"),
DeclaredValue::Inherit => dest.write_str("inherit"), DeclaredValue::Inherit => dest.write_str("inherit"),
DeclaredValue::Unset => dest.write_str("unset"), DeclaredValue::Unset => dest.write_str("unset"),
@ -826,11 +847,15 @@ impl PropertyId {
pub enum PropertyDeclaration { pub enum PropertyDeclaration {
% for property in data.longhands: % for property in data.longhands:
/// ${property.name} /// ${property.name}
% if property.boxed:
${property.camel_case}(DeclaredValue<Box<longhands::${property.ident}::SpecifiedValue>>),
% else:
${property.camel_case}(DeclaredValue<longhands::${property.ident}::SpecifiedValue>), ${property.camel_case}(DeclaredValue<longhands::${property.ident}::SpecifiedValue>),
% endif
% endfor % endfor
/// A custom property declaration, with the property name and the declared /// A custom property declaration, with the property name and the declared
/// value. /// value.
Custom(::custom_properties::Name, DeclaredValue<::custom_properties::SpecifiedValue>), Custom(::custom_properties::Name, DeclaredValue<Box<::custom_properties::SpecifiedValue>>),
} }
impl HasViewportPercentage for PropertyDeclaration { impl HasViewportPercentage for PropertyDeclaration {
@ -939,9 +964,12 @@ impl PropertyDeclaration {
match *self { match *self {
% for property in data.longhands: % for property in data.longhands:
PropertyDeclaration::${property.camel_case}(ref value) => match *value { PropertyDeclaration::${property.camel_case}(ref value) => match *value {
DeclaredValue::WithVariables { ref css, from_shorthand: Some(s), .. } DeclaredValue::WithVariables(ref with_variables) => {
if s == shorthand => { if let Some(s) = with_variables.from_shorthand {
Some(&**css) if s == shorthand {
Some(&*with_variables.css)
} else { None }
} else { None }
} }
_ => None _ => None
}, },
@ -956,12 +984,12 @@ impl PropertyDeclaration {
match *self { match *self {
% for property in data.longhands: % for property in data.longhands:
PropertyDeclaration::${property.camel_case}(ref value) => match *value { PropertyDeclaration::${property.camel_case}(ref value) => match *value {
DeclaredValue::WithVariables { .. } => true, DeclaredValue::WithVariables(_) => true,
_ => false, _ => false,
}, },
% endfor % endfor
PropertyDeclaration::Custom(_, ref value) => match *value { PropertyDeclaration::Custom(_, ref value) => match *value {
DeclaredValue::WithVariables { .. } => true, DeclaredValue::WithVariables(_) => true,
_ => false, _ => false,
} }
} }
@ -977,7 +1005,7 @@ impl PropertyDeclaration {
match *self { match *self {
% for property in data.longhands: % for property in data.longhands:
PropertyDeclaration::${property.camel_case}(ref value) => { PropertyDeclaration::${property.camel_case}(ref value) => {
matches!(*value, DeclaredValue::WithVariables { .. }) matches!(*value, DeclaredValue::WithVariables(_))
}, },
% endfor % endfor
PropertyDeclaration::Custom(..) => true PropertyDeclaration::Custom(..) => true
@ -1009,7 +1037,8 @@ impl PropertyDeclaration {
Err(()) => return PropertyDeclarationParseResult::InvalidValue, Err(()) => return PropertyDeclarationParseResult::InvalidValue,
} }
}; };
result_list.push((PropertyDeclaration::Custom(name, value), Importance::Normal)); result_list.push((PropertyDeclaration::Custom(name, value),
Importance::Normal));
return PropertyDeclarationParseResult::ValidOrIgnoredDeclaration; return PropertyDeclarationParseResult::ValidOrIgnoredDeclaration;
} }
PropertyId::Longhand(id) => match id { PropertyId::Longhand(id) => match id {
@ -2300,3 +2329,18 @@ macro_rules! longhand_properties_idents {
} }
} }
} }
/// Retuns all longhands SpecifiedValue sizes. This is used in unit tests.
#[cfg(feature = "testing")]
pub fn specified_value_sizes() -> Vec<(&'static str, usize, bool)> {
use std::mem::size_of;
let mut sizes = vec![];
% for property in data.longhands:
sizes.push(("${property.name}",
size_of::<longhands::${property.ident}::SpecifiedValue>(),
${"true" if property.boxed else "false"}));
% endfor
sizes
}

View file

@ -22,7 +22,7 @@
(&DeclaredValue::Value(ref x_value), &DeclaredValue::Value(ref y_container)) => { (&DeclaredValue::Value(ref x_value), &DeclaredValue::Value(ref y_container)) => {
*x_value == y_container.0 *x_value == y_container.0
}, },
(&DeclaredValue::WithVariables { .. }, &DeclaredValue::WithVariables { .. }) => true, (&DeclaredValue::WithVariables(_), &DeclaredValue::WithVariables(_)) => true,
(&DeclaredValue::Initial, &DeclaredValue::Initial) => true, (&DeclaredValue::Initial, &DeclaredValue::Initial) => true,
(&DeclaredValue::Inherit, &DeclaredValue::Inherit) => true, (&DeclaredValue::Inherit, &DeclaredValue::Inherit) => true,
(&DeclaredValue::Unset, &DeclaredValue::Unset) => true, (&DeclaredValue::Unset, &DeclaredValue::Unset) => true,
@ -43,8 +43,8 @@
(&DeclaredValue::Value(ref x_value), &DeclaredValue::Value(ref y_container)) => { (&DeclaredValue::Value(ref x_value), &DeclaredValue::Value(ref y_container)) => {
*x_value == y_container.0 *x_value == y_container.0
}, },
(_, &DeclaredValue::WithVariables { .. }) | (_, &DeclaredValue::WithVariables(_)) |
(&DeclaredValue::WithVariables { .. }, _) => { (&DeclaredValue::WithVariables(_), _) => {
// We don't serialize shorthands with variables // We don't serialize shorthands with variables
return dest.write_str(""); return dest.write_str("");
}, },

View file

@ -58,10 +58,10 @@ pub fn serialize_four_sides<W, I>(dest: &mut W,
Ok(()) Ok(())
} }
fn serialize_directional_border<W, I>(dest: &mut W, fn serialize_directional_border<W, I,>(dest: &mut W,
width: &DeclaredValue<I>, width: &DeclaredValue<I>,
style: &DeclaredValue<BorderStyle>, style: &DeclaredValue<BorderStyle>,
color: &DeclaredValue<CSSColor>) color: &DeclaredValue<Box<CSSColor>>)
-> fmt::Result where W: fmt::Write, I: ToCss { -> fmt::Result where W: fmt::Write, I: ToCss {
match *width { match *width {
DeclaredValue::Value(ref width) => { DeclaredValue::Value(ref width) => {

View file

@ -47,6 +47,19 @@ macro_rules! define_numbered_css_keyword_enum {
} }
} }
/// A macro used to implement HasViewportPercentage trait
/// for a given type that may never contain viewport units.
macro_rules! no_viewport_percentage {
($name: ident) => {
impl HasViewportPercentage for $name {
#[inline]
fn has_viewport_percentage(&self) -> bool {
false
}
}
};
}
pub mod computed; pub mod computed;
pub mod specified; pub mod specified;
@ -62,16 +75,10 @@ pub trait HasViewportPercentage {
fn has_viewport_percentage(&self) -> bool; fn has_viewport_percentage(&self) -> bool;
} }
/// A trait used as a marker to represent that a given type may never contain impl<T: HasViewportPercentage> HasViewportPercentage for Box<T> {
/// viewport units.
pub trait NoViewportPercentage {}
impl<T> HasViewportPercentage for T
where T: NoViewportPercentage,
{
#[inline] #[inline]
fn has_viewport_percentage(&self) -> bool { fn has_viewport_percentage(&self) -> bool {
false (**self).has_viewport_percentage()
} }
} }
@ -103,7 +110,7 @@ macro_rules! define_keyword_type {
} }
impl ComputedValueAsSpecified for $name {} impl ComputedValueAsSpecified for $name {}
impl NoViewportPercentage for $name {} no_viewport_percentage!($name);
}; };
} }

View file

@ -8,7 +8,7 @@ use cssparser::Parser;
use parser::{Parse, ParserContext}; use parser::{Parse, ParserContext};
use std::fmt; use std::fmt;
use style_traits::ToCss; use style_traits::ToCss;
use values::NoViewportPercentage; use values::HasViewportPercentage;
use values::computed::ComputedValueAsSpecified; use values::computed::ComputedValueAsSpecified;
#[derive(PartialEq, Clone, Debug)] #[derive(PartialEq, Clone, Debug)]
@ -96,4 +96,4 @@ impl Parse for GridLine {
} }
impl ComputedValueAsSpecified for GridLine {} impl ComputedValueAsSpecified for GridLine {}
impl NoViewportPercentage for GridLine {} no_viewport_percentage!(GridLine);

View file

@ -16,7 +16,7 @@ use std::f32::consts::PI;
use std::fmt; use std::fmt;
use std::ops::Mul; use std::ops::Mul;
use style_traits::ToCss; use style_traits::ToCss;
use super::{CSSFloat, HasViewportPercentage, NoViewportPercentage, Either, None_}; use super::{CSSFloat, HasViewportPercentage, Either, None_};
use super::computed::{ComputedValueAsSpecified, Context, ToComputedValue}; use super::computed::{ComputedValueAsSpecified, Context, ToComputedValue};
use super::computed::Shadow as ComputedShadow; use super::computed::Shadow as ComputedShadow;
@ -35,7 +35,7 @@ pub mod length;
pub mod position; pub mod position;
pub mod url; pub mod url;
impl NoViewportPercentage for i32 {} // For PropertyDeclaration::Order no_viewport_percentage!(i32); // For PropertyDeclaration::Order
#[derive(Clone, PartialEq, Debug)] #[derive(Clone, PartialEq, Debug)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
@ -60,7 +60,7 @@ impl Parse for CSSColor {
} }
} }
impl NoViewportPercentage for CSSColor {} no_viewport_percentage!(CSSColor);
impl ToCss for CSSColor { impl ToCss for CSSColor {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
@ -79,7 +79,7 @@ pub struct CSSRGBA {
pub authored: Option<String>, pub authored: Option<String>,
} }
impl NoViewportPercentage for CSSRGBA {} no_viewport_percentage!(CSSRGBA);
impl ToCss for CSSRGBA { impl ToCss for CSSRGBA {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
@ -193,7 +193,7 @@ pub fn parse_number(input: &mut Parser) -> Result<f32, ()> {
#[allow(missing_docs)] #[allow(missing_docs)]
pub struct BorderRadiusSize(pub Size2D<LengthOrPercentage>); pub struct BorderRadiusSize(pub Size2D<LengthOrPercentage>);
impl NoViewportPercentage for BorderRadiusSize {} no_viewport_percentage!(BorderRadiusSize);
impl BorderRadiusSize { impl BorderRadiusSize {
#[allow(missing_docs)] #[allow(missing_docs)]
@ -402,7 +402,7 @@ define_numbered_css_keyword_enum! { BorderStyle:
"outset" => outset = 2, "outset" => outset = 2,
} }
impl NoViewportPercentage for BorderStyle {} no_viewport_percentage!(BorderStyle);
impl BorderStyle { impl BorderStyle {
/// Whether this border style is either none or hidden. /// Whether this border style is either none or hidden.
@ -462,7 +462,7 @@ impl ToCss for Time {
#[allow(missing_docs)] #[allow(missing_docs)]
pub struct Number(pub CSSFloat); pub struct Number(pub CSSFloat);
impl NoViewportPercentage for Number {} no_viewport_percentage!(Number);
impl Parse for Number { impl Parse for Number {
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> { fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
@ -512,7 +512,7 @@ impl ToCss for Number {
#[allow(missing_docs)] #[allow(missing_docs)]
pub struct Opacity(pub CSSFloat); pub struct Opacity(pub CSSFloat);
impl NoViewportPercentage for Opacity {} no_viewport_percentage!(Opacity);
impl Parse for Opacity { impl Parse for Opacity {
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> { fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {

View file

@ -15,7 +15,7 @@ use std::borrow::Cow;
use std::fmt::{self, Write}; use std::fmt::{self, Write};
use std::sync::Arc; use std::sync::Arc;
use style_traits::ToCss; use style_traits::ToCss;
use values::NoViewportPercentage; use values::HasViewportPercentage;
use values::computed::ComputedValueAsSpecified; use values::computed::ComputedValueAsSpecified;
/// A set of data needed in Gecko to represent a URL. /// A set of data needed in Gecko to represent a URL.
@ -202,4 +202,4 @@ impl ToCss for SpecifiedUrl {
// TODO(emilio): Maybe consider ComputedUrl to save a word in style structs? // TODO(emilio): Maybe consider ComputedUrl to save a word in style structs?
impl ComputedValueAsSpecified for SpecifiedUrl {} impl ComputedValueAsSpecified for SpecifiedUrl {}
impl NoViewportPercentage for SpecifiedUrl {} no_viewport_percentage!(SpecifiedUrl);

View file

@ -39,6 +39,14 @@ impl<T> ToCss for Vec<T> where T: ToCss + OneOrMoreCommaSeparated {
} }
} }
impl<T: ToCss> ToCss for Box<T> {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
where W: fmt::Write,
{
(**self).to_css(dest)
}
}
impl ToCss for Au { impl ToCss for Au {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
write!(dest, "{}px", self.to_f64_px()) write!(dest, "{}px", self.to_f64_px())

View file

@ -1007,12 +1007,12 @@ pub extern "C" fn Servo_DeclarationBlock_AddPresValue(declarations: RawServoDecl
} }
LonghandId::Color => { LonghandId::Color => {
if let Some(color) = css_value.color_value() { if let Some(color) = css_value.color_value() {
PropertyDeclaration::Color(DeclaredValue::Value( PropertyDeclaration::Color(DeclaredValue::Value(Box::new(
specified::CSSRGBA { specified::CSSRGBA {
parsed: convert_nscolor_to_rgba(color), parsed: convert_nscolor_to_rgba(color),
authored: None authored: None
} }
)) )))
} else { } else {
error!("stylo: got unexpected non-integer value for color presentation attribute"); error!("stylo: got unexpected non-integer value for color presentation attribute");
return return

View file

@ -32,6 +32,7 @@ mod owning_handle;
mod parsing; mod parsing;
mod properties; mod properties;
mod rule_tree; mod rule_tree;
mod size_of;
mod str; mod str;
mod stylesheets; mod stylesheets;
mod stylist; mod stylist;

View file

@ -231,15 +231,15 @@ mod shorthand_serialization {
fn border_color_should_serialize_correctly() { fn border_color_should_serialize_correctly() {
let mut properties = Vec::new(); let mut properties = Vec::new();
let red = DeclaredValue::Value(CSSColor { let red = DeclaredValue::Value(Box::new(CSSColor {
parsed: ComputedColor::RGBA(RGBA { red: 1f32, green: 0f32, blue: 0f32, alpha: 1f32 }), parsed: ComputedColor::RGBA(RGBA { red: 1f32, green: 0f32, blue: 0f32, alpha: 1f32 }),
authored: None authored: None
}); }));
let blue = DeclaredValue::Value(CSSColor { let blue = DeclaredValue::Value(Box::new(CSSColor {
parsed: ComputedColor::RGBA(RGBA { red: 0f32, green: 0f32, blue: 1f32, alpha: 1f32 }), parsed: ComputedColor::RGBA(RGBA { red: 0f32, green: 0f32, blue: 1f32, alpha: 1f32 }),
authored: None authored: None
}); }));
properties.push(PropertyDeclaration::BorderTopColor(blue.clone())); properties.push(PropertyDeclaration::BorderTopColor(blue.clone()));
properties.push(PropertyDeclaration::BorderRightColor(red.clone())); properties.push(PropertyDeclaration::BorderRightColor(red.clone()));
@ -281,10 +281,10 @@ mod shorthand_serialization {
let width = DeclaredValue::Value(BorderWidth::from_length(Length::from_px(4f32))); let width = DeclaredValue::Value(BorderWidth::from_length(Length::from_px(4f32)));
let style = DeclaredValue::Value(BorderStyle::solid); let style = DeclaredValue::Value(BorderStyle::solid);
let color = DeclaredValue::Value(CSSColor { let color = DeclaredValue::Value(Box::new(CSSColor {
parsed: ComputedColor::RGBA(RGBA { red: 1f32, green: 0f32, blue: 0f32, alpha: 1f32 }), parsed: ComputedColor::RGBA(RGBA { red: 1f32, green: 0f32, blue: 0f32, alpha: 1f32 }),
authored: None authored: None
}); }));
properties.push(PropertyDeclaration::BorderTopWidth(width)); properties.push(PropertyDeclaration::BorderTopWidth(width));
properties.push(PropertyDeclaration::BorderTopStyle(style)); properties.push(PropertyDeclaration::BorderTopStyle(style));
@ -300,10 +300,10 @@ mod shorthand_serialization {
let width = DeclaredValue::Value(BorderWidth::from_length(Length::from_px(4f32))); let width = DeclaredValue::Value(BorderWidth::from_length(Length::from_px(4f32)));
let style = DeclaredValue::Initial; let style = DeclaredValue::Initial;
let color = DeclaredValue::Value(CSSColor { let color = DeclaredValue::Value(Box::new(CSSColor {
parsed: ComputedColor::RGBA(RGBA { red: 1f32, green: 0f32, blue: 0f32, alpha: 1f32 }), parsed: ComputedColor::RGBA(RGBA { red: 1f32, green: 0f32, blue: 0f32, alpha: 1f32 }),
authored: None authored: None
}); }));
properties.push(PropertyDeclaration::BorderTopWidth(width)); properties.push(PropertyDeclaration::BorderTopWidth(width));
properties.push(PropertyDeclaration::BorderTopStyle(style)); properties.push(PropertyDeclaration::BorderTopStyle(style));
@ -469,10 +469,10 @@ mod shorthand_serialization {
let width = DeclaredValue::Value(WidthContainer(Length::from_px(4f32))); let width = DeclaredValue::Value(WidthContainer(Length::from_px(4f32)));
let style = DeclaredValue::Value(Either::Second(BorderStyle::solid)); let style = DeclaredValue::Value(Either::Second(BorderStyle::solid));
let color = DeclaredValue::Value(CSSColor { let color = DeclaredValue::Value(Box::new(CSSColor {
parsed: ComputedColor::RGBA(RGBA { red: 1f32, green: 0f32, blue: 0f32, alpha: 1f32 }), parsed: ComputedColor::RGBA(RGBA { red: 1f32, green: 0f32, blue: 0f32, alpha: 1f32 }),
authored: None authored: None
}); }));
properties.push(PropertyDeclaration::OutlineWidth(width)); properties.push(PropertyDeclaration::OutlineWidth(width));
properties.push(PropertyDeclaration::OutlineStyle(style)); properties.push(PropertyDeclaration::OutlineStyle(style));
@ -504,10 +504,10 @@ mod shorthand_serialization {
let width = DeclaredValue::Value(WidthContainer(Length::from_px(4f32))); let width = DeclaredValue::Value(WidthContainer(Length::from_px(4f32)));
let style = DeclaredValue::Initial; let style = DeclaredValue::Initial;
let color = DeclaredValue::Value(CSSColor { let color = DeclaredValue::Value(Box::new(CSSColor {
parsed: ComputedColor::RGBA(RGBA { red: 1f32, green: 0f32, blue: 0f32, alpha: 1f32 }), parsed: ComputedColor::RGBA(RGBA { red: 1f32, green: 0f32, blue: 0f32, alpha: 1f32 }),
authored: None authored: None
}); }));
properties.push(PropertyDeclaration::OutlineWidth(width)); properties.push(PropertyDeclaration::OutlineWidth(width));
properties.push(PropertyDeclaration::OutlineStyle(style)); properties.push(PropertyDeclaration::OutlineStyle(style));
properties.push(PropertyDeclaration::OutlineColor(color)); properties.push(PropertyDeclaration::OutlineColor(color));
@ -522,10 +522,10 @@ mod shorthand_serialization {
let width = DeclaredValue::Value(WidthContainer(Length::from_px(4f32))); let width = DeclaredValue::Value(WidthContainer(Length::from_px(4f32)));
let style = DeclaredValue::Value(Either::First(Auto)); let style = DeclaredValue::Value(Either::First(Auto));
let color = DeclaredValue::Value(CSSColor { let color = DeclaredValue::Value(Box::new(CSSColor {
parsed: ComputedColor::RGBA(RGBA { red: 1f32, green: 0f32, blue: 0f32, alpha: 1f32 }), parsed: ComputedColor::RGBA(RGBA { red: 1f32, green: 0f32, blue: 0f32, alpha: 1f32 }),
authored: None authored: None
}); }));
properties.push(PropertyDeclaration::OutlineWidth(width)); properties.push(PropertyDeclaration::OutlineWidth(width));
properties.push(PropertyDeclaration::OutlineStyle(style)); properties.push(PropertyDeclaration::OutlineStyle(style));
properties.push(PropertyDeclaration::OutlineColor(color)); properties.push(PropertyDeclaration::OutlineColor(color));
@ -730,10 +730,10 @@ mod shorthand_serialization {
fn background_should_serialize_all_available_properties_when_specified() { fn background_should_serialize_all_available_properties_when_specified() {
let mut properties = Vec::new(); let mut properties = Vec::new();
let color = DeclaredValue::Value(CSSColor { let color = DeclaredValue::Value(Box::new(CSSColor {
parsed: ComputedColor::RGBA(RGBA { red: 1f32, green: 0f32, blue: 0f32, alpha: 1f32 }), parsed: ComputedColor::RGBA(RGBA { red: 1f32, green: 0f32, blue: 0f32, alpha: 1f32 }),
authored: None authored: None
}); }));
let position_x = single_vec_value_typedef!(position_x, let position_x = single_vec_value_typedef!(position_x,
HorizontalPosition { HorizontalPosition {
@ -790,10 +790,10 @@ mod shorthand_serialization {
fn background_should_combine_origin_and_clip_properties_when_equal() { fn background_should_combine_origin_and_clip_properties_when_equal() {
let mut properties = Vec::new(); let mut properties = Vec::new();
let color = DeclaredValue::Value(CSSColor { let color = DeclaredValue::Value(Box::new(CSSColor {
parsed: ComputedColor::RGBA(RGBA { red: 1f32, green: 0f32, blue: 0f32, alpha: 1f32 }), parsed: ComputedColor::RGBA(RGBA { red: 1f32, green: 0f32, blue: 0f32, alpha: 1f32 }),
authored: None authored: None
}); }));
let position_x = single_vec_value_typedef!(position_x, let position_x = single_vec_value_typedef!(position_x,
HorizontalPosition { HorizontalPosition {
@ -849,10 +849,10 @@ mod shorthand_serialization {
fn background_should_always_print_color_and_url_and_repeat_and_attachment_and_position() { fn background_should_always_print_color_and_url_and_repeat_and_attachment_and_position() {
let mut properties = Vec::new(); let mut properties = Vec::new();
let color = DeclaredValue::Value(CSSColor { let color = DeclaredValue::Value(Box::new(CSSColor {
parsed: ComputedColor::RGBA(RGBA { red: 1f32, green: 0f32, blue: 0f32, alpha: 1f32 }), parsed: ComputedColor::RGBA(RGBA { red: 1f32, green: 0f32, blue: 0f32, alpha: 1f32 }),
authored: None authored: None
}); }));
let position_x = single_vec_value_typedef!(position_x, let position_x = single_vec_value_typedef!(position_x,
HorizontalPosition { HorizontalPosition {

View file

@ -0,0 +1,44 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* 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::mem::size_of;
use style::properties::{PropertyDeclaration, specified_value_sizes};
#[test]
fn size_of_property_declaration() {
let old = 48;
let new = size_of::<PropertyDeclaration>();
if new < old {
panic!("Your changes have decreased the stack size of PropertyDeclaration enum from {} to {}. \
Good work! Please update the size in tests/unit/style/size_of.rs.",
old, new)
} else if new > old {
panic!("Your changes have increased the stack size of PropertyDeclaration enum from {} to {}. \
These enum is present in large quantities in the style, and increasing the size \
may dramatically affect our memory footprint. Please consider using `boxed=\"True\"` in \
the longhand If you feel that the increase is necessary, update to the new size in \
tests/unit/style/size_of.rs.",
old, new)
}
}
#[test]
fn size_of_specified_values() {
let threshold = 40;
let longhands = specified_value_sizes();
for specified_value in longhands {
if specified_value.1 >= threshold && !specified_value.2 {
panic!("Your changes have increased the size of {} SpecifiedValue to {}. The threshold is \
currently {}. SpecifiedValues are affect size of PropertyDeclaration enum and \
increasing the size may dramatically affect our memory footprint. Please consider \
using `boxed=\"True\"` in this longhand.",
specified_value.0, specified_value.1, threshold)
} else if specified_value.1 < threshold && specified_value.2 {
panic!("Your changes have decreased the size of {} SpecifiedValue to {}. Good work! \
The threshold is currently {}. Please consider removing `boxed=\"True\"` from this longhand.",
specified_value.0, specified_value.1, threshold)
}
}
}

View file

@ -183,12 +183,12 @@ fn test_parse_stylesheet() {
block: Arc::new(RwLock::new(PropertyDeclarationBlock { block: Arc::new(RwLock::new(PropertyDeclarationBlock {
declarations: vec![ declarations: vec![
(PropertyDeclaration::BackgroundColor(DeclaredValue::Value( (PropertyDeclaration::BackgroundColor(DeclaredValue::Value(
longhands::background_color::SpecifiedValue { Box::new(longhands::background_color::SpecifiedValue {
authored: Some("blue".to_owned()), authored: Some("blue".to_owned()),
parsed: cssparser::Color::RGBA(cssparser::RGBA { parsed: cssparser::Color::RGBA(cssparser::RGBA {
red: 0., green: 0., blue: 1., alpha: 1. red: 0., green: 0., blue: 1., alpha: 1.
}), }),
} })
)), )),
Importance::Normal), Importance::Normal),
(PropertyDeclaration::BackgroundPositionX(DeclaredValue::Value( (PropertyDeclaration::BackgroundPositionX(DeclaredValue::Value(