Bug 952011 - Add gfx3DMatrix API for untransformed rects and points. r=bjacob
☠☠ backed out by 1bb4238bdde3 ☠ ☠
authorMatt Woodrow <mwoodrow@mozilla.com>
Wed, 29 Jan 2014 13:10:35 +1300
changeset 182184 577290ff145dca450e21853d8aa6f15949f48f45
parent 182183 89491b5d0af844e2d20fa9d4c16a1703f22b04ad
child 182185 4133759094589ce41e2da848416b7b51ac21d88b
push id3343
push userffxbld
push dateMon, 17 Mar 2014 21:55:32 +0000
treeherdermozilla-beta@2f7d3415f79f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersbjacob
bugs952011
milestone29.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 952011 - Add gfx3DMatrix API for untransformed rects and points. r=bjacob
gfx/thebes/gfx3DMatrix.cpp
gfx/thebes/gfx3DMatrix.h
--- a/gfx/thebes/gfx3DMatrix.cpp
+++ b/gfx/thebes/gfx3DMatrix.cpp
@@ -783,20 +783,19 @@ gfxPoint gfx3DMatrix::ProjectPoint(const
   return result;
 }
 
 gfxRect gfx3DMatrix::ProjectRectBounds(const gfxRect& aRect) const
 {
   gfxPoint points[4];
 
   points[0] = ProjectPoint(aRect.TopLeft());
-  points[1] = ProjectPoint(gfxPoint(aRect.X() + aRect.Width(), aRect.Y()));
-  points[2] = ProjectPoint(gfxPoint(aRect.X(), aRect.Y() + aRect.Height()));
-  points[3] = ProjectPoint(gfxPoint(aRect.X() + aRect.Width(),
-                                    aRect.Y() + aRect.Height()));
+  points[1] = ProjectPoint(aRect.TopRight());
+  points[2] = ProjectPoint(aRect.BottomLeft());
+  points[3] = ProjectPoint(aRect.BottomRight());
 
   gfxFloat min_x, max_x;
   gfxFloat min_y, max_y;
 
   min_x = max_x = points[0].x;
   min_y = max_y = points[0].y;
 
   for (int i=1; i<4; i++) {
@@ -804,16 +803,37 @@ gfxRect gfx3DMatrix::ProjectRectBounds(c
     max_x = max(points[i].x, max_x);
     min_y = min(points[i].y, min_y);
     max_y = max(points[i].y, max_y);
   }
 
   return gfxRect(min_x, min_y, max_x - min_x, max_y - min_y);
 }
 
+gfxRect gfx3DMatrix::UntransformBounds(const gfxRect& aRect, const gfxRect& aChildBounds) const
+{
+  gfxRect bounds = TransformBounds(aChildBounds);
+
+  gfxRect rect = aRect.Intersect(bounds);
+
+  return Inverse().ProjectRectBounds(rect);
+}
+
+bool gfx3DMatrix::UntransformPoint(const gfxPoint& aPoint, const gfxRect& aChildBounds, gfxPoint* aOut) const
+{
+  gfxRect bounds = TransformBounds(aChildBounds);
+
+  if (!bounds.Contains(aPoint)) {
+    return false;
+  }
+
+  *aOut = Inverse().ProjectPoint(aPoint);
+  return true;
+}
+
 gfxPoint3D gfx3DMatrix::GetNormalVector() const
 {
   // Define a plane in transformed space as the transformations
   // of 3 points on the z=0 screen plane.
   gfxPoint3D a = Transform3D(gfxPoint3D(0, 0, 0));
   gfxPoint3D b = Transform3D(gfxPoint3D(0, 1, 0));
   gfxPoint3D c = Transform3D(gfxPoint3D(1, 0, 0));
 
--- a/gfx/thebes/gfx3DMatrix.h
+++ b/gfx/thebes/gfx3DMatrix.h
@@ -245,16 +245,35 @@ public:
    */
   gfxPoint3D Transform3D(const gfxPoint3D& point) const;
   gfxPointH3D Transform4D(const gfxPointH3D& aPoint) const;
   gfxPointH3D TransposeTransform4D(const gfxPointH3D& aPoint) const;
 
   gfxPoint ProjectPoint(const gfxPoint& aPoint) const;
   gfxRect ProjectRectBounds(const gfxRect& aRect) const;
 
+  /**
+   * Transforms a point by the inverse of this matrix. In the case of projective transforms, some screen
+   * points have no equivalent in the untransformed plane (if they exist past the vanishing point). To
+   * avoid this, we need to specify the bounds of the untransformed plane to restrict the search area.
+   *
+   * @param aPoint Point to untransform.
+   * @param aChildBounds Bounds of the untransformed plane.
+   * @param aOut Untransformed point.
+   * @return Returns true if a point was found within a ChildBounds, false otherwise.
+   */
+  bool UntransformPoint(const gfxPoint& aPoint, const gfxRect& aChildBounds, gfxPoint* aOut) const;
+
+
+  /**
+   * Same as UntransformPoint, but untransforms a rect and returns the bounding rect of the result.
+   * Returns an empty rect if the result doesn't intersect aChildBounds.
+   */
+  gfxRect UntransformBounds(const gfxRect& aRect, const gfxRect& aChildBounds) const;
+
 
   /**
    * Inverts this matrix, if possible. Otherwise, the matrix is left
    * unchanged.
    */
   gfx3DMatrix Inverse() const;
 
   gfx3DMatrix& Invert()