Bug 1424134 - Part 1: Factor the mako code out from transform functions. r=emilio
authorBoris Chiou <boris.chiou@gmail.com>
Fri, 16 Nov 2018 18:58:37 +0000
changeset 503293 f70b47c227bf34b382e1188ade0c84950b5e41ea
parent 503292 c62c378d4f58e2d82a52b329e312cf9f0758cbc1
child 503294 f0c56dea286e3ffc9ae90bc56e702060388af651
push id10290
push userffxbld-merge
push dateMon, 03 Dec 2018 16:23:23 +0000
treeherdermozilla-beta@700bed2445e6 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersemilio
bugs1424134
milestone65.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1424134 - Part 1: Factor the mako code out from transform functions. r=emilio I'm trying to put all the mako code together, so we could move transform code into a different file. Differential Revision: https://phabricator.services.mozilla.com/D11933
servo/components/style/properties/helpers/animated_properties.mako.rs
--- a/servo/components/style/properties/helpers/animated_properties.mako.rs
+++ b/servo/components/style/properties/helpers/animated_properties.mako.rs
@@ -1439,17 +1439,17 @@ impl From<MatrixDecomposed2D> for Matrix
 
         let mut rotate_matrix = Matrix3D::identity();
         rotate_matrix.m11 = cos_angle;
         rotate_matrix.m12 = sin_angle;
         rotate_matrix.m21 = -sin_angle;
         rotate_matrix.m22 = cos_angle;
 
         // Multiplication of computed_matrix and rotate_matrix
-        computed_matrix = multiply(rotate_matrix, computed_matrix);
+        computed_matrix = rotate_matrix.multiply(&computed_matrix);
 
         // Scale matrix.
         computed_matrix.m11 *= decomposed.scale.0;
         computed_matrix.m12 *= decomposed.scale.0;
         computed_matrix.m21 *= decomposed.scale.1;
         computed_matrix.m22 *= decomposed.scale.1;
         computed_matrix
     }
@@ -1539,16 +1539,22 @@ impl Quaternion {
                    (angle / 2.).cos())
     }
 
     /// Calculate the dot product.
     #[inline]
     fn dot(&self, other: &Self) -> f64 {
         self.0 * other.0 + self.1 * other.1 + self.2 * other.2 + self.3 * other.3
     }
+
+    /// Return the scaled quaternion by a factor.
+    #[inline]
+    fn scale(&self, factor: f64) -> Self {
+        Quaternion(self.0 * factor, self.1 * factor, self.2 * factor, self.3 * factor)
+    }
 }
 
 impl Animate for Quaternion {
     fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> {
         use std::f64;
 
         let (this_weight, other_weight) = procedure.weights();
         debug_assert!(
@@ -1608,22 +1614,18 @@ impl Animate for Quaternion {
         }
 
         let theta = dot.acos();
         let rsintheta = 1.0 / (1.0 - dot * dot).sqrt();
 
         let right_weight = (other_weight * theta).sin() * rsintheta;
         let left_weight = (other_weight * theta).cos() - dot * right_weight;
 
-        let mut left = *self;
-        let mut right = *other;
-        % for i in range(4):
-            left.${i} *= left_weight;
-            right.${i} *= right_weight;
-        % endfor
+        let left = self.scale(left_weight);
+        let right = other.scale(right_weight);
 
         Ok(Quaternion(
             left.0 + right.0,
             left.1 + right.1,
             left.2 + right.2,
             left.3 + right.3,
         ))
     }
@@ -1639,29 +1641,24 @@ impl ComputeSquaredDistance for Quaterni
         Ok(SquaredDistance::from_sqrt(distance))
     }
 }
 
 /// Decompose a 3D matrix.
 /// https://drafts.csswg.org/css-transforms-2/#decomposing-a-3d-matrix
 /// http://www.realtimerendering.com/resources/GraphicsGems/gemsii/unmatrix.c
 fn decompose_3d_matrix(mut matrix: Matrix3D) -> Result<MatrixDecomposed3D, ()> {
-    // Normalize the matrix.
     if matrix.m44 == 0.0 {
         return Err(());
     }
 
     let scaling_factor = matrix.m44;
 
     // Normalize the matrix.
-    % for i in range(1, 5):
-        % for j in range(1, 5):
-            matrix.m${i}${j} /= scaling_factor;
-        % endfor
-    % endfor
+    matrix.scale_by_factor(1.0 / scaling_factor);
 
     // perspective_matrix is used to solve for perspective, but it also provides
     // an easy way to test for singularity of the upper 3x3 component.
     let mut perspective_matrix = matrix;
 
     perspective_matrix.m14 = 0.0;
     perspective_matrix.m24 = 0.0;
     perspective_matrix.m34 = 0.0;
@@ -1689,22 +1686,17 @@ fn decompose_3d_matrix(mut matrix: Matri
     } else {
         Perspective(0.0, 0.0, 0.0, 1.0)
     };
 
     // Next take care of translation (easy).
     let translate = Translate3D(matrix.m41, matrix.m42, matrix.m43);
 
     // Now get scale and shear. 'row' is a 3 element array of 3 component vectors
-    let mut row: [[f32; 3]; 3] = [[0.0; 3]; 3];
-    % for i in range(1, 4):
-        row[${i - 1}][0] = matrix.m${i}1;
-        row[${i - 1}][1] = matrix.m${i}2;
-        row[${i - 1}][2] = matrix.m${i}3;
-    % endfor
+    let mut row = matrix.get_matrix_3x3_part();
 
     // Compute X scale factor and normalize first row.
     let row0len = (row[0][0] * row[0][0] + row[0][1] * row[0][1] + row[0][2] * row[0][2]).sqrt();
     let mut scale = Scale3D(row0len, 0.0, 0.0);
     row[0] = [row[0][0] / row0len, row[0][1] / row0len, row[0][2] / row0len];
 
     // Compute XY shear factor and make 2nd row orthogonal to 1st.
     let mut skew = Skew(dot(row[0], row[1]), 0.0, 0.0);
@@ -1728,22 +1720,17 @@ fn decompose_3d_matrix(mut matrix: Matri
     row[2] = [row[2][0] / row2len, row[2][1] / row2len, row[2][2] / row2len];
     skew.1 /= scale.2;
     skew.2 /= scale.2;
 
     // At this point, the matrix (in rows) is orthonormal.
     // Check for a coordinate system flip.  If the determinant
     // is -1, then negate the matrix and the scaling factors.
     if dot(row[0], cross(row[1], row[2])) < 0.0 {
-        % for i in range(3):
-            scale.${i} *= -1.0;
-            row[${i}][0] *= -1.0;
-            row[${i}][1] *= -1.0;
-            row[${i}][2] *= -1.0;
-        % endfor
+        negate_matrix_3x3_and_scaling_factor(&mut row, &mut scale);
     }
 
     // Now, get the rotations out.
     let mut quaternion = Quaternion(
         0.5 * ((1.0 + row[0][0] - row[1][1] - row[2][2]).max(0.0) as f64).sqrt(),
         0.5 * ((1.0 - row[0][0] + row[1][1] - row[2][2]).max(0.0) as f64).sqrt(),
         0.5 * ((1.0 - row[0][0] - row[1][1] + row[2][2]).max(0.0) as f64).sqrt(),
         0.5 * ((1.0 + row[0][0] + row[1][1] + row[2][2]).max(0.0) as f64).sqrt()
@@ -1763,16 +1750,27 @@ fn decompose_3d_matrix(mut matrix: Matri
         translate,
         scale,
         skew,
         perspective,
         quaternion,
     })
 }
 
+/// Negate the matrix and the scaling factors.
+#[inline]
+fn negate_matrix_3x3_and_scaling_factor(row: &mut [[f32; 3]; 3], scale: &mut Scale3D) {
+    % for i in range(3):
+        scale.${i} *= -1.0;
+        row[${i}][0] *= -1.0;
+        row[${i}][1] *= -1.0;
+        row[${i}][2] *= -1.0;
+    % endfor
+}
+
 /// Decompose a 2D matrix for Gecko.
 // Use the algorithm from nsStyleTransformMatrix::Decompose2DMatrix() in Gecko.
 #[cfg(feature = "gecko")]
 fn decompose_2d_matrix(matrix: &Matrix3D) -> 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 |
@@ -1877,26 +1875,20 @@ impl Animate for Perspective {
 
 impl From<MatrixDecomposed3D> for Matrix3D {
     /// Recompose a 3D matrix.
     /// <https://drafts.csswg.org/css-transforms/#recomposing-to-a-3d-matrix>
     fn from(decomposed: MatrixDecomposed3D) -> Matrix3D {
         let mut matrix = Matrix3D::identity();
 
         // Apply perspective
-        % for i in range(1, 5):
-            matrix.m${i}4 = decomposed.perspective.${i - 1};
-        % endfor
+        matrix.set_perspective(&decomposed.perspective);
 
         // Apply translation
-        % for i in range(1, 5):
-            % for j in range(1, 4):
-                matrix.m4${i} += decomposed.translate.${j - 1} * matrix.m${j}${i};
-            % endfor
-        % endfor
+        matrix.apply_translate(&decomposed.translate);
 
         // Apply rotation
         {
             let x = decomposed.quaternion.0;
             let y = decomposed.quaternion.1;
             let z = decomposed.quaternion.2;
             let w = decomposed.quaternion.3;
 
@@ -1908,66 +1900,47 @@ impl From<MatrixDecomposed3D> for Matrix
             rotation_matrix.m13 = 2.0 * (x * z - y * w) as f32;
             rotation_matrix.m21 = 2.0 * (x * y - z * w) as f32;
             rotation_matrix.m22 = 1.0 - 2.0 * (x * x + z * z) as f32;
             rotation_matrix.m23 = 2.0 * (y * z + x * w) as f32;
             rotation_matrix.m31 = 2.0 * (x * z + y * w) as f32;
             rotation_matrix.m32 = 2.0 * (y * z - x * w) as f32;
             rotation_matrix.m33 = 1.0 - 2.0 * (x * x + y * y) as f32;
 
-            matrix = multiply(rotation_matrix, matrix);
+            matrix = rotation_matrix.multiply(&matrix);
         }
 
         // Apply skew
         {
             let mut temp = Matrix3D::identity();
             if decomposed.skew.2 != 0.0 {
                 temp.m32 = decomposed.skew.2;
-                matrix = multiply(temp, matrix);
+                matrix = temp.multiply(&matrix);
                 temp.m32 = 0.0;
             }
 
             if decomposed.skew.1 != 0.0 {
                 temp.m31 = decomposed.skew.1;
-                matrix = multiply(temp, matrix);
+                matrix = temp.multiply(&matrix);
                 temp.m31 = 0.0;
             }
 
             if decomposed.skew.0 != 0.0 {
                 temp.m21 = decomposed.skew.0;
-                matrix = multiply(temp, matrix);
+                matrix = temp.multiply(&matrix);
             }
         }
 
         // Apply scale
-        % for i in range(1, 4):
-        % for j in range(1, 5):
-        matrix.m${i}${j} *= decomposed.scale.${i - 1};
-        % endfor
-        % endfor
+        matrix.apply_scale(&decomposed.scale);
 
         matrix
     }
 }
 
-// Multiplication of two 4x4 matrices.
-fn multiply(a: Matrix3D, b: Matrix3D) -> Matrix3D {
-    Matrix3D {
-    % for i in range(1, 5):
-    % for j in range(1, 5):
-        m${i}${j}:
-            a.m${i}1 * b.m1${j} +
-            a.m${i}2 * b.m2${j} +
-            a.m${i}3 * b.m3${j} +
-            a.m${i}4 * b.m4${j},
-    % endfor
-    % endfor
-    }
-}
-
 impl Matrix3D {
     fn is_3d(&self) -> bool {
         self.m13 != 0.0 || self.m14 != 0.0 ||
         self.m23 != 0.0 || self.m24 != 0.0 ||
         self.m31 != 0.0 || self.m32 != 0.0 || self.m33 != 1.0 || self.m34 != 0.0 ||
         self.m43 != 0.0 || self.m44 != 1.0
     }
 
@@ -2093,16 +2066,82 @@ impl Matrix3D {
         % for i in range(1, 5):
             pin[0] * self.m1${i} +
             pin[1] * self.m2${i} +
             pin[2] * self.m3${i} +
             pin[3] * self.m4${i},
         % endfor
         ]
     }
+
+    /// Multiplication of two 4x4 matrices.
+    fn multiply(&self, other: &Self) -> Self {
+        Matrix3D {
+        % for i in range(1, 5):
+            % for j in range(1, 5):
+                m${i}${j}:
+                    self.m${i}1 * other.m1${j} +
+                    self.m${i}2 * other.m2${j} +
+                    self.m${i}3 * other.m3${j} +
+                    self.m${i}4 * other.m4${j},
+            % endfor
+        % endfor
+        }
+    }
+
+    /// Normalize the matrix.
+    #[inline]
+    fn scale_by_factor(&mut self, scaling_factor: CSSFloat) {
+        % for i in range(1, 5):
+        % for j in range(1, 5):
+            self.m${i}${j} *= scaling_factor;
+        % endfor
+        % endfor
+    }
+
+    /// This is used by retrieving the scale and shear factors
+    /// during decomposing a 3d matrix.
+    #[inline]
+    fn get_matrix_3x3_part(&self) -> [[f32; 3]; 3] {
+        let mut row: [[f32; 3]; 3] = [[0.0; 3]; 3];
+        % for i in range(1, 4):
+            row[${i - 1}][0] = self.m${i}1;
+            row[${i - 1}][1] = self.m${i}2;
+            row[${i - 1}][2] = self.m${i}3;
+        % endfor
+        row
+    }
+
+    /// Set perspective on the matrix.
+    #[inline]
+    fn set_perspective(&mut self, perspective: &Perspective) {
+        % for i in range(1, 5):
+            self.m${i}4 = perspective.${i - 1};
+        % endfor
+    }
+
+    /// Apply translate on the matrix.
+    #[inline]
+    fn apply_translate(&mut self, translate: &Translate3D) {
+        % for i in range(1, 5):
+        % for j in range(1, 4):
+            self.m4${i} += translate.${j - 1} * self.m${j}${i};
+        % endfor
+        % endfor
+    }
+
+    /// Apply scale on the matrix
+    #[inline]
+    fn apply_scale(&mut self, scale: &Scale3D) {
+        % for i in range(1, 4):
+        % for j in range(1, 5):
+            self.m${i}${j} *= scale.${i - 1};
+        % endfor
+        % endfor
+    }
 }
 
 /// <https://drafts.csswg.org/css-transforms-2/#propdef-rotate>
 impl ComputedRotate {
     fn resolve(&self) -> (Number, Number, Number, Angle) {
         // According to the spec:
         // https://drafts.csswg.org/css-transforms-2/#individual-transforms
         //