From 2718fd08976c5689a0237b9cee719a77f1cc7624 Mon Sep 17 00:00:00 2001 From: Boris Chiou Date: Fri, 16 Nov 2018 18:58:41 +0000 Subject: [PATCH] Bug 1424134 - Part 3: Implement ComputeSquaredDistance for individual transforms. r=birtles We manually implement ComputeSquaredDistance for Translate, Rotate, and Scale because we have to handle mismatch cases, and actually we don't need to implement it for specified types. Depends on D11934 Differential Revision: https://phabricator.services.mozilla.com/D11935 --HG-- extra : moz-landing-system : lando --- dom/animation/test/mochitest.ini | 1 + .../mozilla/test_distance_of_transform.html | 61 ++++++++++++++ .../style/values/animated/transform.rs | 84 +++++++++++++++---- .../style/values/generics/transform.rs | 3 - 4 files changed, 132 insertions(+), 17 deletions(-) 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,