Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCMathUtil.cpp (119057 => 119058)
--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCMathUtil.cpp 2012-05-31 05:58:45 UTC (rev 119057)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCMathUtil.cpp 2012-05-31 06:05:30 UTC (rev 119058)
@@ -33,37 +33,6 @@
namespace WebCore {
-struct HomogeneousCoordinate {
- HomogeneousCoordinate(double newX, double newY, double newZ, double newW)
- : x(newX)
- , y(newY)
- , z(newZ)
- , w(newW)
- {
- }
-
- bool shouldBeClipped() const
- {
- return w <= 0;
- }
-
- FloatPoint cartesianPoint2d() const
- {
- if (w == 1)
- return FloatPoint(x, y);
-
- // For now, because this code is used privately only by CCMathUtil, it should never be called when w == 0, and we do not yet need to handle that case.
- ASSERT(w);
- double invW = 1.0 / w;
- return FloatPoint(x * invW, y * invW);
- }
-
- double x;
- double y;
- double z;
- double w;
-};
-
static HomogeneousCoordinate projectPoint(const TransformationMatrix& transform, const FloatPoint& p)
{
// In this case, the layer we are trying to project onto is perpendicular to ray
@@ -138,55 +107,6 @@
ymax = std::max(p.y(), ymax);
}
-static FloatRect computeEnclosingRect(const HomogeneousCoordinate& h1, const HomogeneousCoordinate& h2, const HomogeneousCoordinate& h3, const HomogeneousCoordinate& h4)
-{
- // This function performs clipping as necessary and computes the enclosing 2d
- // FloatRect of the vertices. Doing these two steps simultaneously allows us to avoid
- // the overhead of storing an unknown number of clipped vertices.
-
- // If no vertices on the quad are clipped, then we can simply return the enclosing rect directly.
- bool somethingClipped = h1.shouldBeClipped() || h2.shouldBeClipped() || h3.shouldBeClipped() || h4.shouldBeClipped();
- if (!somethingClipped) {
- FloatQuad mappedQuad = FloatQuad(h1.cartesianPoint2d(), h2.cartesianPoint2d(), h3.cartesianPoint2d(), h4.cartesianPoint2d());
- return mappedQuad.boundingBox();
- }
-
- bool everythingClipped = h1.shouldBeClipped() && h2.shouldBeClipped() && h3.shouldBeClipped() && h4.shouldBeClipped();
- if (everythingClipped)
- return FloatRect();
-
- float xmin = std::numeric_limits<float>::max();
- float xmax = std::numeric_limits<float>::min();
- float ymin = std::numeric_limits<float>::max();
- float ymax = std::numeric_limits<float>::min();
-
- if (!h1.shouldBeClipped())
- expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, h1.cartesianPoint2d());
-
- if (h1.shouldBeClipped() ^ h2.shouldBeClipped())
- expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, computeClippedPointForEdge(h1, h2).cartesianPoint2d());
-
- if (!h2.shouldBeClipped())
- expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, h2.cartesianPoint2d());
-
- if (h2.shouldBeClipped() ^ h3.shouldBeClipped())
- expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, computeClippedPointForEdge(h2, h3).cartesianPoint2d());
-
- if (!h3.shouldBeClipped())
- expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, h3.cartesianPoint2d());
-
- if (h3.shouldBeClipped() ^ h4.shouldBeClipped())
- expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, computeClippedPointForEdge(h3, h4).cartesianPoint2d());
-
- if (!h4.shouldBeClipped())
- expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, h4.cartesianPoint2d());
-
- if (h4.shouldBeClipped() ^ h1.shouldBeClipped())
- expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, computeClippedPointForEdge(h4, h1).cartesianPoint2d());
-
- return FloatRect(FloatPoint(xmin, ymin), FloatSize(xmax - xmin, ymax - ymin));
-}
-
static inline void addVertexToClippedQuad(const FloatPoint& newVertex, FloatPoint clippedQuad[8], int& numVerticesInClippedQuad)
{
clippedQuad[numVerticesInClippedQuad] = newVertex;
@@ -213,7 +133,7 @@
HomogeneousCoordinate h3 = mapPoint(transform, q.p3());
HomogeneousCoordinate h4 = mapPoint(transform, q.p4());
- return computeEnclosingRect(h1, h2, h3, h4);
+ return computeEnclosingClippedRect(h1, h2, h3, h4);
}
FloatRect CCMathUtil::projectClippedRect(const TransformationMatrix& transform, const FloatRect& srcRect)
@@ -225,7 +145,7 @@
HomogeneousCoordinate h3 = projectPoint(transform, q.p3());
HomogeneousCoordinate h4 = projectPoint(transform, q.p4());
- return computeEnclosingRect(h1, h2, h3, h4);
+ return computeEnclosingClippedRect(h1, h2, h3, h4);
}
void CCMathUtil::mapClippedQuad(const TransformationMatrix& transform, const FloatQuad& srcQuad, FloatPoint clippedQuad[8], int& numVerticesInClippedQuad)
@@ -272,9 +192,9 @@
return FloatRect();
float xmin = std::numeric_limits<float>::max();
- float xmax = std::numeric_limits<float>::min();
+ float xmax = -std::numeric_limits<float>::max();
float ymin = std::numeric_limits<float>::max();
- float ymax = std::numeric_limits<float>::min();
+ float ymax = -std::numeric_limits<float>::max();
for (int i = 0; i < numVertices; ++i)
expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, vertices[i]);
@@ -282,6 +202,56 @@
return FloatRect(FloatPoint(xmin, ymin), FloatSize(xmax - xmin, ymax - ymin));
}
+FloatRect CCMathUtil::computeEnclosingClippedRect(const HomogeneousCoordinate& h1, const HomogeneousCoordinate& h2, const HomogeneousCoordinate& h3, const HomogeneousCoordinate& h4)
+{
+ // This function performs clipping as necessary and computes the enclosing 2d
+ // FloatRect of the vertices. Doing these two steps simultaneously allows us to avoid
+ // the overhead of storing an unknown number of clipped vertices.
+
+ // If no vertices on the quad are clipped, then we can simply return the enclosing rect directly.
+ bool somethingClipped = h1.shouldBeClipped() || h2.shouldBeClipped() || h3.shouldBeClipped() || h4.shouldBeClipped();
+ if (!somethingClipped) {
+ FloatQuad mappedQuad = FloatQuad(h1.cartesianPoint2d(), h2.cartesianPoint2d(), h3.cartesianPoint2d(), h4.cartesianPoint2d());
+ return mappedQuad.boundingBox();
+ }
+
+ bool everythingClipped = h1.shouldBeClipped() && h2.shouldBeClipped() && h3.shouldBeClipped() && h4.shouldBeClipped();
+ if (everythingClipped)
+ return FloatRect();
+
+
+ float xmin = std::numeric_limits<float>::max();
+ float xmax = -std::numeric_limits<float>::max();
+ float ymin = std::numeric_limits<float>::max();
+ float ymax = -std::numeric_limits<float>::max();
+
+ if (!h1.shouldBeClipped())
+ expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, h1.cartesianPoint2d());
+
+ if (h1.shouldBeClipped() ^ h2.shouldBeClipped())
+ expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, computeClippedPointForEdge(h1, h2).cartesianPoint2d());
+
+ if (!h2.shouldBeClipped())
+ expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, h2.cartesianPoint2d());
+
+ if (h2.shouldBeClipped() ^ h3.shouldBeClipped())
+ expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, computeClippedPointForEdge(h2, h3).cartesianPoint2d());
+
+ if (!h3.shouldBeClipped())
+ expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, h3.cartesianPoint2d());
+
+ if (h3.shouldBeClipped() ^ h4.shouldBeClipped())
+ expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, computeClippedPointForEdge(h3, h4).cartesianPoint2d());
+
+ if (!h4.shouldBeClipped())
+ expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, h4.cartesianPoint2d());
+
+ if (h4.shouldBeClipped() ^ h1.shouldBeClipped())
+ expandBoundsToIncludePoint(xmin, xmax, ymin, ymax, computeClippedPointForEdge(h4, h1).cartesianPoint2d());
+
+ return FloatRect(FloatPoint(xmin, ymin), FloatSize(xmax - xmin, ymax - ymin));
+}
+
FloatQuad CCMathUtil::mapQuad(const TransformationMatrix& transform, const FloatQuad& q, bool& clipped)
{
if (transform.isIdentityOrTranslation()) {
Modified: trunk/Source/WebCore/platform/graphics/chromium/cc/CCMathUtil.h (119057 => 119058)
--- trunk/Source/WebCore/platform/graphics/chromium/cc/CCMathUtil.h 2012-05-31 05:58:45 UTC (rev 119057)
+++ trunk/Source/WebCore/platform/graphics/chromium/cc/CCMathUtil.h 2012-05-31 06:05:30 UTC (rev 119058)
@@ -25,6 +25,8 @@
#ifndef CCMathUtil_h
#define CCMathUtil_h
+#include "FloatPoint.h"
+
namespace WebCore {
class IntRect;
@@ -33,6 +35,37 @@
class FloatQuad;
class TransformationMatrix;
+struct HomogeneousCoordinate {
+ HomogeneousCoordinate(double newX, double newY, double newZ, double newW)
+ : x(newX)
+ , y(newY)
+ , z(newZ)
+ , w(newW)
+ {
+ }
+
+ bool shouldBeClipped() const
+ {
+ return w <= 0;
+ }
+
+ FloatPoint cartesianPoint2d() const
+ {
+ if (w == 1)
+ return FloatPoint(x, y);
+
+ // For now, because this code is used privately only by CCMathUtil, it should never be called when w == 0, and we do not yet need to handle that case.
+ ASSERT(w);
+ double invW = 1.0 / w;
+ return FloatPoint(x * invW, y * invW);
+ }
+
+ double x;
+ double y;
+ double z;
+ double w;
+};
+
// This class contains math helper functionality that does not belong in WebCore.
// It is possible that this functionality should be migrated to WebCore eventually.
class CCMathUtil {
@@ -55,7 +88,9 @@
// numVerticesInClippedQuad may be zero, which means the entire quad was clipped, and
// none of the vertices in the array are valid.
static void mapClippedQuad(const TransformationMatrix&, const FloatQuad& srcQuad, FloatPoint clippedQuad[8], int& numVerticesInClippedQuad);
+
static FloatRect computeEnclosingRectOfVertices(FloatPoint vertices[], int numVertices);
+ static FloatRect computeEnclosingClippedRect(const HomogeneousCoordinate& h1, const HomogeneousCoordinate& h2, const HomogeneousCoordinate& h3, const HomogeneousCoordinate& h4);
// NOTE: These functions do not do correct clipping against w = 0 plane, but they
// correctly detect the clipped condition via the boolean clipped.
Modified: trunk/Source/WebKit/chromium/tests/CCMathUtilTest.cpp (119057 => 119058)
--- trunk/Source/WebKit/chromium/tests/CCMathUtilTest.cpp 2012-05-31 05:58:45 UTC (rev 119057)
+++ trunk/Source/WebKit/chromium/tests/CCMathUtilTest.cpp 2012-05-31 06:05:30 UTC (rev 119058)
@@ -26,6 +26,7 @@
#include "cc/CCMathUtil.h"
+#include "CCLayerTreeTestCommon.h"
#include "TransformationMatrix.h"
#include <gmock/gmock.h>
@@ -116,4 +117,38 @@
EXPECT_TRUE(projectedRect.isEmpty());
}
+TEST(CCMathUtilTest, verifyEnclosingClippedRectUsesCorrectInitialBounds)
+{
+ HomogeneousCoordinate h1(-100, -100, 0, 1);
+ HomogeneousCoordinate h2(-10, -10, 0, 1);
+ HomogeneousCoordinate h3(10, 10, 0, -1);
+ HomogeneousCoordinate h4(100, 100, 0, -1);
+
+ // The bounds of the enclosing clipped rect should be -100 to -10 for both x and y.
+ // However, if there is a bug where the initial xmin/xmax/ymin/ymax are initialized to
+ // numeric_limits<float>::min() (which is zero, not -flt_max) then the enclosing
+ // clipped rect will be computed incorrectly.
+ FloatRect result = CCMathUtil::computeEnclosingClippedRect(h1, h2, h3, h4);
+
+ EXPECT_FLOAT_RECT_EQ(FloatRect(FloatPoint(-100, -100), FloatSize(90, 90)), result);
+}
+
+TEST(CCMathUtilTest, verifyEnclosingRectOfVerticesUsesCorrectInitialBounds)
+{
+ FloatPoint vertices[3];
+ int numVertices = 3;
+
+ vertices[0] = FloatPoint(-10, -100);
+ vertices[1] = FloatPoint(-100, -10);
+ vertices[2] = FloatPoint(-30, -30);
+
+ // The bounds of the enclosing rect should be -100 to -10 for both x and y. However,
+ // if there is a bug where the initial xmin/xmax/ymin/ymax are initialized to
+ // numeric_limits<float>::min() (which is zero, not -flt_max) then the enclosing
+ // clipped rect will be computed incorrectly.
+ FloatRect result = CCMathUtil::computeEnclosingRectOfVertices(vertices, numVertices);
+
+ EXPECT_FLOAT_RECT_EQ(FloatRect(FloatPoint(-100, -100), FloatSize(90, 90)), result);
+}
+
} // namespace