Bug 1207734 - Part 8. (stylo) Implement Animate trait for individual transform. draft
authorcku <cku@mozilla.com>
Thu, 07 Dec 2017 14:46:37 +0800
changeset 713516 2733f9b73ee49f027f630702487e386e5ff25802
parent 713515 5593063324766d1c72194cdcaa7f9a67d2b8b7ca
child 713517 ae6bf050a03ee6e16fb5718be5562cbf63e17954
push id93657
push userbmo:cku@mozilla.com
push dateWed, 20 Dec 2017 14:03:45 +0000
bugs1207734
milestone59.0a1
Bug 1207734 - Part 8. (stylo) Implement Animate trait for individual transform. MozReview-Commit-ID: HlDD9xXh8jv
servo/components/style/properties/helpers/animated_properties.mako.rs
servo/components/style/values/generics/transform.rs
--- a/servo/components/style/properties/helpers/animated_properties.mako.rs
+++ b/servo/components/style/properties/helpers/animated_properties.mako.rs
@@ -41,17 +41,20 @@ use values::computed::{ClipRect, Context
 use values::computed::{Length, LengthOrPercentage, LengthOrPercentageOrAuto};
 use values::computed::{LengthOrPercentageOrNone, MaxLength};
 use values::computed::{NonNegativeNumber, Number, NumberOrPercentage, Percentage};
 use values::computed::length::NonNegativeLengthOrPercentage;
 use values::computed::ToComputedValue;
 use values::computed::transform::{DirectionVector, Matrix, Matrix3D};
 use values::computed::transform::TransformOperation as ComputedTransformOperation;
 use values::computed::transform::Transform as ComputedTransform;
-use values::generics::transform::{self, Transform, TransformOperation};
+use values::computed::transform::Rotate as ComputedRotate;
+use values::computed::transform::Translate as ComputedTranslate;
+use values::computed::transform::Scale as ComputedScale;
+use values::generics::transform::{self, Transform, TransformOperation, Translate, Scale, Rotate};
 use values::distance::{ComputeSquaredDistance, SquaredDistance};
 #[cfg(feature = "gecko")] use values::generics::FontSettings as GenericFontSettings;
 #[cfg(feature = "gecko")] use values::generics::FontSettingTag as GenericFontSettingTag;
 #[cfg(feature = "gecko")] use values::generics::FontSettingTagFloat;
 use values::generics::NonNegative;
 use values::generics::effects::Filter;
 use values::generics::position as generic_position;
 use values::generics::svg::{SVGLength,  SvgLengthOrPercentageOrNumber, SVGPaint};
@@ -2277,16 +2280,133 @@ impl Matrix3D {
              self.m12*self.m21*self.m33 + self.m11*self.m22*self.m33),
         };
 
         Some(x)
     }
 }
 
 /// <https://drafts.csswg.org/css-transforms/#interpolation-of-transforms>
+impl ComputedRotate {
+    fn fill_unspecified(rotate: &ComputedRotate)
+        -> Result<(Number, Number, Number, Angle), ()>{
+        // According to the spec:
+        // https://drafts.csswg.org/css-transforms-2/#individual-transforms
+        //
+        // If the axis is unspecified, it defaults to "0 0 1"
+        match rotate {
+            &Rotate::None =>
+                Ok((0., 0., 1., Angle::zero())),
+            &Rotate::Specified(None, angle) =>
+                Ok((0., 0., 1., angle)),
+            &Rotate::Specified(Some((rx, ry, rz)), angle) =>
+                Ok((rx, ry, rz, angle)),
+        }
+    }
+}
+
+impl Animate for ComputedRotate {
+    #[inline]
+    fn animate(
+        &self,
+        other: &Self,
+        procedure: Procedure,
+    ) -> Result<Self, ()> {
+        let from = ComputedRotate::fill_unspecified(self)?;
+        let to = ComputedRotate::fill_unspecified(other)?;
+
+        Ok(Rotate::Specified(Some((from.0.animate(&to.0, procedure)?,
+                                   from.1.animate(&to.1, procedure)?,
+                                   from.2.animate(&to.2, procedure)?)),
+                             from.3.animate(&to.3, procedure)?))
+    }
+}
+
+impl ComputedTranslate {
+    fn fill_unspecified(translate: &ComputedTranslate)
+        -> Result<(LengthOrPercentage, LengthOrPercentage, Length), ()>{
+        // According to the spec:
+        // https://drafts.csswg.org/css-transforms-2/#individual-transforms
+        //
+        // Unspecified translations default to 0px
+        match translate {
+            &Translate::None => {
+                Ok((LengthOrPercentage::Length(Length::zero()),
+                    LengthOrPercentage::Length(Length::zero()),
+                    Length::zero()))
+            },
+            &Translate::Specified(tx, None, None) => {
+                Ok((tx, LengthOrPercentage::Length(Length::zero()),
+                    Length::zero()))
+            },
+            &Translate::Specified(tx, Some(ty), None) =>
+                Ok((tx, ty, Length::zero())),
+            &Translate::Specified(tx, Some(ty), Some(tz)) =>
+                Ok((tx, ty, tz)),
+            _ =>
+                panic!("Found unexpected value for translate property: {:?}", translate),
+        }
+    }
+}
+
+impl Animate for ComputedTranslate {
+    #[inline]
+    fn animate(
+        &self,
+        other: &Self,
+        procedure: Procedure,
+    ) -> Result<Self, ()> {
+        let from = ComputedTranslate::fill_unspecified(self)?;
+        let to = ComputedTranslate::fill_unspecified(other)?;
+
+        Ok(Translate::Specified(from.0.animate(&to.0, procedure)?,
+                                Some(from.1.animate(&to.1, procedure)?),
+                                Some(from.2.animate(&to.2, procedure)?)))
+    }
+}
+
+impl ComputedScale {
+    fn fill_unspecified(scale: &ComputedScale)
+        -> Result<(Number, Number, Number), ()>{
+        // According to the spec:
+        // https://drafts.csswg.org/css-transforms-2/#individual-transforms
+        //
+        // Unspecified scales default to 1
+        match scale {
+            &Scale::None =>
+                Ok((1.0, 1.0, 1.0)),
+            &Scale::Specified(sx, None, None) =>
+                Ok((sx, 1.0, 1.0)),
+            &Scale::Specified(sx, Some(sy), None) =>
+                Ok((sx, sy, 1.0)),
+            &Scale::Specified(sx, Some(sy), Some(sz)) =>
+                Ok((sx, sy, sz)),
+            _ =>
+                panic!("Found unexpected value for scale property: {:?}", scale),
+        }
+    }
+}
+
+impl Animate for ComputedScale {
+    #[inline]
+    fn animate(
+        &self,
+        other: &Self,
+        procedure: Procedure,
+    ) -> Result<Self, ()> {
+        let from = ComputedScale::fill_unspecified(self)?;
+        let to = ComputedScale::fill_unspecified(other)?;
+
+        Ok(Scale::Specified(animate_multiplicative_factor(from.0, to.0, procedure)?,
+                            Some(animate_multiplicative_factor(from.1, to.1, procedure)?),
+                            Some(animate_multiplicative_factor(from.2, to.2, procedure)?)))
+    }
+}
+
+/// <https://drafts.csswg.org/css-transforms/#interpolation-of-transforms>
 impl Animate for ComputedTransform {
     #[inline]
     fn animate(
         &self,
         other_: &Self,
         procedure: Procedure,
     ) -> Result<Self, ()> {
 
--- a/servo/components/style/values/generics/transform.rs
+++ b/servo/components/style/values/generics/transform.rs
@@ -751,41 +751,41 @@ pub fn get_normalized_vector_and_angle<T
         // rotation to not be applied, so we use identity matrix (i.e. rotate3d(0, 0, 1, 0)).
         (0., 0., 1., T::zero())
     } else {
         let vector = vector.normalize();
         (vector.x, vector.y, vector.z, angle)
     }
 }
 
-#[derive(ToComputedValue, Animate, ComputeSquaredDistance, ToAnimatedZero)]
+#[derive(ToComputedValue, ComputeSquaredDistance, ToAnimatedZero)]
 #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
 /// A value of the `Rotate` property
 ///
 /// <https://drafts.csswg.org/css-transforms-2/#individual-transforms>
 pub enum Rotate<Number, Angle> {
     /// 'none'
     None,
     /// '<number>{3}? <angle>'
     Specified(Option<(Number, Number, Number)>, Angle)
 }
 
-#[derive(ToComputedValue, Animate, ComputeSquaredDistance, ToAnimatedZero)]
+#[derive(ToComputedValue, ComputeSquaredDistance, ToAnimatedZero)]
 #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
 /// A value of the `Translate` property
 ///
 /// <https://drafts.csswg.org/css-transforms-2/#individual-transforms>
 pub enum Translate<LengthOrPercentage, Length> {
     /// 'none'
     None,
     /// '<length-percentage> [ <length-percentage> <length>? ]?'
     Specified(LengthOrPercentage, Option<LengthOrPercentage>, Option<Length>)
 }
 
-#[derive(ToComputedValue, Animate, ComputeSquaredDistance, ToAnimatedZero)]
+#[derive(ToComputedValue, ComputeSquaredDistance, ToAnimatedZero)]
 #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
 /// A value of the `Scale` property
 ///
 /// <https://drafts.csswg.org/css-transforms-2/#individual-transforms>
 pub enum Scale<Number> {
     /// 'none'
     None,
     /// '<number>{1,3}'