Bug 1272549 - Part 8: Compute distance for perspective transform function. draft
 author Boris Chiou Mon, 03 Oct 2016 16:04:24 +0800 changeset 428020 f1c1f056c462f3fdd6109f765e92ea4e1303886b parent 428019 ad44760225a6229a7bc1eef231683e3acd90da1e child 428021 3ae9ca098462ae4e7692cba3f3491c3fdb3233da push id 33211 push user bmo:boris.chiou@gmail.com push date Fri, 21 Oct 2016 13:32:53 +0000 bugs 1272549 milestone 52.0a1
Bug 1272549 - Part 8: Compute distance for perspective transform function. MozReview-Commit-ID: IUL9RYuP82r
```--- a/layout/style/StyleAnimationValue.cpp
+++ b/layout/style/StyleAnimationValue.cpp
@@ -933,20 +933,47 @@ ComputeTransformDistance(nsCSSValue::Arr
// cos(theta/2) = (q1 dot q2) / (|q1| * |q2|) = q1 dot q2.
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 interpolation process,
+      // which do 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;```