From 9b76cd9d1c2353d9e9f1edc38e609ecce9252526 Mon Sep 17 00:00:00 2001 From: Boris Chiou Date: Thu, 17 Aug 2017 10:59:09 +0800 Subject: [PATCH 1/2] Rewrite decomposition of 2d matrix. The implementation of 2d matrix decomposition in Servo matches that in spec, but its result is really different from that in Gecko, so the visual results on the main thread and on the compositor thread are really different and we got many test failures. Therefore, let's write a different algorithm of decomposition of 2d matrix for Stylo, and keep the original one for Servo. The output of new implemented 2d matrix decomposition is a Decomposed3DMatrix, so we can reuse the interpolation and re-composition code. (Just like what we do in Gecko.) --- .../helpers/animated_properties.mako.rs | 70 +++++++++++++++++++ 1 file changed, 70 insertions(+) diff --git a/components/style/properties/helpers/animated_properties.mako.rs b/components/style/properties/helpers/animated_properties.mako.rs index a97b8e26042..08afe9308de 100644 --- a/components/style/properties/helpers/animated_properties.mako.rs +++ b/components/style/properties/helpers/animated_properties.mako.rs @@ -1399,6 +1399,7 @@ impl ComputeSquaredDistance for MatrixDecomposed2D { } impl Animate for ComputedMatrix { + #[cfg(feature = "servo")] fn animate(&self, other: &Self, procedure: Procedure) -> Result { if self.is_3d() || other.is_3d() { let decomposed_from = decompose_3d_matrix(*self); @@ -1419,6 +1420,25 @@ impl Animate for ComputedMatrix { Ok(ComputedMatrix::from(this.animate(&other, procedure)?)) } } + + #[cfg(feature = "gecko")] + fn animate(&self, other: &Self, procedure: Procedure) -> Result { + let (from, to) = if self.is_3d() || other.is_3d() { + (decompose_3d_matrix(*self), decompose_3d_matrix(*other)) + } else { + (decompose_2d_matrix(self), decompose_2d_matrix(other)) + }; + match (from, to) { + (Ok(from), Ok(to)) => { + Ok(ComputedMatrix::from(from.animate(&to, procedure)?)) + }, + _ => { + let (this_weight, other_weight) = procedure.weights(); + let result = if this_weight > other_weight { *self } else { *other }; + Ok(result) + }, + } + } } impl ComputeSquaredDistance for ComputedMatrix { @@ -1830,6 +1850,56 @@ fn decompose_3d_matrix(mut matrix: ComputedMatrix) -> Result Result { + // The index is column-major, so the equivalent transform matrix is: + // | m11 m21 0 m41 | => | m11 m21 | and translate(m41, m42) + // | m12 m22 0 m42 | | m12 m22 | + // | 0 0 1 0 | + // | 0 0 0 1 | + let (mut m11, mut m12) = (matrix.m11, matrix.m12); + let (mut m21, mut m22) = (matrix.m21, matrix.m22); + if m11 * m22 == m12 * m21 { + // singular matrix + return Err(()); + } + + let mut scale_x = (m11 * m11 + m12 * m12).sqrt(); + m11 /= scale_x; + m12 /= scale_x; + + let mut shear_xy = m11 * m21 + m12 * m22; + m21 -= m11 * shear_xy; + m22 -= m12 * shear_xy; + + let scale_y = (m21 * m21 + m22 * m22).sqrt(); + m21 /= scale_y; + m22 /= scale_y; + shear_xy /= scale_y; + + let determinant = m11 * m22 - m12 * m21; + debug_assert!(0.99 < determinant.abs() && determinant.abs() < 1.01, + "determinant should now be 1 or -1"); + + if determinant < 0. { + m11 = -m11; + m12 = -m12; + shear_xy = -shear_xy; + scale_x = -scale_x; + } + + Ok(MatrixDecomposed3D { + translate: Translate3D(matrix.m41, matrix.m42, 0.), + scale: Scale3D(scale_x, scale_y, 1.), + skew: Skew(shear_xy, 0., 0.), + perspective: Perspective(0., 0., 0., 1.), + quaternion: Quaternion::from_direction_and_angle(&DirectionVector::new(0., 0., 1.), + m12.atan2(m11) as f64) + }) +} + // Combine 2 point. fn combine(a: [f32; 3], b: [f32; 3], ascl: f32, bscl: f32) -> [f32; 3] { [ From 172b4aaddacdeb6eeb70821ffe5762fd713e857d Mon Sep 17 00:00:00 2001 From: Boris Chiou Date: Mon, 21 Aug 2017 14:58:41 +0800 Subject: [PATCH 2/2] Use rewritten decomposition of 2d matrix to compute distance. So we can align the result with interpolation. --- .../properties/helpers/animated_properties.mako.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/components/style/properties/helpers/animated_properties.mako.rs b/components/style/properties/helpers/animated_properties.mako.rs index 08afe9308de..683c23555ce 100644 --- a/components/style/properties/helpers/animated_properties.mako.rs +++ b/components/style/properties/helpers/animated_properties.mako.rs @@ -1443,6 +1443,7 @@ impl Animate for ComputedMatrix { impl ComputeSquaredDistance for ComputedMatrix { #[inline] + #[cfg(feature = "servo")] fn compute_squared_distance(&self, other: &Self) -> Result { if self.is_3d() || other.is_3d() { let from = decompose_3d_matrix(*self)?; @@ -1454,6 +1455,17 @@ impl ComputeSquaredDistance for ComputedMatrix { from.compute_squared_distance(&to) } } + + #[inline] + #[cfg(feature = "gecko")] + fn compute_squared_distance(&self, other: &Self) -> Result { + let (from, to) = if self.is_3d() || other.is_3d() { + (decompose_3d_matrix(*self)?, decompose_3d_matrix(*other)?) + } else { + (decompose_2d_matrix(self)?, decompose_2d_matrix(other)?) + }; + from.compute_squared_distance(&to) + } } impl From for MatrixDecomposed2D {