diff --git a/components/style/font_face.rs b/components/style/font_face.rs index 1eae14e4a3a..36361c27e67 100644 --- a/components/style/font_face.rs +++ b/components/style/font_face.rs @@ -67,13 +67,17 @@ impl ToCss for UrlSource { /// A font-display value for a @font-face rule. /// The font-display descriptor determines how a font face is displayed based /// on whether and when it is downloaded and ready to use. -define_css_keyword_enum!(FontDisplay: - "auto" => Auto, - "block" => Block, - "swap" => Swap, - "fallback" => Fallback, - "optional" => Optional); -add_impls_for_keyword_enum!(FontDisplay); +#[allow(missing_docs)] +#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] +#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq)] +#[derive(ToComputedValue, ToCss)] +pub enum FontDisplay { + Auto, + Block, + Swap, + Fallback, + Optional, +} /// A font-weight value for a @font-face rule. /// The font-weight CSS property specifies the weight or boldness of the font. diff --git a/components/style/gecko/conversions.rs b/components/style/gecko/conversions.rs index de42d262694..a36f82018df 100644 --- a/components/style/gecko/conversions.rs +++ b/components/style/gecko/conversions.rs @@ -707,9 +707,9 @@ pub mod basic_shape { } StyleBasicShapeType::Polygon => { let fill_rule = if other.mFillRule == StyleFillRule::Evenodd { - FillRule::EvenOdd + FillRule::Evenodd } else { - FillRule::NonZero + FillRule::Nonzero }; let mut coords = Vec::with_capacity(other.mCoordinates.len() / 2); for i in 0..(other.mCoordinates.len() / 2) { diff --git a/components/style/gecko/values.rs b/components/style/gecko/values.rs index fc5d75bbe4b..d24e9ea33ac 100644 --- a/components/style/gecko/values.rs +++ b/components/style/gecko/values.rs @@ -348,10 +348,10 @@ impl GeckoStyleCoordConvertible for ExtremumLength { use gecko_bindings::structs::{NS_STYLE_WIDTH_MAX_CONTENT, NS_STYLE_WIDTH_MIN_CONTENT}; coord.set_value(CoordDataValue::Enumerated( match *self { - ExtremumLength::MaxContent => NS_STYLE_WIDTH_MAX_CONTENT, - ExtremumLength::MinContent => NS_STYLE_WIDTH_MIN_CONTENT, - ExtremumLength::FitContent => NS_STYLE_WIDTH_FIT_CONTENT, - ExtremumLength::FillAvailable => NS_STYLE_WIDTH_AVAILABLE, + ExtremumLength::MozMaxContent => NS_STYLE_WIDTH_MAX_CONTENT, + ExtremumLength::MozMinContent => NS_STYLE_WIDTH_MIN_CONTENT, + ExtremumLength::MozFitContent => NS_STYLE_WIDTH_FIT_CONTENT, + ExtremumLength::MozAvailable => NS_STYLE_WIDTH_AVAILABLE, } )) } @@ -361,12 +361,12 @@ impl GeckoStyleCoordConvertible for ExtremumLength { use gecko_bindings::structs::{NS_STYLE_WIDTH_MAX_CONTENT, NS_STYLE_WIDTH_MIN_CONTENT}; match coord.as_value() { CoordDataValue::Enumerated(NS_STYLE_WIDTH_MAX_CONTENT) => - Some(ExtremumLength::MaxContent), + Some(ExtremumLength::MozMaxContent), CoordDataValue::Enumerated(NS_STYLE_WIDTH_MIN_CONTENT) => - Some(ExtremumLength::MinContent), + Some(ExtremumLength::MozMinContent), CoordDataValue::Enumerated(NS_STYLE_WIDTH_FIT_CONTENT) => - Some(ExtremumLength::FitContent), - CoordDataValue::Enumerated(NS_STYLE_WIDTH_AVAILABLE) => Some(ExtremumLength::FillAvailable), + Some(ExtremumLength::MozFitContent), + CoordDataValue::Enumerated(NS_STYLE_WIDTH_AVAILABLE) => Some(ExtremumLength::MozAvailable), _ => None, } } diff --git a/components/style/lib.rs b/components/style/lib.rs index 8a343496e6d..5c5a837d5ba 100644 --- a/components/style/lib.rs +++ b/components/style/lib.rs @@ -25,8 +25,6 @@ #![deny(missing_docs)] -#![recursion_limit = "500"] // For define_css_keyword_enum! in -moz-appearance - extern crate app_units; extern crate arrayvec; extern crate atomic_refcell; @@ -72,7 +70,6 @@ extern crate smallbitvec; extern crate smallvec; #[macro_use] extern crate style_derive; -#[macro_use] extern crate style_traits; extern crate time; extern crate uluru; diff --git a/components/style/macros.rs b/components/style/macros.rs index c3bf87b51a4..5f20e3c8d0c 100644 --- a/components/style/macros.rs +++ b/components/style/macros.rs @@ -65,67 +65,6 @@ macro_rules! try_match_ident_ignore_ascii_case { }} } -macro_rules! define_numbered_css_keyword_enum { - ($name: ident: $( $css: expr => $variant: ident = $value: expr ),+,) => { - define_numbered_css_keyword_enum!($name: $( $css => $variant = $value ),+); - }; - ($name: ident: $( $css: expr => $variant: ident = $value: expr ),+) => { - #[allow(non_camel_case_types, missing_docs)] - #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Ord, PartialEq, PartialOrd)] - #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] - pub enum $name { - $( $variant = $value ),+ - } - - impl $crate::parser::Parse for $name { - fn parse<'i, 't>( - _context: &$crate::parser::ParserContext, - input: &mut ::cssparser::Parser<'i, 't>, - ) -> Result<$name, ::style_traits::ParseError<'i>> { - try_match_ident_ignore_ascii_case! { input, - $( $css => Ok($name::$variant), )+ - } - } - } - - impl ::style_traits::ToCss for $name { - fn to_css( - &self, - dest: &mut ::style_traits::CssWriter, - ) -> ::std::fmt::Result - where - W: ::std::fmt::Write, - { - match *self { - $( $name::$variant => dest.write_str($css) ),+ - } - } - } - } -} - -/// A macro for implementing `ToComputedValue`, and `Parse` traits for -/// the enums defined using `define_css_keyword_enum` macro. -/// -/// NOTE: We should either move `Parse` trait to `style_traits` -/// or `define_css_keyword_enum` macro to this crate, but that -/// may involve significant cleanup in both the crates. -macro_rules! add_impls_for_keyword_enum { - ($name:ident) => { - impl $crate::parser::Parse for $name { - #[inline] - fn parse<'i, 't>( - _context: &$crate::parser::ParserContext, - input: &mut ::cssparser::Parser<'i, 't>, - ) -> Result> { - $name::parse(input) - } - } - - trivial_to_computed_value!($name); - }; -} - macro_rules! define_keyword_type { ($name: ident, $css: expr) => { #[allow(missing_docs)] diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 7b86d29106c..2e4cf3db43b 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -62,6 +62,7 @@ use values::computed::{NonNegativeLength, ToComputedValue, Percentage}; use values::computed::font::{FontSize, SingleFontFamily}; use values::computed::effects::{BoxShadow, Filter, SimpleShadow}; use values::computed::outline::OutlineStyle; +use values::generics::transform::TransformStyle; use computed_values::border_style; pub mod style_structs { @@ -3345,6 +3346,25 @@ fn static_assert() { self.copy_transition_property_from(other) } + // Hand-written because the Mako helpers transform `Preserve3d` into `PRESERVE3D`. + pub fn set_transform_style(&mut self, v: TransformStyle) { + self.gecko.mTransformStyle = match v { + TransformStyle::Flat => structs::NS_STYLE_TRANSFORM_STYLE_FLAT as u8, + TransformStyle::Preserve3d => structs::NS_STYLE_TRANSFORM_STYLE_PRESERVE_3D as u8, + }; + } + + // Hand-written because the Mako helpers transform `Preserve3d` into `PRESERVE3D`. + pub fn clone_transform_style(&self) -> TransformStyle { + match self.gecko.mTransformStyle as u32 { + structs::NS_STYLE_TRANSFORM_STYLE_FLAT => TransformStyle::Flat, + structs::NS_STYLE_TRANSFORM_STYLE_PRESERVE_3D => TransformStyle::Preserve3d, + _ => panic!("illegal transform style"), + } + } + + ${impl_simple_copy('transform_style', 'mTransformStyle')} + ${impl_transition_count('property', 'Property')} pub fn animations_equals(&self, other: &Self) -> bool { @@ -5081,7 +5101,7 @@ fn static_assert() { coord.0.to_gecko_style_coord(&mut shape.mCoordinates[2 * i]); coord.1.to_gecko_style_coord(&mut shape.mCoordinates[2 * i + 1]); } - shape.mFillRule = if poly.fill == FillRule::EvenOdd { + shape.mFillRule = if poly.fill == FillRule::Evenodd { StyleFillRule::Evenodd } else { StyleFillRule::Nonzero diff --git a/components/style/properties/helpers.mako.rs b/components/style/properties/helpers.mako.rs index 4d7c1ff19ad..411dea7a95a 100644 --- a/components/style/properties/helpers.mako.rs +++ b/components/style/properties/helpers.mako.rs @@ -424,20 +424,13 @@ use properties::longhands::system_font::SystemFont; pub mod computed_value { - use cssparser::Parser; - use parser::{Parse, ParserContext}; - - use style_traits::ParseError; - define_css_keyword_enum! { T: - % for value in keyword.values_for(product): - "${value}" => ${to_camel_case(value)}, - % endfor - } - - impl Parse for T { - fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { - T::parse(input) - } + #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] + #[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse)] + #[derive(PartialEq, ToCss)] + pub enum T { + % for value in keyword.values_for(product): + ${to_camel_case(value)}, + % endfor } ${gecko_keyword_conversion(keyword, keyword.values_for(product), type="T", cast_to="i32")} @@ -604,26 +597,32 @@ <%def name="inner_body(keyword, extra_specified=None, needs_conversion=False)"> % if extra_specified or keyword.aliases_for(product): - define_css_keyword_enum! { SpecifiedValue: - values { - % for value in keyword.values_for(product) + (extra_specified or "").split(): - "${value}" => ${to_camel_case(value)}, - % endfor - } - aliases { - % for alias, value in keyword.aliases_for(product).iteritems(): - "${alias}" => ${to_camel_case(value)}, - % endfor - } + #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] + #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToCss)] + pub enum SpecifiedValue { + % for value in keyword.values_for(product) + (extra_specified or "").split(): + <% + aliases = [] + for alias, v in keyword.aliases_for(product).iteritems(): + if value == v: + aliases.append(alias) + %> + % if aliases: + #[css(aliases = "${','.join(aliases)}")] + % endif + ${to_camel_case(value)}, + % endfor } % else: pub use self::computed_value::T as SpecifiedValue; % endif pub mod computed_value { - define_css_keyword_enum! { T: - % for value in data.longhands_by_name[name].keyword.values_for(product): - "${value}" => ${to_camel_case(value)}, - % endfor + #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] + #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToCss)] + pub enum T { + % for value in data.longhands_by_name[name].keyword.values_for(product): + ${to_camel_case(value)}, + % endfor } } #[inline] @@ -639,13 +638,6 @@ -> Result> { SpecifiedValue::parse(input) } - impl Parse for SpecifiedValue { - #[inline] - fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) - -> Result> { - SpecifiedValue::parse(input) - } - } % if needs_conversion: <% diff --git a/components/style/properties/longhand/border.mako.rs b/components/style/properties/longhand/border.mako.rs index a24c31acf88..a98c83c6697 100644 --- a/components/style/properties/longhand/border.mako.rs +++ b/components/style/properties/longhand/border.mako.rs @@ -32,13 +32,16 @@ ignored_when_colors_disabled=True, )} - ${helpers.predefined_type("border-%s-style" % side_name, "BorderStyle", - "specified::BorderStyle::None", - alias=maybe_moz_logical_alias(product, side, "-moz-border-%s-style"), - spec=maybe_logical_spec(side, "style"), - flags="APPLIES_TO_FIRST_LETTER", - animation_value_type="discrete" if not is_logical else "none", - logical=is_logical)} + ${helpers.predefined_type( + "border-%s-style" % side_name, "BorderStyle", + "specified::BorderStyle::None", + alias=maybe_moz_logical_alias(product, side, "-moz-border-%s-style"), + spec=maybe_logical_spec(side, "style"), + flags="APPLIES_TO_FIRST_LETTER", + animation_value_type="discrete" if not is_logical else "none", + logical=is_logical, + needs_context=False, + )} ${helpers.predefined_type("border-%s-width" % side_name, "BorderSideWidth", @@ -112,11 +115,14 @@ ${helpers.predefined_type("border-image-outset", "LengthOrNumberRect", pub struct SpecifiedValue(pub RepeatKeyword, pub Option); - define_css_keyword_enum!(RepeatKeyword: - "stretch" => Stretch, - "repeat" => Repeat, - "round" => Round, - "space" => Space); + #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] + #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToCss)] + pub enum RepeatKeyword { + Stretch, + Repeat, + Round, + Space, + } #[inline] pub fn get_initial_value() -> computed_value::T { diff --git a/components/style/properties/longhand/box.mako.rs b/components/style/properties/longhand/box.mako.rs index 286bf6b7ea9..6de6486fa4d 100644 --- a/components/style/properties/longhand/box.mako.rs +++ b/components/style/properties/longhand/box.mako.rs @@ -526,14 +526,16 @@ ${helpers.single_keyword("transform-box", gecko_inexhaustive="True", animation_value_type="discrete")} -// `auto` keyword is not supported in gecko yet. -${helpers.single_keyword("transform-style", - "auto flat preserve-3d" if product == "servo" else - "flat preserve-3d", - spec="https://drafts.csswg.org/css-transforms/#transform-style-property", - extra_prefixes="moz webkit", - flags="CREATES_STACKING_CONTEXT FIXPOS_CB", - animation_value_type="discrete")} +${helpers.predefined_type( + "transform-style", + "TransformStyle", + "computed::TransformStyle::" + ("Auto" if product == "servo" else "Flat"), + spec="https://drafts.csswg.org/css-transforms-2/#transform-style-property", + needs_context=False, + extra_prefixes="moz webkit", + flags="CREATES_STACKING_CONTEXT FIXPOS_CB", + animation_value_type="discrete", +)} ${helpers.predefined_type("transform-origin", "TransformOrigin", diff --git a/components/style/properties/longhand/inherited_text.mako.rs b/components/style/properties/longhand/inherited_text.mako.rs index c7ad330a274..7c8ec734c3c 100644 --- a/components/style/properties/longhand/inherited_text.mako.rs +++ b/components/style/properties/longhand/inherited_text.mako.rs @@ -279,12 +279,14 @@ ${helpers.predefined_type( } } - define_css_keyword_enum!(ShapeKeyword: - "dot" => Dot, - "circle" => Circle, - "double-circle" => DoubleCircle, - "triangle" => Triangle, - "sesame" => Sesame); + #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToCss)] + pub enum ShapeKeyword { + Dot, + Circle, + DoubleCircle, + Triangle, + Sesame, + } impl ShapeKeyword { pub fn char(&self, fill: bool) -> &str { @@ -381,14 +383,19 @@ ${helpers.predefined_type( <%helpers:longhand name="text-emphasis-position" animation_value_type="discrete" products="gecko" spec="https://drafts.csswg.org/css-text-decor/#propdef-text-emphasis-position"> - define_css_keyword_enum!(HorizontalWritingModeValue: - "over" => Over, - "under" => Under); - add_impls_for_keyword_enum!(VerticalWritingModeValue); - define_css_keyword_enum!(VerticalWritingModeValue: - "right" => Right, - "left" => Left); - add_impls_for_keyword_enum!(HorizontalWritingModeValue); + #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq)] + #[derive(ToComputedValue, ToCss)] + pub enum HorizontalWritingModeValue { + Over, + Under, + } + + #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq)] + #[derive(ToComputedValue, ToCss)] + pub enum VerticalWritingModeValue { + Right, + Left, + } #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss)] pub struct SpecifiedValue(pub HorizontalWritingModeValue, pub VerticalWritingModeValue); diff --git a/components/style/properties/shorthand/border.mako.rs b/components/style/properties/shorthand/border.mako.rs index 0209ebb2376..ec462510bf7 100644 --- a/components/style/properties/shorthand/border.mako.rs +++ b/components/style/properties/shorthand/border.mako.rs @@ -9,9 +9,13 @@ ${helpers.four_sides_shorthand("border-color", "border-%s-color", "specified::Co spec="https://drafts.csswg.org/css-backgrounds/#border-color", allow_quirks=True)} -${helpers.four_sides_shorthand("border-style", "border-%s-style", - "specified::BorderStyle::parse", - spec="https://drafts.csswg.org/css-backgrounds/#border-style")} +${helpers.four_sides_shorthand( + "border-style", + "border-%s-style", + "specified::BorderStyle::parse", + needs_context=False, + spec="https://drafts.csswg.org/css-backgrounds/#border-style", +)} <%helpers:shorthand name="border-width" sub_properties="${ ' '.join('border-%s-width' % side @@ -63,7 +67,7 @@ pub fn parse_border<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) } } if style.is_none() { - if let Ok(value) = input.try(|i| BorderStyle::parse(context, i)) { + if let Ok(value) = input.try(BorderStyle::parse) { style = Some(value); any = true; continue diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index c91256d7e6e..874424f45c3 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -73,7 +73,8 @@ pub use self::svg::MozContextProperties; pub use self::table::XSpan; pub use self::text::{InitialLetter, LetterSpacing, LineHeight, TextAlign, TextOverflow, WordSpacing}; pub use self::time::Time; -pub use self::transform::{TimingFunction, Transform, TransformOperation, TransformOrigin, Rotate, Translate, Scale}; +pub use self::transform::{Rotate, Scale, TimingFunction, Transform, TransformOperation}; +pub use self::transform::{TransformOrigin, TransformStyle, Translate}; pub use self::ui::MozForceBrokenImageIcon; #[cfg(feature = "gecko")] diff --git a/components/style/values/computed/transform.rs b/components/style/values/computed/transform.rs index 17b2fa70540..bcf90f3966c 100644 --- a/components/style/values/computed/transform.rs +++ b/components/style/values/computed/transform.rs @@ -18,6 +18,8 @@ use values::generics::transform::TimingFunction as GenericTimingFunction; use values::generics::transform::TransformOrigin as GenericTransformOrigin; use values::generics::transform::Translate as GenericTranslate; +pub use values::generics::transform::TransformStyle; + /// A single operation in a computed CSS `transform` pub type TransformOperation = GenericTransformOperation< Angle, diff --git a/components/style/values/generics/basic_shape.rs b/components/style/values/generics/basic_shape.rs index 07881a3a103..4c805eb0591 100644 --- a/components/style/values/generics/basic_shape.rs +++ b/components/style/values/generics/basic_shape.rs @@ -30,13 +30,16 @@ pub enum GeometryBox { pub type FloatAreaShape = ShapeSource; // https://drafts.csswg.org/css-shapes-1/#typedef-shape-box -define_css_keyword_enum!(ShapeBox: - "margin-box" => MarginBox, - "border-box" => BorderBox, - "padding-box" => PaddingBox, - "content-box" => ContentBox -); -add_impls_for_keyword_enum!(ShapeBox); +#[allow(missing_docs)] +#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] +#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq)] +#[derive(ToComputedValue, ToCss)] +pub enum ShapeBox { + MarginBox, + BorderBox, + PaddingBox, + ContentBox, +} /// A shape source, for some reference box. #[allow(missing_docs)] @@ -117,11 +120,14 @@ pub struct Polygon { // NOTE: Basic shapes spec says that these are the only two values, however // https://www.w3.org/TR/SVG/painting.html#FillRuleProperty // says that it can also be `inherit` -define_css_keyword_enum!(FillRule: - "nonzero" => NonZero, - "evenodd" => EvenOdd -); -add_impls_for_keyword_enum!(FillRule); +#[allow(missing_docs)] +#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] +#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq)] +#[derive(ToComputedValue, ToCss)] +pub enum FillRule { + Nonzero, + Evenodd, +} // FIXME(nox): Implement ComputeSquaredDistance for T types and stop // using PartialEq here, this will let us derive this impl. @@ -239,5 +245,5 @@ impl ToCss for Polygon { impl Default for FillRule { #[inline] - fn default() -> Self { FillRule::NonZero } + fn default() -> Self { FillRule::Nonzero } } diff --git a/components/style/values/generics/grid.rs b/components/style/values/generics/grid.rs index dab8b0f3e9d..2b519f1aa85 100644 --- a/components/style/values/generics/grid.rs +++ b/components/style/values/generics/grid.rs @@ -140,12 +140,15 @@ impl Parse for GridLine { } } -define_css_keyword_enum!{ TrackKeyword: - "auto" => Auto, - "max-content" => MaxContent, - "min-content" => MinContent +#[allow(missing_docs)] +#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] +#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq)] +#[derive(ToComputedValue, ToCss)] +pub enum TrackKeyword { + Auto, + MaxContent, + MinContent, } -add_impls_for_keyword_enum!(TrackKeyword); /// A track breadth for explicit grid track sizing. It's generic solely to /// avoid re-implementing it for the computed type. diff --git a/components/style/values/generics/image.rs b/components/style/values/generics/image.rs index d74c05ae81d..588c4d3fdda 100644 --- a/components/style/values/generics/image.rs +++ b/components/style/values/generics/image.rs @@ -97,15 +97,18 @@ pub enum Ellipse { } /// -define_css_keyword_enum!(ShapeExtent: - "closest-side" => ClosestSide, - "farthest-side" => FarthestSide, - "closest-corner" => ClosestCorner, - "farthest-corner" => FarthestCorner, - "contain" => Contain, - "cover" => Cover -); -add_impls_for_keyword_enum!(ShapeExtent); +#[allow(missing_docs)] +#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] +#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq)] +#[derive(ToComputedValue, ToCss)] +pub enum ShapeExtent { + ClosestSide, + FarthestSide, + ClosestCorner, + FarthestCorner, + Contain, + Cover, +} /// A gradient item. /// diff --git a/components/style/values/generics/mod.rs b/components/style/values/generics/mod.rs index 263db6890d2..0ecd51f170c 100644 --- a/components/style/values/generics/mod.rs +++ b/components/style/values/generics/mod.rs @@ -32,14 +32,17 @@ pub mod text; pub mod transform; // https://drafts.csswg.org/css-counter-styles/#typedef-symbols-type -define_css_keyword_enum! { SymbolsType: - "cyclic" => Cyclic, - "numeric" => Numeric, - "alphabetic" => Alphabetic, - "symbolic" => Symbolic, - "fixed" => Fixed, +#[allow(missing_docs)] +#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] +#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq)] +#[derive(ToComputedValue, ToCss)] +pub enum SymbolsType { + Cyclic, + Numeric, + Alphabetic, + Symbolic, + Fixed, } -add_impls_for_keyword_enum!(SymbolsType); #[cfg(feature = "gecko")] impl SymbolsType { diff --git a/components/style/values/generics/transform.rs b/components/style/values/generics/transform.rs index e8b8c2e0678..f2818842723 100644 --- a/components/style/values/generics/transform.rs +++ b/components/style/values/generics/transform.rs @@ -98,20 +98,26 @@ pub enum TimingFunction { Frames(Integer), } -define_css_keyword_enum! { TimingKeyword: - "linear" => Linear, - "ease" => Ease, - "ease-in" => EaseIn, - "ease-out" => EaseOut, - "ease-in-out" => EaseInOut, +#[allow(missing_docs)] +#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] +#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq)] +#[derive(ToComputedValue, ToCss)] +pub enum TimingKeyword { + Linear, + Ease, + EaseIn, + EaseOut, + EaseInOut, } -add_impls_for_keyword_enum!(TimingKeyword); -define_css_keyword_enum! { StepPosition: - "start" => Start, - "end" => End, +#[allow(missing_docs)] +#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] +#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq)] +#[derive(ToComputedValue, ToCss)] +pub enum StepPosition { + Start, + End, } -add_impls_for_keyword_enum!(StepPosition); impl TransformOrigin { /// Returns a new transform origin. @@ -714,3 +720,13 @@ pub enum Translate { /// ' ' Translate3D(LengthOrPercentage, LengthOrPercentage, Length), } + +#[allow(missing_docs)] +#[derive(Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, ToComputedValue, ToCss)] +pub enum TransformStyle { + #[cfg(feature = "servo")] + Auto, + Flat, + #[css(keyword = "preserve-3d")] + Preserve3d, +} diff --git a/components/style/values/mod.rs b/components/style/values/mod.rs index 601b5edc5ac..d75400d9e7e 100644 --- a/components/style/values/mod.rs +++ b/components/style/values/mod.rs @@ -195,10 +195,14 @@ impl ToCss for KeyframesName { } } -// A type for possible values for min- and max- flavors of width, -// height, block-size, and inline-size. -define_css_keyword_enum!(ExtremumLength: - "-moz-max-content" => MaxContent, - "-moz-min-content" => MinContent, - "-moz-fit-content" => FitContent, - "-moz-available" => FillAvailable); +/// A type for possible values for min- and max- flavors of width, +/// height, block-size, and inline-size. +#[allow(missing_docs)] +#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] +#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToCss)] +pub enum ExtremumLength { + MozMaxContent, + MozMinContent, + MozFitContent, + MozAvailable, +} diff --git a/components/style/values/specified/box.rs b/components/style/values/specified/box.rs index 483ac9907e0..99858936702 100644 --- a/components/style/values/specified/box.rs +++ b/components/style/values/specified/box.rs @@ -28,9 +28,9 @@ pub enum Display { Table, InlineTable, TableRowGroup, TableHeaderGroup, TableFooterGroup, TableRow, TableColumnGroup, TableColumn, TableCell, TableCaption, ListItem, None, - #[parse(aliases = "-webkit-flex")] + #[css(aliases = "-webkit-flex")] Flex, - #[parse(aliases = "-webkit-inline-flex")] + #[css(aliases = "-webkit-inline-flex")] InlineFlex, #[cfg(feature = "gecko")] Grid, @@ -320,25 +320,34 @@ impl Parse for AnimationName { } } -define_css_keyword_enum! { ScrollSnapType: - "none" => None, - "mandatory" => Mandatory, - "proximity" => Proximity, +#[allow(missing_docs)] +#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] +#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq)] +#[derive(ToComputedValue, ToCss)] +pub enum ScrollSnapType { + None, + Mandatory, + Proximity, } -add_impls_for_keyword_enum!(ScrollSnapType); -define_css_keyword_enum! { OverscrollBehavior: - "auto" => Auto, - "contain" => Contain, - "none" => None, +#[allow(missing_docs)] +#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] +#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq)] +#[derive(ToComputedValue, ToCss)] +pub enum OverscrollBehavior { + Auto, + Contain, + None, } -add_impls_for_keyword_enum!(OverscrollBehavior); -define_css_keyword_enum! { OverflowClipBox: - "padding-box" => PaddingBox, - "content-box" => ContentBox, +#[allow(missing_docs)] +#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] +#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq)] +#[derive(ToComputedValue, ToCss)] +pub enum OverflowClipBox { + PaddingBox, + ContentBox, } -add_impls_for_keyword_enum!(OverflowClipBox); #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss)] /// Provides a rendering hint to the user agent, diff --git a/components/style/values/specified/color.rs b/components/style/values/specified/color.rs index a22a183cf49..b7dbe35a165 100644 --- a/components/style/values/specified/color.rs +++ b/components/style/values/specified/color.rs @@ -47,12 +47,13 @@ pub enum Color { #[cfg(feature = "gecko")] mod gecko { - define_css_keyword_enum! { SpecialColorKeyword: - "-moz-default-color" => MozDefaultColor, - "-moz-default-background-color" => MozDefaultBackgroundColor, - "-moz-hyperlinktext" => MozHyperlinktext, - "-moz-activehyperlinktext" => MozActiveHyperlinktext, - "-moz-visitedhyperlinktext" => MozVisitedHyperlinktext, + #[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, Parse, PartialEq, ToCss)] + pub enum SpecialColorKeyword { + MozDefaultColor, + MozDefaultBackgroundColor, + MozHyperlinktext, + MozActiveHyperlinktext, + MozVisitedHyperlinktext, } } diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index bff8af54aaa..32d9a46f14d 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -69,7 +69,8 @@ pub use self::table::XSpan; pub use self::text::{InitialLetter, LetterSpacing, LineHeight, TextDecorationLine}; pub use self::text::{TextAlign, TextAlignKeyword, TextOverflow, WordSpacing}; pub use self::time::Time; -pub use self::transform::{TimingFunction, Transform, TransformOrigin, Rotate, Translate, Scale}; +pub use self::transform::{Rotate, Scale, TimingFunction, Transform}; +pub use self::transform::{TransformOrigin, TransformStyle, Translate}; pub use self::ui::MozForceBrokenImageIcon; pub use super::generics::grid::GridTemplateComponent as GenericGridTemplateComponent; @@ -160,20 +161,23 @@ fn parse_number_with_clamping_mode<'i, 't>( // 17.6.2.1. Higher values override lower values. // // FIXME(emilio): Should move to border.rs -define_numbered_css_keyword_enum! { BorderStyle: - "none" => None = -1, - "solid" => Solid = 6, - "double" => Double = 7, - "dotted" => Dotted = 4, - "dashed" => Dashed = 5, - "hidden" => Hidden = -2, - "groove" => Groove = 1, - "ridge" => Ridge = 3, - "inset" => Inset = 0, - "outset" => Outset = 2, +#[allow(missing_docs)] +#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] +#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Ord, Parse, PartialEq)] +#[derive(PartialOrd, ToCss)] +pub enum BorderStyle { + None = -1, + Solid = 6, + Double = 7, + Dotted = 4, + Dashed = 5, + Hidden = -2, + Groove = 1, + Ridge = 3, + Inset = 0, + Outset = 2, } - impl BorderStyle { /// Whether this border style is either none or hidden. pub fn none_or_hidden(&self) -> bool { diff --git a/components/style/values/specified/outline.rs b/components/style/values/specified/outline.rs index 48385242275..a9366c185db 100644 --- a/components/style/values/specified/outline.rs +++ b/components/style/values/specified/outline.rs @@ -39,10 +39,10 @@ impl OutlineStyle { impl Parse for OutlineStyle { fn parse<'i, 't>( - context: &ParserContext, + _context: &ParserContext, input: &mut Parser<'i, 't> ) -> Result> { - if let Ok(border_style) = input.try(|i| BorderStyle::parse(context, i)) { + if let Ok(border_style) = input.try(BorderStyle::parse) { if let BorderStyle::Hidden = border_style { return Err(input.new_custom_error(SelectorParseErrorKind::UnexpectedIdent("hidden".into()))); } diff --git a/components/style/values/specified/transform.rs b/components/style/values/specified/transform.rs index d98b4c9da6f..e2965cfefc5 100644 --- a/components/style/values/specified/transform.rs +++ b/components/style/values/specified/transform.rs @@ -22,6 +22,8 @@ use values::specified::{self, Angle, Number, Length, Integer}; use values::specified::{LengthOrNumber, LengthOrPercentage, LengthOrPercentageOrNumber}; use values::specified::position::{Side, X, Y}; +pub use values::generics::transform::TransformStyle; + /// A single operation in a specified CSS `transform` pub type TransformOperation = GenericTransformOperation< Angle, diff --git a/components/style_derive/lib.rs b/components/style_derive/lib.rs index a9a8a32dbf7..7778b7ea39c 100644 --- a/components/style_derive/lib.rs +++ b/components/style_derive/lib.rs @@ -39,7 +39,7 @@ pub fn derive_to_animated_value(stream: TokenStream) -> TokenStream { to_animated_value::derive(input).to_string().parse().unwrap() } -#[proc_macro_derive(Parse, attributes(parse))] +#[proc_macro_derive(Parse, attributes(css))] pub fn derive_parse(stream: TokenStream) -> TokenStream { let input = syn::parse_derive_input(&stream.to_string()).unwrap(); parse::derive(input).to_string().parse().unwrap() diff --git a/components/style_derive/parse.rs b/components/style_derive/parse.rs index cac626749bd..79ada00878f 100644 --- a/components/style_derive/parse.rs +++ b/components/style_derive/parse.rs @@ -6,6 +6,7 @@ use cg; use quote::Tokens; use syn::DeriveInput; use synstructure; +use to_css::CssVariantAttrs; pub fn derive(input: DeriveInput) -> Tokens { let name = &input.ident; @@ -19,8 +20,10 @@ pub fn derive(input: DeriveInput) -> Tokens { "Parse is only supported for single-variant enums for now" ); - let variant_attrs = cg::parse_variant_attrs::(variant); - let identifier = cg::to_css_identifier(variant.ident.as_ref()); + let variant_attrs = cg::parse_variant_attrs::(variant); + let identifier = cg::to_css_identifier( + &variant_attrs.keyword.as_ref().unwrap_or(&variant.ident).as_ref(), + ); let ident = &variant.ident; match_body = quote! { @@ -87,11 +90,3 @@ pub fn derive(input: DeriveInput) -> Tokens { #methods_impl } } - -#[darling(attributes(parse), default)] -#[derive(Default, FromVariant)] -struct ParseVariantAttrs { - /// The comma-separated list of aliases this variant should be aliased to at - /// parse time. - aliases: Option, -} diff --git a/components/style_derive/to_css.rs b/components/style_derive/to_css.rs index de48f4612e4..f9ac8fcbdd5 100644 --- a/components/style_derive/to_css.rs +++ b/components/style_derive/to_css.rs @@ -23,10 +23,19 @@ pub fn derive(input: DeriveInput) -> Tokens { if variant_attrs.dimension { assert_eq!(bindings.len(), 1); - assert!(variant_attrs.function.is_none(), "That makes no sense"); + assert!( + variant_attrs.function.is_none() && variant_attrs.keyword.is_none(), + "That makes no sense" + ); } - let mut expr = if !bindings.is_empty() { + let mut expr = if let Some(keyword) = variant_attrs.keyword { + assert!(bindings.is_empty()); + let keyword = keyword.to_string(); + quote! { + ::std::fmt::Write::write_str(dest, #keyword) + } + } else if !bindings.is_empty() { let mut expr = quote! {}; if variant_attrs.iterable { assert_eq!(bindings.len(), 1); @@ -123,11 +132,13 @@ struct CssInputAttrs { #[darling(attributes(css), default)] #[derive(Default, FromVariant)] -struct CssVariantAttrs { - function: Option, - iterable: bool, - comma: bool, - dimension: bool, +pub struct CssVariantAttrs { + pub function: Option, + pub iterable: bool, + pub comma: bool, + pub dimension: bool, + pub keyword: Option, + pub aliases: Option, } #[darling(attributes(css), default)] @@ -136,7 +147,7 @@ struct CssFieldAttrs { ignore_bound: bool, } -struct Function { +pub struct Function { name: Option, } diff --git a/components/style_traits/values.rs b/components/style_traits/values.rs index 56574ac161d..0c3dcc8851b 100644 --- a/components/style_traits/values.rs +++ b/components/style_traits/values.rs @@ -384,69 +384,12 @@ impl_to_css_for_predefined_type!(::cssparser::UnicodeRange); #[macro_export] macro_rules! define_css_keyword_enum { - ($name: ident: values { $( $css: expr => $variant: ident),+, } - aliases { $( $alias: expr => $alias_variant: ident ),+, }) => { - __define_css_keyword_enum__add_optional_traits!($name [ $( $css => $variant ),+ ] - [ $( $alias => $alias_variant ),+ ]); - }; - ($name: ident: values { $( $css: expr => $variant: ident),+, } - aliases { $( $alias: expr => $alias_variant: ident ),* }) => { - __define_css_keyword_enum__add_optional_traits!($name [ $( $css => $variant ),+ ] - [ $( $alias => $alias_variant ),* ]); - }; - ($name: ident: values { $( $css: expr => $variant: ident),+ } - aliases { $( $alias: expr => $alias_variant: ident ),+, }) => { - __define_css_keyword_enum__add_optional_traits!($name [ $( $css => $variant ),+ ] - [ $( $alias => $alias_variant ),+ ]); - }; - ($name: ident: values { $( $css: expr => $variant: ident),+ } - aliases { $( $alias: expr => $alias_variant: ident ),* }) => { - __define_css_keyword_enum__add_optional_traits!($name [ $( $css => $variant ),+ ] - [ $( $alias => $alias_variant ),* ]); - }; - ($name: ident: $( $css: expr => $variant: ident ),+,) => { - __define_css_keyword_enum__add_optional_traits!($name [ $( $css => $variant ),+ ] []); - }; - ($name: ident: $( $css: expr => $variant: ident ),+) => { - __define_css_keyword_enum__add_optional_traits!($name [ $( $css => $variant ),+ ] []); - }; -} - -#[cfg(feature = "servo")] -#[macro_export] -macro_rules! __define_css_keyword_enum__add_optional_traits { - ($name: ident [ $( $css: expr => $variant: ident ),+ ] - [ $( $alias: expr => $alias_variant: ident),* ]) => { - __define_css_keyword_enum__actual! { - $name [ Deserialize, Serialize, MallocSizeOf ] - [ $( $css => $variant ),+ ] - [ $( $alias => $alias_variant ),* ] - } - }; -} - -#[cfg(not(feature = "servo"))] -#[macro_export] -macro_rules! __define_css_keyword_enum__add_optional_traits { - ($name: ident [ $( $css: expr => $variant: ident ),+ ] - [ $( $alias: expr => $alias_variant: ident),* ]) => { - __define_css_keyword_enum__actual! { - $name [ MallocSizeOf ] - [ $( $css => $variant ),+ ] - [ $( $alias => $alias_variant ),* ] - } - }; -} - -#[macro_export] -macro_rules! __define_css_keyword_enum__actual { - ($name: ident [ $( $derived_trait: ident),* ] - [ $( $css: expr => $variant: ident ),+ ] - [ $( $alias: expr => $alias_variant: ident ),* ]) => { - #[allow(non_camel_case_types, missing_docs)] - #[derive(Clone, Copy, Debug, Eq, Hash, PartialEq$(, $derived_trait )* )] + (pub enum $name:ident { $($variant:ident = $css:expr,)+ }) => { + #[allow(missing_docs)] + #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] + #[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq)] pub enum $name { - $( $variant ),+ + $($variant),+ } impl $name { @@ -458,33 +401,40 @@ macro_rules! __define_css_keyword_enum__actual { match *input.next()? { Token::Ident(ref ident) => { Self::from_ident(ident).map_err(|()| { - location.new_unexpected_token_error(Token::Ident(ident.clone())) + location.new_unexpected_token_error( + Token::Ident(ident.clone()), + ) }) } - ref token => Err(location.new_unexpected_token_error(token.clone())) + ref token => { + Err(location.new_unexpected_token_error(token.clone())) + } } } /// Parse this property from an already-tokenized identifier. pub fn from_ident(ident: &str) -> Result<$name, ()> { match_ignore_ascii_case! { ident, - $( $css => Ok($name::$variant), )+ - $( $alias => Ok($name::$alias_variant), )* - _ => Err(()) + $($css => Ok($name::$variant),)+ + _ => Err(()) } } } impl $crate::ToCss for $name { - fn to_css(&self, dest: &mut $crate::CssWriter) -> ::std::fmt::Result - where W: ::std::fmt::Write + fn to_css( + &self, + dest: &mut $crate::CssWriter, + ) -> ::std::fmt::Result + where + W: ::std::fmt::Write, { match *self { $( $name::$variant => ::std::fmt::Write::write_str(dest, $css) ),+ } } } - } + }; } /// Helper types for the handling of specified values. diff --git a/components/style_traits/viewport.rs b/components/style_traits/viewport.rs index e2f8c6baf6f..75dd13870e0 100644 --- a/components/style_traits/viewport.rs +++ b/components/style_traits/viewport.rs @@ -10,14 +10,20 @@ use euclid::TypedSize2D; #[allow(unused_imports)] use std::ascii::AsciiExt; use std::fmt::{self, Write}; -define_css_keyword_enum!(UserZoom: - "zoom" => Zoom, - "fixed" => Fixed); +define_css_keyword_enum! { + pub enum UserZoom { + Zoom = "zoom", + Fixed = "fixed", + } +} -define_css_keyword_enum!(Orientation: - "auto" => Auto, - "portrait" => Portrait, - "landscape" => Landscape); +define_css_keyword_enum! { + pub enum Orientation { + Auto = "auto", + Portrait = "portrait", + Landscape = "landscape", + } +} /// A set of viewport descriptors: /// diff --git a/tests/unit/style/parsing/border.rs b/tests/unit/style/parsing/border.rs index e92b59dd2fb..0eadbec4f31 100644 --- a/tests/unit/style/parsing/border.rs +++ b/tests/unit/style/parsing/border.rs @@ -168,16 +168,16 @@ fn border_image_outset_should_return_length_on_length_zero() { fn test_border_style() { use style::values::specified::BorderStyle; - assert_roundtrip_with_context!(BorderStyle::parse, r#"none"#); - assert_roundtrip_with_context!(BorderStyle::parse, r#"hidden"#); - assert_roundtrip_with_context!(BorderStyle::parse, r#"solid"#); - assert_roundtrip_with_context!(BorderStyle::parse, r#"double"#); - assert_roundtrip_with_context!(BorderStyle::parse, r#"dotted"#); - assert_roundtrip_with_context!(BorderStyle::parse, r#"dashed"#); - assert_roundtrip_with_context!(BorderStyle::parse, r#"groove"#); - assert_roundtrip_with_context!(BorderStyle::parse, r#"ridge"#); - assert_roundtrip_with_context!(BorderStyle::parse, r#"inset"#); - assert_roundtrip_with_context!(BorderStyle::parse, r#"outset"#); + assert_roundtrip_with_context!(::parse, r#"none"#); + assert_roundtrip_with_context!(::parse, r#"hidden"#); + assert_roundtrip_with_context!(::parse, r#"solid"#); + assert_roundtrip_with_context!(::parse, r#"double"#); + assert_roundtrip_with_context!(::parse, r#"dotted"#); + assert_roundtrip_with_context!(::parse, r#"dashed"#); + assert_roundtrip_with_context!(::parse, r#"groove"#); + assert_roundtrip_with_context!(::parse, r#"ridge"#); + assert_roundtrip_with_context!(::parse, r#"inset"#); + assert_roundtrip_with_context!(::parse, r#"outset"#); } #[test]