Title: [119058] trunk/Source
Revision
119058
Author
[email protected]
Date
2012-05-30 23:05:30 -0700 (Wed, 30 May 2012)

Log Message

[chromium] Fix min/max bounds error in CCMathUtil.cpp
https://bugs.webkit.org/show_bug.cgi?id=87915

Reviewed by James Robinson.

Source/WebCore:

Two unit tests added to CCMathUtilTest:
    CCMathUtilTest.verifyEnclosingClippedRectUsesCorrectInitialBounds
    CCMathUtilTest.verifyEnclosingRectOfVerticesUsesCorrectInitialBounds

While computing bounds, the initial values for xmax and ymax are
intended to be set to -float_max. It turns out that
std::numeric_limits<float>::min() actually returns the smallest
positive value close to zero, which is not what was intended. This
patch fixes the code to use -float_max instead, which is the
intended value.

* platform/graphics/chromium/cc/CCMathUtil.cpp:
(WebCore::CCMathUtil::mapClippedRect):
(WebCore::CCMathUtil::projectClippedRect):
(WebCore::CCMathUtil::computeEnclosingRectOfVertices):
(WebCore::CCMathUtil::computeEnclosingClippedRect):
(WebCore):
* platform/graphics/chromium/cc/CCMathUtil.h:
(WebCore::HomogeneousCoordinate::HomogeneousCoordinate):
(HomogeneousCoordinate):
(WebCore::HomogeneousCoordinate::shouldBeClipped):
(WebCore::HomogeneousCoordinate::cartesianPoint2d):
(WebCore):
(CCMathUtil):

Source/WebKit/chromium:

* tests/CCMathUtilTest.cpp:
(WebCore::TEST):
(WebCore):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (119057 => 119058)


--- trunk/Source/WebCore/ChangeLog	2012-05-31 05:58:45 UTC (rev 119057)
+++ trunk/Source/WebCore/ChangeLog	2012-05-31 06:05:30 UTC (rev 119058)
@@ -1,3 +1,35 @@
+2012-05-30  Shawn Singh  <[email protected]>
+
+        [chromium] Fix min/max bounds error in CCMathUtil.cpp
+        https://bugs.webkit.org/show_bug.cgi?id=87915
+
+        Reviewed by James Robinson.
+
+        Two unit tests added to CCMathUtilTest:
+            CCMathUtilTest.verifyEnclosingClippedRectUsesCorrectInitialBounds
+            CCMathUtilTest.verifyEnclosingRectOfVerticesUsesCorrectInitialBounds
+
+        While computing bounds, the initial values for xmax and ymax are
+        intended to be set to -float_max. It turns out that
+        std::numeric_limits<float>::min() actually returns the smallest
+        positive value close to zero, which is not what was intended. This
+        patch fixes the code to use -float_max instead, which is the
+        intended value.
+
+        * platform/graphics/chromium/cc/CCMathUtil.cpp:
+        (WebCore::CCMathUtil::mapClippedRect):
+        (WebCore::CCMathUtil::projectClippedRect):
+        (WebCore::CCMathUtil::computeEnclosingRectOfVertices):
+        (WebCore::CCMathUtil::computeEnclosingClippedRect):
+        (WebCore):
+        * platform/graphics/chromium/cc/CCMathUtil.h:
+        (WebCore::HomogeneousCoordinate::HomogeneousCoordinate):
+        (HomogeneousCoordinate):
+        (WebCore::HomogeneousCoordinate::shouldBeClipped):
+        (WebCore::HomogeneousCoordinate::cartesianPoint2d):
+        (WebCore):
+        (CCMathUtil):
+
 2012-05-30  Patrick Gansterer  <[email protected]>
 
         Build fix for WinCE after r118568.

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/ChangeLog (119057 => 119058)


--- trunk/Source/WebKit/chromium/ChangeLog	2012-05-31 05:58:45 UTC (rev 119057)
+++ trunk/Source/WebKit/chromium/ChangeLog	2012-05-31 06:05:30 UTC (rev 119058)
@@ -1,3 +1,14 @@
+2012-05-30  Shawn Singh  <[email protected]>
+
+        [chromium] Fix min/max bounds error in CCMathUtil.cpp
+        https://bugs.webkit.org/show_bug.cgi?id=87915
+
+        Reviewed by James Robinson.
+
+        * tests/CCMathUtilTest.cpp:
+        (WebCore::TEST):
+        (WebCore):
+
 2012-05-30  Ami Fischman  <[email protected]>
 
         Roll chromium DEPS from r139300 to r139542.  Unreviewed.

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
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to