Skip to content

Commit

Permalink
Bug 1424134 - Part 3: Implement ComputeSquaredDistance for individual…
Browse files Browse the repository at this point in the history
… 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
  • Loading branch information
BorisChiou committed Nov 16, 2018
1 parent 40a2db8 commit 2718fd0
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 17 deletions.
1 change: 1 addition & 0 deletions dom/animation/test/mochitest.ini
Original file line number Diff line number Diff line change
Expand Up @@ -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 =
Expand Down
61 changes: 61 additions & 0 deletions dom/animation/test/mozilla/test_distance_of_transform.html
Original file line number Diff line number Diff line change
Expand Up @@ -339,5 +339,66 @@
'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');

</script>
</html>
84 changes: 70 additions & 14 deletions servo/components/style/values/animated/transform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down Expand Up @@ -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),
}
Expand Down Expand Up @@ -1459,6 +1448,49 @@ impl Animate for ComputedRotate {
}
}

impl ComputeSquaredDistance for ComputedRotate {
#[inline]
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
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)
},
}
}
}

/// <https://drafts.csswg.org/css-transforms-2/#propdef-translate>
impl ComputedTranslate {
fn resolve(&self) -> (LengthOrPercentage, LengthOrPercentage, Length) {
Expand Down Expand Up @@ -1500,6 +1532,18 @@ impl Animate for ComputedTranslate {
}
}

impl ComputeSquaredDistance for ComputedTranslate {
#[inline]
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
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)?
)
}
}

/// <https://drafts.csswg.org/css-transforms-2/#propdef-scale>
impl ComputedScale {
fn resolve(&self) -> (Number, Number, Number) {
Expand Down Expand Up @@ -1554,3 +1598,15 @@ impl Animate for ComputedScale {
}
}
}

impl ComputeSquaredDistance for ComputedScale {
#[inline]
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
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)?
)
}
}
3 changes: 0 additions & 3 deletions servo/components/style/values/generics/transform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,6 @@ pub fn get_normalized_vector_and_angle<T: Zero>(

#[derive(
Clone,
ComputeSquaredDistance,
Copy,
Debug,
MallocSizeOf,
Expand Down Expand Up @@ -600,7 +599,6 @@ where

#[derive(
Clone,
ComputeSquaredDistance,
Copy,
Debug,
MallocSizeOf,
Expand Down Expand Up @@ -649,7 +647,6 @@ impl<Number: ToCss + PartialEq> ToCss for Scale<Number> {

#[derive(
Clone,
ComputeSquaredDistance,
Debug,
MallocSizeOf,
PartialEq,
Expand Down

0 comments on commit 2718fd0

Please sign in to comment.