Bug 1272549 - Part 8: Compute distance for perspective transform function. r=birtles
authorBoris Chiou <boris.chiou@gmail.com>
Mon, 03 Oct 2016 16:04:24 +0800
changeset 319300 6f417fc0c45dafc11140c31820689514f1b213b1
parent 319299 00e8df3987f90a27f85232eb38cdfe920ff7dad9
child 319301 89e37cf072fe2bfae86de8d985bfe8f9502a3d40
push id30869
push userphilringnalda@gmail.com
push dateWed, 26 Oct 2016 04:57:48 +0000
treeherdermozilla-central@9471b3c49b2c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbirtles
bugs1272549
milestone52.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 1272549 - Part 8: Compute distance for perspective transform function. r=birtles MozReview-Commit-ID: IUL9RYuP82r
layout/style/StyleAnimationValue.cpp
--- a/layout/style/StyleAnimationValue.cpp
+++ b/layout/style/StyleAnimationValue.cpp
@@ -917,20 +917,47 @@ ComputeTransformDistance(nsCSSValue::Arr
         // cos(theta/2) = (q1 dot q2) / (|q1| * |q2|) = q1 dot q2.
         gfxQuaternion q1(vector1, a1->Item(4).GetAngleValueInRadians());
         gfxQuaternion q2(vector2, a2->Item(4).GetAngleValueInRadians());
         distance = 2.0 * acos(clamped(q1.DotProduct(q2), -1.0, 1.0));
         distance = distance * distance;
       }
       break;
     }
-    case eCSSKeyword_perspective:
-      // TODO: This will be fixed in the later patch.
-      distance = 0.0;
+    case eCSSKeyword_perspective: {
+      MOZ_ASSERT(a1->Count() == 2, "unexpected count");
+      MOZ_ASSERT(a2->Count() == 2, "unexpected count");
+
+      // We convert a perspective function into an equivalent matrix3d, and
+      // then do matrix decomposition to get the distance.
+      // Why don't we just subtract one perspective depth from the other?
+      // I think it's better to follow the logic of our interpolation,
+      // which does linear interpolation between two decomposed perspective
+      // vectors.
+      // e.g.
+      // Do interpolation between perspective(100px) and perspective(1000px).
+      //   1) Convert them into matrix3d, and then do matrix decomposition:
+      //      perspective vector 1: perspective(0, 0, -1/100, 1);
+      //      perspective vector 2: perspective(0, 0, -1/1000, 1);
+      //   2) Do linear interpolation between these two vectors.
+      // Therefore, we use the same rule to get the distance as what we do for
+      // matrix3d.
+
+      auto clampPerspectiveDepth = [](float aDepth) {
+        // Perspective depth should be positive non-zero value.
+        return std::max(aDepth, std::numeric_limits<float>::epsilon());
+      };
+      Matrix4x4 m1;
+      m1.Perspective(clampPerspectiveDepth(a1->Item(1).GetFloatValue()));
+      Matrix4x4 m2;
+      m2.Perspective(clampPerspectiveDepth(a2->Item(1).GetFloatValue()));
+
+      distance = ComputeTransform3DMatrixDistance(m1, m2);
       break;
+    }
     case eCSSKeyword_matrix: {
       MOZ_ASSERT(a1->Count() == 7, "unexpected count");
       MOZ_ASSERT(a2->Count() == 7, "unexpected count");
 
       distance = ComputeTransform2DMatrixDistance(
         nsStyleTransformMatrix::CSSValueArrayTo2DMatrix(a1),
         nsStyleTransformMatrix::CSSValueArrayTo2DMatrix(a2));
       break;