diff --git a/components/style/properties/helpers/animated_properties.mako.rs b/components/style/properties/helpers/animated_properties.mako.rs index 448c1f7c88b..9a0ea20f238 100644 --- a/components/style/properties/helpers/animated_properties.mako.rs +++ b/components/style/properties/helpers/animated_properties.mako.rs @@ -46,7 +46,10 @@ 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, Rotate, Translate, Scale, Transform, TransformOperation}; use values::distance::{ComputeSquaredDistance, SquaredDistance}; #[cfg(feature = "gecko")] use values::generics::FontSettings as GenericFontSettings; #[cfg(feature = "gecko")] use values::generics::FontSettingTag as GenericFontSettingTag; @@ -2269,6 +2272,129 @@ impl Matrix3D { } } +/// +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::Rotate3D(rx, ry, rz, angle) => Ok((rx, ry, rz, angle)), + Rotate::Rotate(angle) => Ok((0., 0., 1., angle)), + } + } +} + +impl Animate for ComputedRotate { + #[inline] + fn animate( + &self, + other: &Self, + procedure: Procedure, + ) -> Result { + let from = ComputedRotate::fill_unspecified(self)?; + let to = ComputedRotate::fill_unspecified(other)?; + + let (fx, fy, fz, fa) = transform::get_normalized_vector_and_angle(from.0, from.1, from.2, from.3); + let (tx, ty, tz, ta) = transform::get_normalized_vector_and_angle(to.0, to.1, to.2, to.3); + if (fx, fy, fz) == (tx, ty, tz) { + return Ok(Rotate::Rotate3D(fx, fy, fz, fa.animate(&ta, procedure)?)); + } + + let fv = DirectionVector::new(fx, fy, fz); + let tv = DirectionVector::new(tx, ty, tz); + let fq = Quaternion::from_direction_and_angle(&fv, fa.radians64()); + let tq = Quaternion::from_direction_and_angle(&tv, ta.radians64()); + + let rq = Quaternion::animate(&fq, &tq, procedure)?; + let (x, y, z, angle) = + transform::get_normalized_vector_and_angle(rq.0 as f32, + rq.1 as f32, + rq.2 as f32, + rq.3.acos() as f32 *2.0); + + Ok(Rotate::Rotate3D(x, y, z, Angle::from_radians(angle))) + } +} + +/// +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::Translate3D(tx, ty, tz) => Ok((tx, ty, tz)), + Translate::Translate(tx, ty) => Ok((tx, ty, Length::zero())), + Translate::TranslateX(tx) => Ok((tx, LengthOrPercentage::Length(Length::zero()), Length::zero())), + } + } +} + +impl Animate for ComputedTranslate { + #[inline] + fn animate( + &self, + other: &Self, + procedure: Procedure, + ) -> Result { + let from = ComputedTranslate::fill_unspecified(self)?; + let to = ComputedTranslate::fill_unspecified(other)?; + + Ok(Translate::Translate3D(from.0.animate(&to.0, procedure)?, + from.1.animate(&to.1, procedure)?, + 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::Scale3D(sx, sy, sz) => Ok((sx, sy, sz)), + Scale::Scale(sx, sy) => Ok((sx, sy, 1.)), + Scale::ScaleX(sx) => Ok((sx, 1., 1.)), + } + } +} + +impl Animate for ComputedScale { + #[inline] + fn animate( + &self, + other: &Self, + procedure: Procedure, + ) -> Result { + let from = ComputedScale::fill_unspecified(self)?; + let to = ComputedScale::fill_unspecified(other)?; + + if procedure == Procedure::Add { + // scale(x1,y1,z1)*scale(x2,y2,z2) = scale(x1*x2, y1*y2, z1*z2) + return Ok(Scale::Scale3D(from.0 * to.0, from.1 * to.1, from.2 * to.2)); + } + + Ok(Scale::Scale3D(animate_multiplicative_factor(from.0, to.0, procedure)?, + animate_multiplicative_factor(from.1, to.1, procedure)?, + animate_multiplicative_factor(from.2, to.2, procedure)?)) + } +} + /// impl Animate for ComputedTransform { #[inline] diff --git a/components/style/values/generics/transform.rs b/components/style/values/generics/transform.rs index 9ea641c047d..e8b8c2e0678 100644 --- a/components/style/values/generics/transform.rs +++ b/components/style/values/generics/transform.rs @@ -669,7 +669,7 @@ pub fn get_normalized_vector_and_angle( } } -#[derive(Animate, ComputeSquaredDistance, ToAnimatedZero, ToComputedValue)] +#[derive(ComputeSquaredDistance, ToAnimatedZero, ToComputedValue)] #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)] /// A value of the `Rotate` property /// @@ -683,7 +683,7 @@ pub enum Rotate { Rotate3D(Number, Number, Number, Angle), } -#[derive(Animate, ComputeSquaredDistance, ToAnimatedZero, ToComputedValue)] +#[derive(ComputeSquaredDistance, ToAnimatedZero, ToComputedValue)] #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)] /// A value of the `Scale` property /// @@ -699,7 +699,7 @@ pub enum Scale { Scale3D(Number, Number, Number), } -#[derive(Animate, ComputeSquaredDistance, ToAnimatedZero, ToComputedValue)] +#[derive(ComputeSquaredDistance, ToAnimatedZero, ToComputedValue)] #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)] /// A value of the `Translate` property /// diff --git a/tests/wpt/metadata/css/css-transforms/animation/rotate-interpolation.html.ini b/tests/wpt/metadata/css/css-transforms/animation/rotate-interpolation.html.ini index f20dc54d7c9..713e1537b0e 100644 --- a/tests/wpt/metadata/css/css-transforms/animation/rotate-interpolation.html.ini +++ b/tests/wpt/metadata/css/css-transforms/animation/rotate-interpolation.html.ini @@ -1,7 +1,4 @@ [rotate-interpolation.html] - ["100deg" and "180deg" are valid rotate values] - expected: FAIL - [Animation between "100deg" and "180deg" at progress -1] expected: FAIL @@ -20,9 +17,6 @@ [Animation between "100deg" and "180deg" at progress 2] expected: FAIL - ["45deg" and "-1 1 0 60deg" are valid rotate values] - expected: FAIL - [Animation between "45deg" and "-1 1 0 60deg" at progress -1] expected: FAIL @@ -41,9 +35,6 @@ [Animation between "45deg" and "-1 1 0 60deg" at progress 2] expected: FAIL - ["none" and "7 -8 9 400grad" are valid rotate values] - expected: FAIL - [Animation between "none" and "7 -8 9 400grad" at progress -1] expected: FAIL @@ -62,9 +53,6 @@ [Animation between "none" and "7 -8 9 400grad" at progress 2] expected: FAIL - ["none" and "none" are valid rotate values] - expected: FAIL - [Animation between "none" and "none" at progress -1] expected: FAIL diff --git a/tests/wpt/metadata/css/css-transforms/animation/scale-interpolation.html.ini b/tests/wpt/metadata/css/css-transforms/animation/scale-interpolation.html.ini index 5abe2d25890..39e9ec50cb9 100644 --- a/tests/wpt/metadata/css/css-transforms/animation/scale-interpolation.html.ini +++ b/tests/wpt/metadata/css/css-transforms/animation/scale-interpolation.html.ini @@ -1,7 +1,4 @@ [scale-interpolation.html] - ["2 30 400" and "10 110 1200" are valid scale values] - expected: FAIL - [Animation between "2 30 400" and "10 110 1200" at progress -1] expected: FAIL @@ -20,9 +17,6 @@ [Animation between "2 30 400" and "10 110 1200" at progress 2] expected: FAIL - ["26 17 9" and "2" are valid scale values] - expected: FAIL - [Animation between "26 17 9" and "2" at progress -1] expected: FAIL @@ -41,9 +35,6 @@ [Animation between "26 17 9" and "2" at progress 2] expected: FAIL - ["none" and "4 3 2" are valid scale values] - expected: FAIL - [Animation between "none" and "4 3 2" at progress -1] expected: FAIL @@ -62,9 +53,6 @@ [Animation between "none" and "4 3 2" at progress 2] expected: FAIL - ["none" and "none" are valid scale values] - expected: FAIL - [Animation between "none" and "none" at progress -1] expected: FAIL diff --git a/tests/wpt/metadata/css/css-transforms/animation/translate-interpolation.html.ini b/tests/wpt/metadata/css/css-transforms/animation/translate-interpolation.html.ini index ed398f54f12..6241318a17f 100644 --- a/tests/wpt/metadata/css/css-transforms/animation/translate-interpolation.html.ini +++ b/tests/wpt/metadata/css/css-transforms/animation/translate-interpolation.html.ini @@ -1,7 +1,4 @@ [translate-interpolation.html] - ["220px 240px 260px" and "300px 400px 500px" are valid translate values] - expected: FAIL - [Animation between "220px 240px 260px" and "300px 400px 500px" at progress -1] expected: FAIL @@ -20,9 +17,6 @@ [Animation between "220px 240px 260px" and "300px 400px 500px" at progress 2] expected: FAIL - ["480px 400px 320px" and "240% 160%" are valid translate values] - expected: FAIL - [Animation between "480px 400px 320px" and "240% 160%" at progress -1] expected: FAIL @@ -41,9 +35,6 @@ [Animation between "480px 400px 320px" and "240% 160%" at progress 2] expected: FAIL - ["none" and "8px 80% 800px" are valid translate values] - expected: FAIL - [Animation between "none" and "8px 80% 800px" at progress -1] expected: FAIL @@ -62,9 +53,6 @@ [Animation between "none" and "8px 80% 800px" at progress 2] expected: FAIL - ["none" and "none" are valid translate values] - expected: FAIL - [Animation between "none" and "none" at progress -1] expected: FAIL