Bug 1304886 - Part 5: Make InterpolateTransformMatrix template to calculate accumulation. r?boris draft
authorHiroyuki Ikezoe <hiikezoe@mozilla-japan.org>
Wed, 16 Nov 2016 16:08:23 +0900
changeset 439590 3589dce49657ac79e2ec5e13dbdd6fd4ec424bac
parent 439589 3b27ffb16d1c4490ebd3decdfb0787c6e12cbf73
child 439591 b01db0833a12235ab817f75e5bb28cb51012e728
push id36056
push userhiikezoe@mozilla-japan.org
push dateWed, 16 Nov 2016 11:13:11 +0000
reviewersboris
bugs1304886
milestone53.0a1
Bug 1304886 - Part 5: Make InterpolateTransformMatrix template to calculate accumulation. r?boris InterpolateTransformMatrix renamed to OperateTransformMatrix. MozReview-Commit-ID: 3IpkAIa3cBN
layout/style/nsStyleTransformMatrix.cpp
--- a/layout/style/nsStyleTransformMatrix.cpp
+++ b/layout/style/nsStyleTransformMatrix.cpp
@@ -259,33 +259,57 @@ ProcessMatrix3D(Matrix4x4& aMatrix,
                                   &aRefBox, &TransformReferenceBox::Height);
   temp._43 = ProcessTranslatePart(aData->Item(15),
                                   aContext, aPresContext, aConditions,
                                   nullptr);
 
   aMatrix = temp * aMatrix;
 }
 
-template<typename T>
-T InterpolateNumerically(const T& aOne, const T& aTwo, double aCoeff)
-{
-  return aOne + (aTwo - aOne) * aCoeff;
-}
+class Interpolate {
+public:
+  template<typename T>
+  static T operate(const T& aOne, const T& aTwo, double aCoeff)
+  {
+    MOZ_ASSERT(aCoeff >= 0.0 && aCoeff <= 1.0,
+               "Coefficient should be in the range [0.0, 1.0]");
+    return aOne + (aTwo - aOne) * aCoeff;
+  }
+
+  static Point3D operateForScale(const Point3D& aOne,
+                                 const Point3D& aTwo,
+                                 double aCoeff)
+  {
+    MOZ_ASSERT(aCoeff >= 0.0 && aCoeff <= 1.0,
+               "Coefficient should be in the range [0.0, 1.0]");
+    return aOne + (aTwo - aOne) * aCoeff;
+  }
+
+  static Matrix4x4 operateForRotate(const gfxQuaternion& aOne,
+                                    const gfxQuaternion& aTwo,
+                                    double aCoeff)
+  {
+    MOZ_ASSERT(aCoeff >= 0.0 && aCoeff <= 1.0,
+               "Coefficient should be in the range [0.0, 1.0]");
+    return aOne.Slerp(aTwo, aCoeff).ToMatrix();
+  }
+};
 
 /**
- * Interpolates between 2 matrices by decomposing them.
+ * Calculate 2 matrices by decomposing them with Operator.
  *
  * @param aMatrix1   First matrix, using CSS pixel units.
  * @param aMatrix2   Second matrix, using CSS pixel units.
- * @param aProgress  Interpolation value in the range [0.0, 1.0]
+ * @param aProgress  Coefficient for the Operator.
  */
+template <typename Operator>
 static Matrix4x4
-InterpolateTransformMatrix(const Matrix4x4 &aMatrix1,
-                           const Matrix4x4 &aMatrix2,
-                           double aProgress)
+OperateTransformMatrix(const Matrix4x4 &aMatrix1,
+                       const Matrix4x4 &aMatrix2,
+                       double aProgress)
 {
   // Decompose both matrices
 
   // TODO: What do we do if one of these returns false (singular matrix)
   Point3D scale1(1, 1, 1), translate1;
   Point4D perspective1(0, 0, 0, 1);
   gfxQuaternion rotate1;
   nsStyleTransformMatrix::ShearArray shear1{0.0f, 0.0f, 0.0f};
@@ -305,57 +329,56 @@ InterpolateTransformMatrix(const Matrix4
     Decompose3DMatrix(aMatrix2, scale2, shear2,
                       rotate2, translate2, perspective2);
   }
 
   // Interpolate each of the pieces
   Matrix4x4 result;
 
   Point4D perspective =
-    InterpolateNumerically(perspective1, perspective2, aProgress);
+    Operator::operate(perspective1, perspective2, aProgress);
   result.SetTransposedVector(3, perspective);
 
   Point3D translate =
-    InterpolateNumerically(translate1, translate2, aProgress);
+    Operator::operate(translate1, translate2, aProgress);
   result.PreTranslate(translate.x, translate.y, translate.z);
 
-  gfxQuaternion q3 = rotate1.Slerp(rotate2, aProgress);
-  Matrix4x4 rotate = q3.ToMatrix();
+  Matrix4x4 rotate = Operator::operateForRotate(rotate1, rotate2, aProgress);
   if (!rotate.IsIdentity()) {
     result = rotate * result;
   }
 
   // TODO: Would it be better to interpolate these as angles?
   //       How do we convert back to angles?
   float yzshear =
-    InterpolateNumerically(shear1[ShearType::YZSHEAR],
-                           shear2[ShearType::YZSHEAR],
-                           aProgress);
+    Operator::operate(shear1[ShearType::YZSHEAR],
+                      shear2[ShearType::YZSHEAR],
+                      aProgress);
   if (yzshear != 0.0) {
     result.SkewYZ(yzshear);
   }
 
   float xzshear =
-    InterpolateNumerically(shear1[ShearType::XZSHEAR],
-                           shear2[ShearType::XZSHEAR],
-                           aProgress);
+    Operator::operate(shear1[ShearType::XZSHEAR],
+                      shear2[ShearType::XZSHEAR],
+                      aProgress);
   if (xzshear != 0.0) {
     result.SkewXZ(xzshear);
   }
 
   float xyshear =
-    InterpolateNumerically(shear1[ShearType::XYSHEAR],
-                           shear2[ShearType::XYSHEAR],
-                           aProgress);
+    Operator::operate(shear1[ShearType::XYSHEAR],
+                      shear2[ShearType::XYSHEAR],
+                      aProgress);
   if (xyshear != 0.0) {
     result.SkewXY(xyshear);
   }
 
   Point3D scale =
-    InterpolateNumerically(scale1, scale2, aProgress);
+    Operator::operateForScale(scale1, scale2, aProgress);
   if (scale != Point3D(1.0, 1.0, 1.0)) {
     result.PreScale(scale.x, scale.y, scale.z);
   }
 
   return result;
 }
 
 /* Helper function to process two matrices that we need to interpolate between */
@@ -382,17 +405,18 @@ ProcessInterpolateMatrix(Matrix4x4& aMat
     matrix2 = ReadTransforms(aData->Item(2).GetListValue(),
                              aContext, aPresContext,
                              aConditions,
                              aRefBox, nsPresContext::AppUnitsPerCSSPixel(),
                              aContains3dTransform);
   }
   double progress = aData->Item(3).GetPercentValue();
 
-  aMatrix = InterpolateTransformMatrix(matrix1, matrix2, progress) * aMatrix;
+  aMatrix =
+    OperateTransformMatrix<Interpolate>(matrix1, matrix2, progress) * aMatrix;
 }
 
 /* Helper function to process a translatex function. */
 static void
 ProcessTranslateX(Matrix4x4& aMatrix,
                   const nsCSSValue::Array* aData,
                   nsStyleContext* aContext,
                   nsPresContext* aPresContext,