diff --git a/dom/animation/test/mochitest.ini b/dom/animation/test/mochitest.ini index 4a7beb02236a..7a40e2463958 100644 --- a/dom/animation/test/mochitest.ini +++ b/dom/animation/test/mochitest.ini @@ -6,6 +6,7 @@ prefs = dom.animations-api.implicit-keyframes.enabled=true dom.animations-api.timelines.enabled=true layout.css.motion-path.enabled=true + layout.css.individual-transform.enabled=true # Support files for chrome tests that we want to load over HTTP need # to go in here, not chrome.ini. support-files = diff --git a/dom/animation/test/mozilla/test_distance_of_transform.html b/dom/animation/test/mozilla/test_distance_of_transform.html index aa5a67ee0533..514a38584fa0 100644 --- a/dom/animation/test/mozilla/test_distance_of_transform.html +++ b/dom/animation/test/mozilla/test_distance_of_transform.html @@ -339,5 +339,66 @@ test(function(t) { 'distance of transform lists'); }, 'Test distance of mismatched transform lists with skew function'); + +// Individual transforms +test(function(t) { + var target = addDiv(t); + var dist = getDistance(target, 'translate', '50px', 'none'); + assert_equals(dist, Math.sqrt(50 * 50), 'distance of 2D translate and none'); +}, 'Test distance of 2D translate property with none'); + +test(function(t) { + var target = addDiv(t); + var dist = getDistance(target, 'translate', '10px 30px', '50px'); + assert_equals(dist, Math.sqrt(40 * 40 + 30 * 30), 'distance of 2D translate'); +}, 'Test distance of 2D translate property'); + +test(function(t) { + var target = addDiv(t); + var dist = getDistance(target, 'translate', '10px 30px 50px', '50px'); + assert_equals(dist, Math.sqrt(40 * 40 + 30 * 30 + 50 * 50), + 'distance of 3D translate'); +}, 'Test distance of 3D translate property'); + +test(function(t) { + var target = addDiv(t); + var dist = getDistance(target, 'scale', '2', 'none'); + assert_equals(dist, Math.sqrt(1 + 1), 'distance of 2D scale and none'); +}, 'Test distance of 2D scale property with none'); + +test(function(t) { + var target = addDiv(t); + var dist = getDistance(target, 'scale', '3', '1 1'); + assert_equals(dist, Math.sqrt(2 * 2 + 2 * 2), 'distance of 2D scale'); +}, 'Test distance of 2D scale property'); + +test(function(t) { + var target = addDiv(t); + var dist = getDistance(target, 'scale', '3 2 2', '1 1'); + assert_equals(dist, Math.sqrt(2 * 2 + 1 * 1 + 1 * 1), + 'distance of 3D scale'); +}, 'Test distance of 3D scale property'); + +test(function(t) { + var target = addDiv(t); + var dist = getDistance(target, 'rotate', '180deg', 'none'); + assert_equals(dist, Math.PI, 'distance of 2D rotate and none'); +}, 'Test distance of 2D rotate property with none'); + +test(function(t) { + var target = addDiv(t); + var dist = getDistance(target, 'rotate', '180deg', '90deg'); + assert_equals(dist, Math.PI / 2.0, 'distance of 2D rotate'); +}, 'Test distance of 2D rotate property'); + +test(function(t) { + var target = addDiv(t); + var dist = getDistance(target, 'rotate', 'z 90deg', 'x 90deg'); + let q1 = getQuaternion([0, 0, 1], Math.PI / 2.0); + let q2 = getQuaternion([1, 0, 0], Math.PI / 2.0); + assert_approx_equals(dist, computeRotateDistance(q1, q2), EPSILON, + 'distance of 3D rotate'); +}, 'Test distance of 3D rotate property'); + diff --git a/servo/components/style/values/animated/transform.rs b/servo/components/style/values/animated/transform.rs index 7d0c0e94ff38..7cd2b32e61eb 100644 --- a/servo/components/style/values/animated/transform.rs +++ b/servo/components/style/values/animated/transform.rs @@ -1309,19 +1309,8 @@ impl ComputeSquaredDistance for ComputedTransformOperation { &TransformOperation::Rotate3D(fx, fy, fz, fa), &TransformOperation::Rotate3D(tx, ty, tz, ta), ) => { - let (fx, fy, fz, angle1) = - transform::get_normalized_vector_and_angle(fx, fy, fz, fa); - let (tx, ty, tz, angle2) = - transform::get_normalized_vector_and_angle(tx, ty, tz, ta); - if (fx, fy, fz) == (tx, ty, tz) { - angle1.compute_squared_distance(&angle2) - } else { - let v1 = DirectionVector::new(fx, fy, fz); - let v2 = DirectionVector::new(tx, ty, tz); - let q1 = Quaternion::from_direction_and_angle(&v1, angle1.radians64()); - let q2 = Quaternion::from_direction_and_angle(&v2, angle2.radians64()); - q1.compute_squared_distance(&q2) - } + Rotate::Rotate3D(fx, fy, fz, fa) + .compute_squared_distance(&Rotate::Rotate3D(tx, ty, tz, ta)) }, ( &TransformOperation::RotateX(fa), @@ -1390,7 +1379,7 @@ impl ComputedRotate { // // If the axis is unspecified, it defaults to "0 0 1" match *self { - Rotate::None => unreachable!("None is handled by the caller"), + Rotate::None => (0., 0., 1., Angle::zero()), Rotate::Rotate3D(rx, ry, rz, angle) => (rx, ry, rz, angle), Rotate::Rotate(angle) => (0., 0., 1., angle), } @@ -1459,6 +1448,49 @@ impl Animate for ComputedRotate { } } +impl ComputeSquaredDistance for ComputedRotate { + #[inline] + fn compute_squared_distance(&self, other: &Self) -> Result { + match (self, other) { + (&Rotate::None, &Rotate::None) => Ok(SquaredDistance::from_sqrt(0.)), + (&Rotate::Rotate3D(_, _, _, a), &Rotate::None) | + (&Rotate::None, &Rotate::Rotate3D(_, _, _, a)) => { + a.compute_squared_distance(&Angle::zero()) + }, + (&Rotate::Rotate3D(_, ..), _) | (_, &Rotate::Rotate3D(_, ..)) => { + let (from, to) = (self.resolve(), other.resolve()); + let (mut fx, mut fy, mut fz, angle1) = + transform::get_normalized_vector_and_angle(from.0, from.1, from.2, from.3); + let (mut tx, mut ty, mut tz, angle2) = + transform::get_normalized_vector_and_angle(to.0, to.1, to.2, to.3); + + if angle1 == Angle::zero() { + fx = tx; + fy = ty; + fz = tz; + } else if angle2 == Angle::zero() { + tx = fx; + ty = fy; + tz = fz; + } + + if (fx, fy, fz) == (tx, ty, tz) { + angle1.compute_squared_distance(&angle2) + } else { + let v1 = DirectionVector::new(fx, fy, fz); + let v2 = DirectionVector::new(tx, ty, tz); + let q1 = Quaternion::from_direction_and_angle(&v1, angle1.radians64()); + let q2 = Quaternion::from_direction_and_angle(&v2, angle2.radians64()); + q1.compute_squared_distance(&q2) + } + }, + (&Rotate::Rotate(_), _) | (_, &Rotate::Rotate(_)) => { + self.resolve().3.compute_squared_distance(&other.resolve().3) + }, + } + } +} + /// impl ComputedTranslate { fn resolve(&self) -> (LengthOrPercentage, LengthOrPercentage, Length) { @@ -1500,6 +1532,18 @@ impl Animate for ComputedTranslate { } } +impl ComputeSquaredDistance for ComputedTranslate { + #[inline] + fn compute_squared_distance(&self, other: &Self) -> Result { + let (from, to) = (self.resolve(), other.resolve()); + Ok( + from.0.compute_squared_distance(&to.0)? + + from.1.compute_squared_distance(&to.1)? + + from.2.compute_squared_distance(&to.2)? + ) + } +} + /// impl ComputedScale { fn resolve(&self) -> (Number, Number, Number) { @@ -1554,3 +1598,15 @@ impl Animate for ComputedScale { } } } + +impl ComputeSquaredDistance for ComputedScale { + #[inline] + fn compute_squared_distance(&self, other: &Self) -> Result { + let (from, to) = (self.resolve(), other.resolve()); + Ok( + from.0.compute_squared_distance(&to.0)? + + from.1.compute_squared_distance(&to.1)? + + from.2.compute_squared_distance(&to.2)? + ) + } +} diff --git a/servo/components/style/values/generics/transform.rs b/servo/components/style/values/generics/transform.rs index ef54c511f639..3bab299413ce 100644 --- a/servo/components/style/values/generics/transform.rs +++ b/servo/components/style/values/generics/transform.rs @@ -530,7 +530,6 @@ pub fn get_normalized_vector_and_angle( #[derive( Clone, - ComputeSquaredDistance, Copy, Debug, MallocSizeOf, @@ -600,7 +599,6 @@ where #[derive( Clone, - ComputeSquaredDistance, Copy, Debug, MallocSizeOf, @@ -649,7 +647,6 @@ impl ToCss for Scale { #[derive( Clone, - ComputeSquaredDistance, Debug, MallocSizeOf, PartialEq,