Bug 781701 - Interpolate rotate3d rotation angles numerically when we can instead of using matrix decompositon. r=dbaron
authorMatt Woodrow <mwoodrow@mozilla.com>
Tue, 19 Aug 2014 15:58:17 +1200
changeset 200237 309b1499160da628ba2ccd1f584271537ab6a6d4
parent 200236 cdf1cbfe5c4943094960d8f1b3176e05a921fb14
child 200238 55ea2c2fb857d86b36bf05e96a19708bae5c3ef8
push id47846
push usermwoodrow@mozilla.com
push dateTue, 19 Aug 2014 03:58:26 +0000
treeherdermozilla-inbound@309b1499160d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdbaron
bugs781701
milestone34.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 781701 - Interpolate rotate3d rotation angles numerically when we can instead of using matrix decompositon. r=dbaron
layout/style/StyleAnimationValue.cpp
layout/style/nsStyleTransformMatrix.cpp
--- a/layout/style/StyleAnimationValue.cpp
+++ b/layout/style/StyleAnimationValue.cpp
@@ -1808,20 +1808,46 @@ AddTransformLists(double aCoeff1, const 
         NS_ABORT_IF_FALSE(a1->Count() == 2, "unexpected count");
         NS_ABORT_IF_FALSE(a2->Count() == 2, "unexpected count");
 
         AddCSSValueAngle(aCoeff1, a1->Item(1), aCoeff2, a2->Item(1),
                          arr->Item(1));
 
         break;
       }
+      case eCSSKeyword_rotate3d: {
+        gfxPoint3D vector1(a1->Item(1).GetFloatValue(),
+                           a1->Item(2).GetFloatValue(),
+                           a1->Item(3).GetFloatValue());
+        vector1.Normalize();
+        gfxPoint3D vector2(a2->Item(1).GetFloatValue(),
+                           a2->Item(2).GetFloatValue(),
+                           a2->Item(3).GetFloatValue());
+        vector2.Normalize();
+
+        // Handle rotate3d with matched (normalized) vectors,
+        // otherwise fallthrough to the next switch statement
+        // and do matrix decomposition.
+        if (vector1 == vector2) {
+          // We skipped appending a transform function above for rotate3d,
+          // so do it now.
+          arr = StyleAnimationValue::AppendTransformFunction(tfunc, resultTail);
+          arr->Item(1).SetFloatValue(vector1.x, eCSSUnit_Number);
+          arr->Item(2).SetFloatValue(vector1.y, eCSSUnit_Number);
+          arr->Item(3).SetFloatValue(vector1.z, eCSSUnit_Number);
+
+          AddCSSValueAngle(aCoeff1, a1->Item(4), aCoeff2, a2->Item(4),
+                           arr->Item(4));
+          break;
+        }
+        // FALL THROUGH
+      }
       case eCSSKeyword_matrix:
       case eCSSKeyword_matrix3d:
       case eCSSKeyword_interpolatematrix:
-      case eCSSKeyword_rotate3d:
       case eCSSKeyword_perspective: {
         // FIXME: If the matrix contains only numbers then we could decompose
         // here.
 
         // Construct temporary lists with only this item in them.
         nsCSSValueList tempList1, tempList2;
         tempList1.mValue = aList1->mValue;
         tempList2.mValue = aList2->mValue;
--- a/layout/style/nsStyleTransformMatrix.cpp
+++ b/layout/style/nsStyleTransformMatrix.cpp
@@ -432,43 +432,39 @@ ProcessRotate3D(gfx3DMatrix& aMatrix, co
   /* The current spec specifies a matrix that rotates in the wrong direction. For now we just negate
    * the angle provided to get the correct rotation direction until the spec is updated.
    * See bug 704468.
    */
   double theta = -aData->Item(4).GetAngleValueInRadians();
   float cosTheta = FlushToZero(cos(theta));
   float sinTheta = FlushToZero(sin(theta));
 
-  float x = aData->Item(1).GetFloatValue();
-  float y = aData->Item(2).GetFloatValue();
-  float z = aData->Item(3).GetFloatValue();
+  gfxPoint3D vector(aData->Item(1).GetFloatValue(),
+                    aData->Item(2).GetFloatValue(),
+                    aData->Item(3).GetFloatValue());
 
-  /* Normalize [x,y,z] */
-  float length = sqrt(x*x + y*y + z*z);
-  if (length == 0.0) {
+  if (!vector.Length()) {
     return;
   }
-  x /= length;
-  y /= length;
-  z /= length;
+  vector.Normalize();
 
   gfx3DMatrix temp;
 
   /* Create our matrix */
-  temp._11 = 1 + (1 - cosTheta) * (x * x - 1);
-  temp._12 = -z * sinTheta + (1 - cosTheta) * x * y;
-  temp._13 = y * sinTheta + (1 - cosTheta) * x * z;
+  temp._11 = 1 + (1 - cosTheta) * (vector.x * vector.x - 1);
+  temp._12 = -vector.z * sinTheta + (1 - cosTheta) * vector.x * vector.y;
+  temp._13 = vector.y * sinTheta + (1 - cosTheta) * vector.x * vector.z;
   temp._14 = 0.0f;
-  temp._21 = z * sinTheta + (1 - cosTheta) * x * y;
-  temp._22 = 1 + (1 - cosTheta) * (y * y - 1);
-  temp._23 = -x * sinTheta + (1 - cosTheta) * y * z;
+  temp._21 = vector.z * sinTheta + (1 - cosTheta) * vector.x * vector.y;
+  temp._22 = 1 + (1 - cosTheta) * (vector.y * vector.y - 1);
+  temp._23 = -vector.x * sinTheta + (1 - cosTheta) * vector.y * vector.z;
   temp._24 = 0.0f;
-  temp._31 = -y * sinTheta + (1 - cosTheta) * x * z;
-  temp._32 = x * sinTheta + (1 - cosTheta) * y * z;
-  temp._33 = 1 + (1 - cosTheta) * (z * z - 1);
+  temp._31 = -vector.y * sinTheta + (1 - cosTheta) * vector.x * vector.z;
+  temp._32 = vector.x * sinTheta + (1 - cosTheta) * vector.y * vector.z;
+  temp._33 = 1 + (1 - cosTheta) * (vector.z * vector.z - 1);
   temp._34 = 0.0f;
   temp._41 = 0.0f;
   temp._42 = 0.0f;
   temp._43 = 0.0f;
   temp._44 = 1.0f;
 
   aMatrix = temp * aMatrix;
 }