aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/style/properties/helpers/animated_properties.mako.rs82
1 files changed, 82 insertions, 0 deletions
diff --git a/components/style/properties/helpers/animated_properties.mako.rs b/components/style/properties/helpers/animated_properties.mako.rs
index a97b8e26042..683c23555ce 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<Self, ()> {
if self.is_3d() || other.is_3d() {
let decomposed_from = decompose_3d_matrix(*self);
@@ -1419,10 +1420,30 @@ impl Animate for ComputedMatrix {
Ok(ComputedMatrix::from(this.animate(&other, procedure)?))
}
}
+
+ #[cfg(feature = "gecko")]
+ fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
+ 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 {
#[inline]
+ #[cfg(feature = "servo")]
fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
if self.is_3d() || other.is_3d() {
let from = decompose_3d_matrix(*self)?;
@@ -1434,6 +1455,17 @@ impl ComputeSquaredDistance for ComputedMatrix {
from.compute_squared_distance(&to)
}
}
+
+ #[inline]
+ #[cfg(feature = "gecko")]
+ fn compute_squared_distance(&self, other: &Self) -> Result<SquaredDistance, ()> {
+ 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<ComputedMatrix> for MatrixDecomposed2D {
@@ -1830,6 +1862,56 @@ fn decompose_3d_matrix(mut matrix: ComputedMatrix) -> Result<MatrixDecomposed3D,
})
}
+/// Decompose a 2D matrix for Gecko.
+// Use the algorithm from nsStyleTransformMatrix::Decompose2DMatrix() in Gecko.
+#[cfg(feature = "gecko")]
+fn decompose_2d_matrix(matrix: &ComputedMatrix) -> Result<MatrixDecomposed3D, ()> {
+ // 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] {
[