diff --git a/components/style/macros.rs b/components/style/macros.rs index b4a27415162..c766d414001 100644 --- a/components/style/macros.rs +++ b/components/style/macros.rs @@ -84,20 +84,10 @@ macro_rules! define_keyword_type { ($name: ident, $css: expr) => { #[allow(missing_docs)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] - #[derive(Clone, ComputeSquaredDistance, Copy, PartialEq, ToCss)] + #[derive(Animate, Clone, ComputeSquaredDistance, Copy, PartialEq)] + #[derive(ToAnimatedZero, ToCss)] pub struct $name; - impl $crate::values::animated::Animate for $name { - #[inline] - fn animate( - &self, - _other: &Self, - _procedure: $crate::values::animated::Procedure, - ) -> Result { - Ok($name) - } - } - impl fmt::Debug for $name { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, $css) @@ -115,10 +105,5 @@ macro_rules! define_keyword_type { impl $crate::values::computed::ComputedValueAsSpecified for $name {} impl $crate::values::animated::AnimatedValueAsComputed for $name {} no_viewport_percentage!($name); - - impl $crate::values::animated::ToAnimatedZero for $name { - #[inline] - fn to_animated_zero(&self) -> Result { Ok($name) } - } }; } diff --git a/components/style/properties/helpers.mako.rs b/components/style/properties/helpers.mako.rs index b7667e64421..e553db36d90 100644 --- a/components/style/properties/helpers.mako.rs +++ b/components/style/properties/helpers.mako.rs @@ -122,7 +122,7 @@ #[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[derive(Clone, Debug, PartialEq)] % if need_animatable or animation_value_type == "ComputedValue": - #[derive(ComputeSquaredDistance)] + #[derive(Animate, ComputeSquaredDistance)] % endif pub struct T( % if allow_empty and allow_empty != "NotInitial": @@ -133,14 +133,7 @@ ); % if need_animatable or animation_value_type == "ComputedValue": - use values::animated::{Animate, Procedure, ToAnimatedZero}; - - impl Animate for T { - #[inline] - fn animate(&self, other: &Self, procedure: Procedure) -> Result { - Ok(T(self.0.animate(&other.0, procedure)?)) - } - } + use values::animated::{ToAnimatedZero}; impl ToAnimatedZero for T { #[inline] diff --git a/components/style/properties/helpers/animated_properties.mako.rs b/components/style/properties/helpers/animated_properties.mako.rs index b30bb25623d..a97b8e26042 100644 --- a/components/style/properties/helpers/animated_properties.mako.rs +++ b/components/style/properties/helpers/animated_properties.mako.rs @@ -54,7 +54,7 @@ use values::computed::{PositiveIntegerOrAuto, ToComputedValue}; use values::computed::length::{NonNegativeLengthOrAuto, NonNegativeLengthOrNormal}; use values::computed::length::NonNegativeLengthOrPercentage; use values::distance::{ComputeSquaredDistance, SquaredDistance}; -use values::generics::{GreaterThanOrEqualToOne, NonNegative}; +use values::generics::NonNegative; use values::generics::effects::Filter; use values::generics::position as generic_position; use values::generics::svg::{SVGLength, SvgLengthOrPercentageOrNumber, SVGPaint}; @@ -879,23 +879,6 @@ impl Animate for LengthOrPercentage { } } -impl ToAnimatedZero for LengthOrPercentage { - #[inline] - fn to_animated_zero(&self) -> Result { - match *self { - LengthOrPercentage::Length(ref length) => { - Ok(LengthOrPercentage::Length(length.to_animated_zero()?)) - }, - LengthOrPercentage::Percentage(ref percentage) => { - Ok(LengthOrPercentage::Percentage(percentage.to_animated_zero()?)) - }, - LengthOrPercentage::Calc(ref calc) => { - Ok(LengthOrPercentage::Calc(calc.to_animated_zero()?)) - }, - } - } -} - /// https://drafts.csswg.org/css-transitions/#animtype-lpcalc impl Animate for LengthOrPercentageOrAuto { #[inline] @@ -1120,50 +1103,9 @@ impl Into for f64 { } } -impl Animate for generic_position::Position -where - H: Animate, - V: Animate, -{ - #[inline] - fn animate(&self, other: &Self, procedure: Procedure) -> Result { - Ok(generic_position::Position { - horizontal: self.horizontal.animate(&other.horizontal, procedure)?, - vertical: self.vertical.animate(&other.vertical, procedure)?, - }) - } -} - -impl ToAnimatedZero for generic_position::Position -where - H: ToAnimatedZero, - V: ToAnimatedZero, -{ - #[inline] - fn to_animated_zero(&self) -> Result { - Ok(generic_position::Position { - horizontal: self.horizontal.to_animated_zero()?, - vertical: self.vertical.to_animated_zero()?, - }) - } -} - impl RepeatableListAnimatable for generic_position::Position where H: RepeatableListAnimatable, V: RepeatableListAnimatable {} -/// https://drafts.csswg.org/css-transitions/#animtype-rect -impl Animate for ClipRect { - #[inline] - fn animate(&self, other: &Self, procedure: Procedure) -> Result { - Ok(ClipRect { - top: self.top.animate(&other.top, procedure)?, - right: self.right.animate(&other.right, procedure)?, - bottom: self.bottom.animate(&other.bottom, procedure)?, - left: self.left.animate(&other.left, procedure)?, - }) - } -} - impl ToAnimatedZero for ClipRect { #[inline] fn to_animated_zero(&self) -> Result { Err(()) } @@ -1353,8 +1295,8 @@ pub struct InnerMatrix2D { } /// A 2d translation function. -#[derive(Clone, ComputeSquaredDistance, Copy, Debug)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] +#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug)] pub struct Translate2D(f32, f32); /// A 2d scale function. @@ -1387,15 +1329,6 @@ impl Animate for InnerMatrix2D { } } -impl Animate for Translate2D { - fn animate(&self, other: &Self, procedure: Procedure) -> Result { - Ok(Translate2D( - self.0.animate(&other.0, procedure)?, - self.1.animate(&other.1, procedure)?, - )) - } -} - impl Animate for Scale2D { fn animate(&self, other: &Self, procedure: Procedure) -> Result { Ok(Scale2D( @@ -1627,8 +1560,8 @@ impl From for RawGeckoGfxMatrix4x4 { } /// A 3d translation. -#[derive(Clone, ComputeSquaredDistance, Copy, Debug)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] +#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug)] pub struct Translate3D(f32, f32, f32); /// A 3d scale function. @@ -1637,8 +1570,8 @@ pub struct Translate3D(f32, f32, f32); pub struct Scale3D(f32, f32, f32); /// A 3d skew function. -#[derive(Clone, Copy, Debug)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] +#[derive(Animate, Clone, Copy, Debug)] pub struct Skew(f32, f32, f32); /// A 3d perspective transformation. @@ -1920,16 +1853,6 @@ fn cross(row1: [f32; 3], row2: [f32; 3]) -> [f32; 3] { ] } -impl Animate for Translate3D { - fn animate(&self, other: &Self, procedure: Procedure) -> Result { - Ok(Translate3D( - self.0.animate(&other.0, procedure)?, - self.1.animate(&other.1, procedure)?, - self.2.animate(&other.2, procedure)?, - )) - } -} - impl Animate for Scale3D { fn animate(&self, other: &Self, procedure: Procedure) -> Result { Ok(Scale3D( @@ -1940,16 +1863,6 @@ impl Animate for Scale3D { } } -impl Animate for Skew { - fn animate(&self, other: &Self, procedure: Procedure) -> Result { - Ok(Skew( - self.0.animate(&other.0, procedure)?, - self.1.animate(&other.1, procedure)?, - self.2.animate(&other.2, procedure)?, - )) - } -} - impl ComputeSquaredDistance for Skew { // We have to use atan() to convert the skew factors into skew angles, so implement // ComputeSquaredDistance manually. @@ -2464,25 +2377,6 @@ impl ToAnimatedZero for TransformList { } } -impl Animate for Either -where - T: Animate, - U: Animate, -{ - #[inline] - fn animate(&self, other: &Self, procedure: Procedure) -> Result { - match (self, other) { - (&Either::First(ref this), &Either::First(ref other)) => { - Ok(Either::First(this.animate(other, procedure)?)) - }, - (&Either::Second(ref this), &Either::Second(ref other)) => { - Ok(Either::Second(this.animate(other, procedure)?)) - }, - _ => Err(()), - } - } -} - impl ToAnimatedZero for Either where A: ToAnimatedZero, @@ -2689,28 +2583,6 @@ where } } -impl ToAnimatedZero for SvgLengthOrPercentageOrNumber -where - L: ToAnimatedZero, - N: ToAnimatedZero, -{ - #[inline] - fn to_animated_zero(&self) -> Result { - match *self { - SvgLengthOrPercentageOrNumber::LengthOrPercentage(ref lop) => { - Ok(SvgLengthOrPercentageOrNumber::LengthOrPercentage( - lop.to_animated_zero()?, - )) - }, - SvgLengthOrPercentageOrNumber::Number(ref num) => { - Ok(SvgLengthOrPercentageOrNumber::Number( - num.to_animated_zero()?, - )) - }, - } - } -} - impl Animate for SVGLength where L: Animate + Clone, @@ -2732,21 +2604,6 @@ where } } -impl ToAnimatedZero for SVGLength -where - L: ToAnimatedZero, -{ - #[inline] - fn to_animated_zero(&self) -> Result { - match *self { - SVGLength::Length(ref length) => { - Ok(SVGLength::Length(length.to_animated_zero()?)) - }, - SVGLength::ContextValue => Ok(SVGLength::ContextValue), - } - } -} - /// https://www.w3.org/TR/SVG11/painting.html#StrokeDasharrayProperty impl Animate for SVGStrokeDashArray where @@ -2772,7 +2629,7 @@ where impl ToAnimatedZero for SVGStrokeDashArray where - L: Clone + ToAnimatedZero + L: ToAnimatedZero, { #[inline] fn to_animated_zero(&self) -> Result { @@ -2808,19 +2665,6 @@ where } } -impl ToAnimatedZero for SVGOpacity - where OpacityType: ToAnimatedZero + Clone -{ - #[inline] - fn to_animated_zero(&self) -> Result { - match self { - &SVGOpacity::Opacity(ref opacity) => - opacity.to_animated_zero().map(SVGOpacity::Opacity), - other => Ok(other.clone()), - } - } -} - <% FILTER_FUNCTIONS = [ 'Blur', 'Brightness', 'Contrast', 'Grayscale', 'HueRotate', 'Invert', 'Opacity', 'Saturate', @@ -2877,7 +2721,6 @@ impl ToAnimatedZero for AnimatedFilter { } } - // FIXME(nox): This should be derived. impl ComputeSquaredDistance for AnimatedFilter { fn compute_squared_distance(&self, other: &Self) -> Result { @@ -2993,41 +2836,3 @@ sorted_shorthands = [(p, position) for position, p in enumerate(sorted_shorthand % endfor } } - -impl Animate for NonNegative -where - T: Animate, -{ - #[inline] - fn animate(&self, other: &Self, procedure: Procedure) -> Result { - Ok(NonNegative(self.0.animate(&other.0, procedure)?)) - } -} - -impl ToAnimatedZero for NonNegative - where T: ToAnimatedZero -{ - #[inline] - fn to_animated_zero(&self) -> Result { - self.0.to_animated_zero().map(NonNegative::) - } -} - -impl Animate for GreaterThanOrEqualToOne -where - T: Animate, -{ - #[inline] - fn animate(&self, other: &Self, procedure: Procedure) -> Result { - Ok(GreaterThanOrEqualToOne(self.0.animate(&other.0, procedure)?)) - } -} - -impl ToAnimatedZero for GreaterThanOrEqualToOne - where T: ToAnimatedZero -{ - #[inline] - fn to_animated_zero(&self) -> Result { - self.0.to_animated_zero().map(GreaterThanOrEqualToOne::) - } -} diff --git a/components/style/properties/longhand/inherited_table.mako.rs b/components/style/properties/longhand/inherited_table.mako.rs index 3cee357a99a..b98cab4204a 100644 --- a/components/style/properties/longhand/inherited_table.mako.rs +++ b/components/style/properties/longhand/inherited_table.mako.rs @@ -26,27 +26,16 @@ ${helpers.single_keyword("caption-side", "top bottom", use values::specified::length::NonNegativeLength; pub mod computed_value { - use values::animated::{Animate, Procedure, ToAnimatedValue, ToAnimatedZero}; + use values::animated::{ToAnimatedValue, ToAnimatedZero}; use values::computed::NonNegativeAu; #[cfg_attr(feature = "servo", derive(HeapSizeOf))] - #[derive(Clone, ComputeSquaredDistance, Copy, Debug, PartialEq, ToCss)] + #[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, PartialEq, ToCss)] pub struct T { pub horizontal: NonNegativeAu, pub vertical: NonNegativeAu, } - /// https://drafts.csswg.org/css-transitions/#animtype-simple-list - impl Animate for T { - #[inline] - fn animate(&self, other: &Self, procedure: Procedure) -> Result { - Ok(T { - horizontal: self.horizontal.animate(&other.horizontal, procedure)?, - vertical: self.vertical.animate(&other.vertical, procedure)?, - }) - } - } - impl ToAnimatedZero for T { #[inline] fn to_animated_zero(&self) -> Result { Err(()) } diff --git a/components/style/values/animated/color.rs b/components/style/values/animated/color.rs index ad77feb10dd..5c891709374 100644 --- a/components/style/values/animated/color.rs +++ b/components/style/values/animated/color.rs @@ -12,7 +12,7 @@ use values::distance::{ComputeSquaredDistance, SquaredDistance}; /// Unlike in computed values, each component value may exceed the /// range `[0.0, 1.0]`. #[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[derive(Clone, Copy, Debug, PartialEq)] +#[derive(Clone, Copy, Debug, PartialEq, ToAnimatedZero)] pub struct RGBA { /// The red component. pub red: f32, @@ -69,13 +69,6 @@ impl ComputeSquaredDistance for RGBA { } } -impl ToAnimatedZero for RGBA { - #[inline] - fn to_animated_zero(&self) -> Result { - Ok(RGBA::transparent()) - } -} - #[allow(missing_docs)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[derive(Clone, Copy, Debug, PartialEq)] diff --git a/components/style/values/animated/effects.rs b/components/style/values/animated/effects.rs index e4419ec9304..cdde2894549 100644 --- a/components/style/values/animated/effects.rs +++ b/components/style/values/animated/effects.rs @@ -139,6 +139,7 @@ impl ToAnimatedValue for ComputedTextShadowList { } } +// FIXME(nox): This could be derived if we implement Animate for bool. impl Animate for BoxShadow { #[inline] fn animate(&self, other: &Self, procedure: Procedure) -> Result { @@ -211,27 +212,3 @@ impl ToAnimatedZero for FilterList { Ok(FilterList(vec![])) } } - -impl Animate for SimpleShadow { - #[inline] - fn animate(&self, other: &Self, procedure: Procedure) -> Result { - Ok(SimpleShadow { - color: self.color.animate(&other.color, procedure)?, - horizontal: self.horizontal.animate(&other.horizontal, procedure)?, - vertical: self.vertical.animate(&other.vertical, procedure)?, - blur: self.blur.animate(&other.blur, procedure)?, - }) - } -} - -impl ToAnimatedZero for SimpleShadow { - #[inline] - fn to_animated_zero(&self) -> Result { - Ok(SimpleShadow { - color: self.color.to_animated_zero()?, - horizontal: self.horizontal.to_animated_zero()?, - vertical: self.vertical.to_animated_zero()?, - blur: self.blur.to_animated_zero()?, - }) - } -} diff --git a/components/style/values/computed/angle.rs b/components/style/values/computed/angle.rs index 3478553666f..d5461d1cbf9 100644 --- a/components/style/values/computed/angle.rs +++ b/components/style/values/computed/angle.rs @@ -8,12 +8,12 @@ use std::{f32, f64, fmt}; use std::f64::consts::PI; use style_traits::ToCss; use values::CSSFloat; -use values::animated::{Animate, Procedure, ToAnimatedZero}; +use values::animated::{Animate, Procedure}; use values::distance::{ComputeSquaredDistance, SquaredDistance}; /// A computed angle. #[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))] -#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, PartialOrd)] +#[derive(Clone, Copy, Debug, HasViewportPercentage, PartialEq, PartialOrd, ToAnimatedZero)] pub enum Angle { /// An angle with degree unit. Degree(CSSFloat), @@ -85,18 +85,6 @@ impl Animate for Angle { } } -impl ToAnimatedZero for Angle { - #[inline] - fn to_animated_zero(&self) -> Result { - match *self { - Angle::Degree(ref this) => Ok(Angle::Degree(this.to_animated_zero()?)), - Angle::Gradian(ref this) => Ok(Angle::Gradian(this.to_animated_zero()?)), - Angle::Radian(ref this) => Ok(Angle::Radian(this.to_animated_zero()?)), - Angle::Turn(ref this) => Ok(Angle::Turn(this.to_animated_zero()?)), - } - } -} - impl ComputeSquaredDistance for Angle { #[inline] fn compute_squared_distance(&self, other: &Self) -> Result { diff --git a/components/style/values/computed/length.rs b/components/style/values/computed/length.rs index 365e377614a..945ce8b841f 100644 --- a/components/style/values/computed/length.rs +++ b/components/style/values/computed/length.rs @@ -286,7 +286,7 @@ impl ToComputedValue for specified::CalcLengthOrPercentage { #[allow(missing_docs)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[derive(Clone, Copy, PartialEq, ToCss)] +#[derive(Clone, Copy, PartialEq, ToAnimatedZero, ToCss)] pub enum LengthOrPercentage { Length(Au), Percentage(Percentage), diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index 664fdcbbe86..912c35238a9 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -439,7 +439,7 @@ pub type NonNegativeLengthOrPercentageOrNumber = Either, diff --git a/components/style/values/computed/percentage.rs b/components/style/values/computed/percentage.rs index 01f8195456c..533bd751616 100644 --- a/components/style/values/computed/percentage.rs +++ b/components/style/values/computed/percentage.rs @@ -7,11 +7,11 @@ use std::fmt; use style_traits::ToCss; use values::{CSSFloat, serialize_percentage}; -use values::animated::{Animate, Procedure, ToAnimatedZero}; /// A computed percentage. -#[derive(Clone, ComputeSquaredDistance, Copy, Debug, Default, HasViewportPercentage, PartialEq, PartialOrd)] #[cfg_attr(feature = "servo", derive(Deserialize, HeapSizeOf, Serialize))] +#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, Default)] +#[derive(HasViewportPercentage, PartialEq, PartialOrd, ToAnimatedZero)] pub struct Percentage(pub CSSFloat); impl Percentage { @@ -34,21 +34,6 @@ impl Percentage { } } -/// https://drafts.csswg.org/css-transitions/#animtype-percentage -impl Animate for Percentage { - #[inline] - fn animate(&self, other: &Self, procedure: Procedure) -> Result { - Ok(Percentage(self.0.animate(&other.0, procedure)?)) - } -} - -impl ToAnimatedZero for Percentage { - #[inline] - fn to_animated_zero(&self) -> Result { - Ok(Percentage(0.)) - } -} - impl ToCss for Percentage { fn to_css(&self, dest: &mut W) -> fmt::Result where diff --git a/components/style/values/computed/text.rs b/components/style/values/computed/text.rs index 30d56278765..2c81d4d4d3d 100644 --- a/components/style/values/computed/text.rs +++ b/components/style/values/computed/text.rs @@ -5,7 +5,7 @@ //! Computed types for text properties. use values::{CSSInteger, CSSFloat}; -use values::animated::{Animate, Procedure, ToAnimatedZero}; +use values::animated::ToAnimatedZero; use values::computed::{NonNegativeAu, NonNegativeNumber}; use values::computed::length::{Length, LengthOrPercentage}; use values::generics::text::InitialLetter as GenericInitialLetter; @@ -24,28 +24,6 @@ pub type WordSpacing = Spacing; /// A computed value for the `line-height` property. pub type LineHeight = GenericLineHeight; -impl Animate for LineHeight { - #[inline] - fn animate(&self, other: &Self, procedure: Procedure) -> Result { - match (self, other) { - (&GenericLineHeight::Length(ref this), &GenericLineHeight::Length(ref other)) => { - Ok(GenericLineHeight::Length(this.animate(other, procedure)?)) - }, - (&GenericLineHeight::Number(ref this), &GenericLineHeight::Number(ref other)) => { - Ok(GenericLineHeight::Number(this.animate(other, procedure)?)) - }, - (&GenericLineHeight::Normal, &GenericLineHeight::Normal) => { - Ok(GenericLineHeight::Normal) - }, - #[cfg(feature = "gecko")] - (&GenericLineHeight::MozBlockHeight, &GenericLineHeight::MozBlockHeight) => { - Ok(GenericLineHeight::MozBlockHeight) - }, - _ => Err(()), - } - } -} - impl ToAnimatedZero for LineHeight { #[inline] fn to_animated_zero(&self) -> Result { Err(()) } diff --git a/components/style/values/computed/transform.rs b/components/style/values/computed/transform.rs index 1d4495bf94e..ab7e1477d8f 100644 --- a/components/style/values/computed/transform.rs +++ b/components/style/values/computed/transform.rs @@ -4,7 +4,6 @@ //! Computed types for CSS values that are related to transformations. -use values::animated::{Animate, Procedure, ToAnimatedZero}; use values::computed::{Length, LengthOrPercentage, Number, Percentage}; use values::generics::transform::TimingFunction as GenericTimingFunction; use values::generics::transform::TransformOrigin as GenericTransformOrigin; @@ -26,25 +25,3 @@ impl TransformOrigin { ) } } - -impl Animate for TransformOrigin { - #[inline] - fn animate(&self, other: &Self, procedure: Procedure) -> Result { - Ok(Self::new( - self.horizontal.animate(&other.horizontal, procedure)?, - self.vertical.animate(&other.vertical, procedure)?, - self.depth.animate(&other.depth, procedure)?, - )) - } -} - -impl ToAnimatedZero for TransformOrigin { - #[inline] - fn to_animated_zero(&self) -> Result { - Ok(Self::new( - self.horizontal.to_animated_zero()?, - self.vertical.to_animated_zero()?, - self.depth.to_animated_zero()?, - )) - } -} diff --git a/components/style/values/generics/basic_shape.rs b/components/style/values/generics/basic_shape.rs index 517062b593b..99de026d706 100644 --- a/components/style/values/generics/basic_shape.rs +++ b/components/style/values/generics/basic_shape.rs @@ -54,7 +54,8 @@ pub enum ShapeSource { #[allow(missing_docs)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[derive(Clone, ComputeSquaredDistance, Debug, PartialEq, ToComputedValue, ToCss)] +#[derive(Animate, Clone, ComputeSquaredDistance, Debug, PartialEq)] +#[derive(ToComputedValue, ToCss)] pub enum BasicShape { Inset(InsetRect), Circle(Circle), @@ -65,7 +66,7 @@ pub enum BasicShape { /// https://drafts.csswg.org/css-shapes/#funcdef-inset #[allow(missing_docs)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[derive(Clone, ComputeSquaredDistance, Debug, PartialEq, ToComputedValue)] +#[derive(Animate, Clone, ComputeSquaredDistance, Debug, PartialEq, ToComputedValue)] pub struct InsetRect { pub rect: Rect, pub round: Option>, @@ -74,7 +75,7 @@ pub struct InsetRect { /// https://drafts.csswg.org/css-shapes/#funcdef-circle #[allow(missing_docs)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[derive(Clone, ComputeSquaredDistance, Copy, Debug, PartialEq, ToComputedValue)] +#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, PartialEq, ToComputedValue)] pub struct Circle { pub position: Position, pub radius: ShapeRadius, @@ -83,7 +84,7 @@ pub struct Circle { /// https://drafts.csswg.org/css-shapes/#funcdef-ellipse #[allow(missing_docs)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[derive(Clone, ComputeSquaredDistance, Copy, Debug, PartialEq, ToComputedValue)] +#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, PartialEq, ToComputedValue)] pub struct Ellipse { pub position: Position, pub semiaxis_x: ShapeRadius, @@ -122,6 +123,8 @@ define_css_keyword_enum!(FillRule: ); add_impls_for_keyword_enum!(FillRule); +// FIXME(nox): This should be derivable, but we need to implement Animate +// on the T types. impl Animate for ShapeSource where B: Animate, @@ -174,43 +177,6 @@ impl HasViewportPercentage for ShapeSource { fn has_viewport_percentage(&self) -> bool { false } } -impl Animate for BasicShape -where - H: Animate, - V: Animate, - L: Animate + Copy, -{ - fn animate(&self, other: &Self, procedure: Procedure) -> Result { - match (self, other) { - (&BasicShape::Circle(ref this), &BasicShape::Circle(ref other)) => { - Ok(BasicShape::Circle(this.animate(other, procedure)?)) - }, - (&BasicShape::Ellipse(ref this), &BasicShape::Ellipse(ref other)) => { - Ok(BasicShape::Ellipse(this.animate(other, procedure)?)) - }, - (&BasicShape::Inset(ref this), &BasicShape::Inset(ref other)) => { - Ok(BasicShape::Inset(this.animate(other, procedure)?)) - }, - (&BasicShape::Polygon(ref this), &BasicShape::Polygon(ref other)) => { - Ok(BasicShape::Polygon(this.animate(other, procedure)?)) - }, - _ => Err(()), - } - } -} - -impl Animate for InsetRect -where - L: Animate + Copy, -{ - fn animate(&self, other: &Self, procedure: Procedure) -> Result { - Ok(InsetRect { - rect: self.rect.animate(&other.rect, procedure)?, - round: self.round.animate(&other.round, procedure)?, - }) - } -} - impl ToCss for InsetRect where L: ToCss + PartialEq { @@ -225,35 +191,6 @@ impl ToCss for InsetRect } } -impl Animate for Circle -where - H: Animate, - V: Animate, - L: Animate, -{ - fn animate(&self, other: &Self, procedure: Procedure) -> Result { - Ok(Circle { - position: self.position.animate(&other.position, procedure)?, - radius: self.radius.animate(&other.radius, procedure)?, - }) - } -} - -impl Animate for Ellipse -where - H: Animate, - V: Animate, - L: Animate, -{ - fn animate(&self, other: &Self, procedure: Procedure) -> Result { - Ok(Ellipse { - position: self.position.animate(&other.position, procedure)?, - semiaxis_x: self.semiaxis_x.animate(&other.semiaxis_x, procedure)?, - semiaxis_y: self.semiaxis_y.animate(&other.semiaxis_y, procedure)?, - }) - } -} - impl Animate for ShapeRadius where L: Animate, diff --git a/components/style/values/generics/border.rs b/components/style/values/generics/border.rs index 1ac6f7d5433..052ef579099 100644 --- a/components/style/values/generics/border.rs +++ b/components/style/values/generics/border.rs @@ -7,7 +7,6 @@ use euclid::Size2D; use std::fmt; use style_traits::ToCss; -use values::animated::{Animate, Procedure}; use values::generics::rect::Rect; /// A generic value for a single side of a `border-image-width` property. @@ -36,7 +35,8 @@ pub struct BorderImageSlice { /// /// https://drafts.csswg.org/css-backgrounds-3/#border-radius #[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[derive(Clone, ComputeSquaredDistance, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)] +#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, HasViewportPercentage)] +#[derive(PartialEq, ToComputedValue)] pub struct BorderRadius { /// The top left radius. pub top_left: BorderCornerRadius, @@ -50,7 +50,8 @@ pub struct BorderRadius { /// A generic value for `border-*-radius` longhand properties. #[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[derive(Clone, ComputeSquaredDistance, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)] +#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, HasViewportPercentage)] +#[derive(PartialEq, ToComputedValue)] pub struct BorderCornerRadius(pub Size2D); impl From for BorderImageSlice @@ -113,20 +114,6 @@ impl BorderRadius } } -impl Animate for BorderRadius -where - L: Animate + Copy, -{ - fn animate(&self, other: &Self, procedure: Procedure) -> Result { - Ok(BorderRadius::new( - self.top_left.animate(&other.top_left, procedure)?, - self.top_right.animate(&other.top_right, procedure)?, - self.bottom_right.animate(&other.bottom_right, procedure)?, - self.bottom_left.animate(&other.bottom_left, procedure)?, - )) - } -} - impl ToCss for BorderRadius where L: PartialEq + ToCss { @@ -159,16 +146,6 @@ impl From for BorderCornerRadius { } } -impl Animate for BorderCornerRadius -where - L: Animate + Copy, -{ - #[inline] - fn animate(&self, other: &Self, procedure: Procedure) -> Result { - Ok(BorderCornerRadius(self.0.animate(&other.0, procedure)?)) - } -} - impl ToCss for BorderCornerRadius where L: ToCss, { diff --git a/components/style/values/generics/effects.rs b/components/style/values/generics/effects.rs index cff8d87c078..3004c21f9b2 100644 --- a/components/style/values/generics/effects.rs +++ b/components/style/values/generics/effects.rs @@ -65,7 +65,8 @@ pub enum Filter { /// Contrary to the canonical order from the spec, the color is serialised /// first, like in Gecko and Webkit. #[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[derive(Clone, ComputeSquaredDistance, Debug, HasViewportPercentage, PartialEq, ToAnimatedValue, ToCss)] +#[derive(Animate, Clone, ComputeSquaredDistance, Debug, HasViewportPercentage)] +#[derive(PartialEq, ToAnimatedValue, ToAnimatedZero, ToCss)] pub struct SimpleShadow { /// Color. pub color: Color, diff --git a/components/style/values/generics/mod.rs b/components/style/values/generics/mod.rs index b097b0f85de..0638743da61 100644 --- a/components/style/values/generics/mod.rs +++ b/components/style/values/generics/mod.rs @@ -268,12 +268,12 @@ impl ToCss for FontSettingTagFloat { /// A wrapper of Non-negative values. #[cfg_attr(feature = "servo", derive(Deserialize, HeapSizeOf, Serialize))] -#[derive(Clone, ComputeSquaredDistance, Copy, Debug, HasViewportPercentage)] -#[derive(PartialEq, PartialOrd, ToComputedValue, ToCss)] +#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, HasViewportPercentage)] +#[derive(PartialEq, PartialOrd, ToAnimatedZero, ToComputedValue, ToCss)] pub struct NonNegative(pub T); /// A wrapper of greater-than-or-equal-to-one values. #[cfg_attr(feature = "servo", derive(Deserialize, HeapSizeOf, Serialize))] -#[derive(Clone, ComputeSquaredDistance, Copy, Debug, HasViewportPercentage)] -#[derive(PartialEq, PartialOrd, ToComputedValue, ToCss)] +#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, HasViewportPercentage)] +#[derive(PartialEq, PartialOrd, ToAnimatedZero, ToComputedValue, ToCss)] pub struct GreaterThanOrEqualToOne(pub T); diff --git a/components/style/values/generics/position.rs b/components/style/values/generics/position.rs index 503cb9a1563..5a014ca62fd 100644 --- a/components/style/values/generics/position.rs +++ b/components/style/values/generics/position.rs @@ -7,7 +7,8 @@ /// A generic type for representing a CSS [position](https://drafts.csswg.org/css-values/#position). #[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[derive(Clone, ComputeSquaredDistance, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)] +#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug)] +#[derive(HasViewportPercentage, PartialEq, ToAnimatedZero, ToComputedValue)] pub struct Position { /// The horizontal component of position. pub horizontal: H, diff --git a/components/style/values/generics/rect.rs b/components/style/values/generics/rect.rs index 6eaaa5a48c4..7c5a7fabfb3 100644 --- a/components/style/values/generics/rect.rs +++ b/components/style/values/generics/rect.rs @@ -8,12 +8,12 @@ use cssparser::Parser; use parser::{Parse, ParserContext}; use std::fmt; use style_traits::{ToCss, ParseError}; -use values::animated::{Animate, Procedure}; /// A CSS value made of four components, where its `ToCss` impl will try to /// serialize as few components as possible, like for example in `border-width`. -#[derive(Clone, ComputeSquaredDistance, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] +#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug)] +#[derive(HasViewportPercentage, PartialEq, ToComputedValue)] pub struct Rect(pub T, pub T, pub T, pub T); impl Rect { @@ -52,20 +52,6 @@ impl Rect } } -impl Animate for Rect -where - L: Animate, -{ - fn animate(&self, other: &Self, procedure: Procedure) -> Result { - Ok(Rect( - self.0.animate(&other.0, procedure)?, - self.1.animate(&other.1, procedure)?, - self.2.animate(&other.2, procedure)?, - self.3.animate(&other.3, procedure)?, - )) - } -} - impl From for Rect where T: Clone { diff --git a/components/style/values/generics/svg.rs b/components/style/values/generics/svg.rs index c393f70dd70..f8362a7cb9e 100644 --- a/components/style/values/generics/svg.rs +++ b/components/style/values/generics/svg.rs @@ -102,12 +102,12 @@ impl Parse for SVGPaint { +#[derive(ToAnimatedZero, ToCss, ToComputedValue)] +pub enum SvgLengthOrPercentageOrNumber { /// | - LengthOrPercentage(LengthOrPercentageType), + LengthOrPercentage(LengthOrPercentage), /// - Number(NumberType), + Number(Number), } impl ComputeSquaredDistance for SvgLengthOrPercentageOrNumber @@ -184,7 +184,8 @@ impl Parse for /// An SVG length value supports `context-value` in addition to length. #[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[derive(Clone, ComputeSquaredDistance, Copy, Debug, PartialEq)] -#[derive(HasViewportPercentage, ToAnimatedValue, ToComputedValue, ToCss)] +#[derive(HasViewportPercentage, ToAnimatedValue, ToAnimatedZero)] +#[derive(ToComputedValue, ToCss)] pub enum SVGLength { /// ` | | ` Length(LengthType), @@ -228,7 +229,8 @@ impl ToCss for SVGStrokeDashArray where LengthType: ToCs /// An SVG opacity value accepts `context-{fill,stroke}-opacity` in /// addition to opacity value. #[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[derive(Clone, ComputeSquaredDistance, Copy, Debug, PartialEq, HasViewportPercentage, ToComputedValue, ToCss)] +#[derive(Clone, ComputeSquaredDistance, Copy, Debug, HasViewportPercentage)] +#[derive(PartialEq, ToAnimatedZero, ToComputedValue, ToCss)] pub enum SVGOpacity { /// `` Opacity(OpacityType), diff --git a/components/style/values/generics/text.rs b/components/style/values/generics/text.rs index f78ab594c5e..c1d55bd541e 100644 --- a/components/style/values/generics/text.rs +++ b/components/style/values/generics/text.rs @@ -110,7 +110,8 @@ where /// A generic value for the `line-height` property. #[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[derive(Clone, ComputeSquaredDistance, Copy, Debug, HasViewportPercentage, PartialEq, ToAnimatedValue, ToCss)] +#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug)] +#[derive(HasViewportPercentage, PartialEq, ToAnimatedValue, ToCss)] pub enum LineHeight { /// `normal` Normal, diff --git a/components/style/values/generics/transform.rs b/components/style/values/generics/transform.rs index 32f37caec12..82e18f436ff 100644 --- a/components/style/values/generics/transform.rs +++ b/components/style/values/generics/transform.rs @@ -24,7 +24,8 @@ pub struct Matrix { /// A generic transform origin. #[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[derive(Clone, ComputeSquaredDistance, Copy, Debug, HasViewportPercentage, PartialEq, ToComputedValue, ToCss)] +#[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, HasViewportPercentage)] +#[derive(PartialEq, ToAnimatedZero, ToComputedValue, ToCss)] pub struct TransformOrigin { /// The horizontal origin. pub horizontal: H, diff --git a/components/style/values/mod.rs b/components/style/values/mod.rs index 35db1405ffc..51101d1a28b 100644 --- a/components/style/values/mod.rs +++ b/components/style/values/mod.rs @@ -68,8 +68,8 @@ impl Parse for Impossible { /// A struct representing one of two kinds of values. #[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[derive(Clone, ComputeSquaredDistance, Copy, HasViewportPercentage, PartialEq)] -#[derive(ToAnimatedValue, ToComputedValue, ToCss)] +#[derive(Animate, Clone, ComputeSquaredDistance, Copy, HasViewportPercentage)] +#[derive(PartialEq, ToAnimatedValue, ToComputedValue, ToCss)] pub enum Either { /// The first value. First(A), diff --git a/components/style_derive/animate.rs b/components/style_derive/animate.rs new file mode 100644 index 00000000000..5ce1040e94c --- /dev/null +++ b/components/style_derive/animate.rs @@ -0,0 +1,123 @@ +/* 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 quote; +use std::borrow::Cow; +use syn; +use synstructure; + +pub fn derive(input: syn::DeriveInput) -> quote::Tokens { + let name = &input.ident; + let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); + let mut where_clause = where_clause.clone(); + for param in &input.generics.ty_params { + where_clause.predicates.push(where_predicate(syn::Ty::Path(None, param.ident.clone().into()))) + } + + let variants = variants(&input); + let mut match_body = quote!(); + match_body.append_all(variants.iter().map(|variant| { + let name = match input.body { + syn::Body::Struct(_) => Cow::Borrowed(&input.ident), + syn::Body::Enum(_) => { + Cow::Owned(syn::Ident::from(format!("{}::{}", input.ident, variant.ident))) + }, + }; + let (this_pattern, this_info) = synstructure::match_pattern( + &name, + &variant.data, + &synstructure::BindOpts::with_prefix( + synstructure::BindStyle::Ref, + "this".to_owned(), + ), + ); + let (other_pattern, other_info) = synstructure::match_pattern( + &name, + &variant.data, + &synstructure::BindOpts::with_prefix( + synstructure::BindStyle::Ref, + "other".to_owned(), + ), + ); + let (result_value, result_info) = synstructure::match_pattern( + &name, + &variant.data, + &synstructure::BindOpts::with_prefix( + synstructure::BindStyle::Move, + "result".to_owned(), + ), + ); + let mut computations = quote!(); + let iter = result_info.iter().zip(this_info.iter().zip(&other_info)); + computations.append_all(iter.map(|(result, (this, other))| { + where_clause.predicates.push(where_predicate(this.field.ty.clone())); + quote! { + let #result = ::values::animated::Animate::animate(#this, #other, procedure)?; + } + })); + quote! { + (&#this_pattern, &#other_pattern) => { + #computations + Ok(#result_value) + } + } + })); + + if variants.len() > 1 { + match_body = quote! { #match_body, _ => Err(()), }; + } + + quote! { + impl #impl_generics ::values::animated::Animate for #name #ty_generics #where_clause { + #[allow(unused_variables, unused_imports)] + #[inline] + fn animate( + &self, + other: &Self, + procedure: ::values::animated::Procedure, + ) -> Result { + match (self, other) { + #match_body + } + } + } + } +} + +fn variants(input: &syn::DeriveInput) -> Cow<[syn::Variant]> { + match input.body { + syn::Body::Enum(ref variants) => (&**variants).into(), + syn::Body::Struct(ref data) => { + vec![syn::Variant { + ident: input.ident.clone(), + attrs: input.attrs.clone(), + data: data.clone(), + discriminant: None, + }].into() + }, + } +} + +fn where_predicate(ty: syn::Ty) -> syn::WherePredicate { + syn::WherePredicate::BoundPredicate( + syn::WhereBoundPredicate { + bound_lifetimes: vec![], + bounded_ty: ty, + bounds: vec![syn::TyParamBound::Trait( + syn::PolyTraitRef { + bound_lifetimes: vec![], + trait_ref: syn::Path { + global: true, + segments: vec![ + "values".into(), + "animated".into(), + "Animate".into(), + ], + }, + }, + syn::TraitBoundModifier::None, + )], + }, + ) +} diff --git a/components/style_derive/lib.rs b/components/style_derive/lib.rs index 13a855eb6ba..a41925ab410 100644 --- a/components/style_derive/lib.rs +++ b/components/style_derive/lib.rs @@ -9,12 +9,20 @@ extern crate synstructure; use proc_macro::TokenStream; +mod animate; mod compute_squared_distance; mod has_viewport_percentage; mod to_animated_value; +mod to_animated_zero; mod to_computed_value; mod to_css; +#[proc_macro_derive(Animate)] +pub fn derive_animate(stream: TokenStream) -> TokenStream { + let input = syn::parse_derive_input(&stream.to_string()).unwrap(); + animate::derive(input).to_string().parse().unwrap() +} + #[proc_macro_derive(ComputeSquaredDistance)] pub fn derive_compute_squared_distance(stream: TokenStream) -> TokenStream { let input = syn::parse_derive_input(&stream.to_string()).unwrap(); @@ -33,6 +41,12 @@ pub fn derive_to_animated_value(stream: TokenStream) -> TokenStream { to_animated_value::derive(input).to_string().parse().unwrap() } +#[proc_macro_derive(ToAnimatedZero)] +pub fn derive_to_animated_zero(stream: TokenStream) -> TokenStream { + let input = syn::parse_derive_input(&stream.to_string()).unwrap(); + to_animated_zero::derive(input).to_string().parse().unwrap() +} + #[proc_macro_derive(ToComputedValue)] pub fn derive_to_computed_value(stream: TokenStream) -> TokenStream { let input = syn::parse_derive_input(&stream.to_string()).unwrap(); diff --git a/components/style_derive/to_animated_zero.rs b/components/style_derive/to_animated_zero.rs new file mode 100644 index 00000000000..f44443f4a34 --- /dev/null +++ b/components/style_derive/to_animated_zero.rs @@ -0,0 +1,79 @@ +/* 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 quote; +use syn; +use synstructure; + +pub fn derive(input: syn::DeriveInput) -> quote::Tokens { + let name = &input.ident; + let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl(); + let mut where_clause = where_clause.clone(); + for param in &input.generics.ty_params { + where_clause.predicates.push( + where_predicate(syn::Ty::Path(None, param.ident.clone().into())), + ); + } + + let to_body = match_body(&input); + + quote! { + impl #impl_generics ::values::animated::ToAnimatedZero for #name #ty_generics #where_clause { + #[allow(unused_variables)] + #[inline] + fn to_animated_zero(&self) -> Result { + match *self { + #to_body + } + } + } + } +} + +fn match_body(input: &syn::DeriveInput) -> quote::Tokens { + synstructure::each_variant(&input, &synstructure::BindStyle::Ref.into(), |fields, variant| { + let name = if let syn::Body::Enum(_) = input.body { + format!("{}::{}", input.ident, variant.ident).into() + } else { + variant.ident.clone() + }; + let (zero, computed_fields) = synstructure::match_pattern( + &name, + &variant.data, + &synstructure::BindStyle::Move.into(), + ); + let fields_pairs = fields.iter().zip(computed_fields.iter()); + let mut computations = quote!(); + computations.append_all(fields_pairs.map(|(field, computed_field)| { + quote! { + let #computed_field = ::values::animated::ToAnimatedZero::to_animated_zero(#field)?; + } + })); + Some(quote!( + #computations + Ok(#zero) + )) + }) +} + +fn where_predicate(ty: syn::Ty) -> syn::WherePredicate { + syn::WherePredicate::BoundPredicate(syn::WhereBoundPredicate { + bound_lifetimes: vec![], + bounded_ty: ty, + bounds: vec![syn::TyParamBound::Trait( + syn::PolyTraitRef { + bound_lifetimes: vec![], + trait_ref: syn::Path { + global: true, + segments: vec![ + "values".into(), + "animated".into(), + "ToAnimatedZero".into(), + ], + }, + }, + syn::TraitBoundModifier::None, + )], + }) +}