Title: [132971] trunk
Revision
132971
Author
[email protected]
Date
2012-10-30 18:37:51 -0700 (Tue, 30 Oct 2012)

Log Message

[CSS Exclusions] Multiple segment polygon layout does not get all segments
https://bugs.webkit.org/show_bug.cgi?id=100039

Patch by Hans Muller <[email protected]> on 2012-10-30
Reviewed by Dirk Schulze.

Source/WebCore:

Corrected the algorithm for computing included polygon intervals for rectilinear polygons,
and polygons with horizontal edges in general.

Tests: fast/exclusions/shape-inside/shape-inside-rectilinear-polygon-001.html
       fast/exclusions/shape-inside/shape-inside-rectilinear-polygon-002.html

* rendering/ExclusionPolygon.cpp: Removed some internal dead code related to the no-longer-used sortedEdgesMinY Vector.
(WebCore::ExclusionPolygon::ExclusionPolygon): Initialize new ExclusionPolygonEdge edgeIndex field.
(WebCore::getVertexIntersectionVertices): Return the previous, next, and target vertex indices for a vertex intersection.
(WebCore::ExclusionPolygon::computeXIntersections): Refactored the core of this method to improve handling of horizontal edges.
(WebCore::ExclusionPolygon::computeEdgeIntersections): Ignore zero-width edges.
* rendering/ExclusionPolygon.h: Removed the rightVertexY() method, since it's no longer used.
(WebCore::ExclusionPolygon::edgeAt): New method.
(WebCore::ExclusionPolygon::numberOfEdges): New method.
(ExclusionPolygon): Added support for retrieving edges.
(WebCore::ExclusionPolygonEdge::vertex1): Use vertex1Index.
(WebCore::ExclusionPolygonEdge::vertex2): Use vertex2Index.
(ExclusionPolygonEdge): Renamed index1, index2 fields to vertex1Index, vertex2Index.
(WebCore::ExclusionPolygonEdge::previousEdge): New method.
(WebCore::ExclusionPolygonEdge::nextEdge): New method.

LayoutTests:

Added tests for CSS Exclusion shape-inside polygons with horizontal edges.
Corrected the simple-polygon.js code for computing a polygon's included intervals.

* fast/exclusions/resources/simple-polygon.js:
* fast/exclusions/shape-inside/shape-inside-rectilinear-polygon-001-expected.html: Added.
* fast/exclusions/shape-inside/shape-inside-rectilinear-polygon-001.html: Added.
* fast/exclusions/shape-inside/shape-inside-rectilinear-polygon-002-expected.html: Added.
* fast/exclusions/shape-inside/shape-inside-rectilinear-polygon-002.html: Added.
* fast/exclusions/shape-inside/shape-inside-simple-polygon-004-expected.html:
* fast/exclusions/shape-inside/shape-inside-simple-polygon-004.html:

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (132970 => 132971)


--- trunk/LayoutTests/ChangeLog	2012-10-31 01:10:11 UTC (rev 132970)
+++ trunk/LayoutTests/ChangeLog	2012-10-31 01:37:51 UTC (rev 132971)
@@ -1,3 +1,21 @@
+2012-10-30  Hans Muller  <[email protected]>
+
+        [CSS Exclusions] Multiple segment polygon layout does not get all segments
+        https://bugs.webkit.org/show_bug.cgi?id=100039
+
+        Reviewed by Dirk Schulze.
+
+        Added tests for CSS Exclusion shape-inside polygons with horizontal edges.
+        Corrected the simple-polygon.js code for computing a polygon's included intervals.
+
+        * fast/exclusions/resources/simple-polygon.js:
+        * fast/exclusions/shape-inside/shape-inside-rectilinear-polygon-001-expected.html: Added.
+        * fast/exclusions/shape-inside/shape-inside-rectilinear-polygon-001.html: Added.
+        * fast/exclusions/shape-inside/shape-inside-rectilinear-polygon-002-expected.html: Added.
+        * fast/exclusions/shape-inside/shape-inside-rectilinear-polygon-002.html: Added.
+        * fast/exclusions/shape-inside/shape-inside-simple-polygon-004-expected.html:
+        * fast/exclusions/shape-inside/shape-inside-simple-polygon-004.html:
+
 2012-10-30  Kenichi Ishibashi  <[email protected]>
 
         local(Helvetica) in src descriptor prevent fallback

Modified: trunk/LayoutTests/fast/exclusions/resources/simple-polygon.js (132970 => 132971)


--- trunk/LayoutTests/fast/exclusions/resources/simple-polygon.js	2012-10-31 01:10:11 UTC (rev 132970)
+++ trunk/LayoutTests/fast/exclusions/resources/simple-polygon.js	2012-10-31 01:37:51 UTC (rev 132971)
@@ -38,49 +38,60 @@
 }
 
 // Return two X intercepts of the horizontal line at y. We're assuming that the polygon
-// 0 or 2 intercepts for all y.Of course this isn't true for polygons in general,
+// has 0 or 2 intercepts for all y. Of course this isn't true for polygons in general,
 // just the ones used by the test cases supported by this file.
 
 function polygonXIntercepts(polygon, y) {
     var vertices = polygon.vertices;
-    var vertex = null;  // first intersecting non-horizontal edge vertex, vertex.y == y
-    var xIntercepts = [];
+    var foundXIntercept = false;
+    var interceptsMinX, interceptsMaxX;
 
-    for(var i = 0; i < vertices.length && xIntercepts.length < 2; i++) {
+    for(var i = 0; i < vertices.length; i++) {
         var v1 = vertices[i];
         var v2 = vertices[(i + 1) % vertices.length];
 
-        if (vertex == v1 || vertex == v2)
+        if (Math.max(v1.y, v2.y) < y || Math.min(v1.y, v2.y) > y)
             continue;
 
-        var minY = Math.min(v1.y, v2.y);
-        var maxY = Math.max(v1.y, v2.y);
+        if (v1.y == y && v2.y == y) {  // horizontal edge 
+            if (y != polygon.maxY)
+                continue;
 
-        if (maxY < y || minY > y)
-            continue;
+            if (!foundXIntercept) {
+                interceptsMinX = Math.min(v1.x, v2.x);
+                interceptsMaxX = Math.max(v1.x, v2.x);
+                foundXIntercept = true;
+            }
+            else {
+                interceptsMinX = Math.min(v1.x, v2.x, interceptsMinX);
+                interceptsMaxX = Math.max(v1.x, v2.x, interceptsMaxX);
+            }
+        }
+        else {
+            var interceptX;
 
-        if (minY == maxY)
-            return [v1.x, v2.x];
+            if (v1.y == y) 
+                interceptX = v1.x;
+            else if (v2.y == y) 
+                interceptX = v2.x;
+            else
+                interceptX = ((y - v1.y) * (v2.x - v1.x) / (v2.y - v1.y)) + v1.x;
 
-        if (v1.y == y) {
-            xIntercepts.push(v1.x);
-            if (!vertex)
-                vertex = v1;
+            if (!foundXIntercept) {
+                interceptsMinX = interceptsMaxX = interceptX;
+                foundXIntercept = true;
+            }
+            else {
+                interceptsMinX = Math.min(interceptX, interceptsMinX);
+                interceptsMaxX = Math.max(interceptX, interceptsMaxX);
+            }
         }
-        else if (v2.y == y) {
-            xIntercepts.push(v2.x);
-            if (!vertex)
-                vertex = v2;
-        }
-        else {
-            xIntercepts.push( ((y - v1.y) * (v2.x - v1.x) / (v2.y - v1.y)) + v1.x );
-        }
     }
 
-    if (xIntercepts.length != 2)
+    if (!foundXIntercept)
         return [];
 
-    return [subpixelRound(Math.min.apply(null, xIntercepts)), Math.floor(Math.max.apply(null, xIntercepts))];
+    return [subpixelRound(interceptsMinX), Math.floor(interceptsMaxX)];
 }
 
 function polygonLineIntercepts(polygon, y, lineHeight) {

Added: trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-rectilinear-polygon-001-expected.html (0 => 132971)


--- trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-rectilinear-polygon-001-expected.html	                        (rev 0)
+++ trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-rectilinear-polygon-001-expected.html	2012-10-31 01:37:51 UTC (rev 132971)
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+<script>
+    if (window.internals)
+        window.internals.settings.setCSSExclusionsEnabled(true);
+
+    // Rectilinear polygon with this shape:
+    //   XXX
+    // XXXXXXX
+    // XXXXXXX
+
+    var vertices = [{x:0, y:50}, {x:100, y:50}, {x:100, y:0}, {x:250, y:0}, {x:250, y:50}, {x:350, y:50}, {x:350, y:150}, {x:0, y:150}];
+    var lineHeight = 50;
+    var hasSubpixelSupport = false;  // Test results do not depend on subpixel layout.
+</script>
+
+<style id="stylesheet">
+    #polygon-shape-inside, #polygon-svg-shape {
+        position: absolute;
+        left: 0px;
+        top: 0px;
+    }
+</style>
+</head>
+
+<body _onload_="createPolygonShapeInsideTestCaseExpected()">
+  <svg id="polygon-svg-shape" xmlns="http://www.w3.org/2000/svg"></svg>
+  <div id="polygon-shape-inside"></div>
+  <p id="informative-text">
+      This test requires the Ahem font. It creates a rectilinear polygonal shape-inside and a
+      matching filled SVG polygon. The content should just fill the shape with alternating
+      black and empty rectangles on each line.</p>
+</body>
+
+</html>

Added: trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-rectilinear-polygon-001.html (0 => 132971)


--- trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-rectilinear-polygon-001.html	                        (rev 0)
+++ trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-rectilinear-polygon-001.html	2012-10-31 01:37:51 UTC (rev 132971)
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+<script>
+    if (window.internals)
+        window.internals.settings.setCSSExclusionsEnabled(true);
+
+    // Rectilinear polygon with this shape:
+    //   XXX
+    // XXXXXXX
+    // XXXXXXX
+
+    var vertices = [{x:0, y:50}, {x:100, y:50}, {x:100, y:0}, {x:250, y:0}, {x:250, y:50}, {x:350, y:50}, {x:350, y:150}, {x:0, y:150}];
+    var lineHeight = 50;
+    var hasSubpixelSupport = false;  // Test results do not depend on subpixel layout.
+</script>
+
+<style id="stylesheet">
+    #polygon-shape-inside, #polygon-svg-shape {
+        position: absolute;
+        left: 0px;
+        top: 0px;
+    }
+</style>
+</head>
+
+<body _onload_="createPolygonShapeInsideTestCase();">
+  <svg id="polygon-svg-shape" xmlns="http://www.w3.org/2000/svg"></svg>
+  <div id="polygon-shape-inside"></div>
+  <p id="informative-text">
+      This test requires the Ahem font. It creates a rectilinear polygonal shape-inside and a
+      matching filled SVG polygon. The content should just fill the shape with alternating
+      black and empty rectangles on each line.</p>
+</body>
+
+</html>

Added: trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-rectilinear-polygon-002-expected.html (0 => 132971)


--- trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-rectilinear-polygon-002-expected.html	                        (rev 0)
+++ trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-rectilinear-polygon-002-expected.html	2012-10-31 01:37:51 UTC (rev 132971)
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+<script>
+    if (window.internals)
+        window.internals.settings.setCSSExclusionsEnabled(true);
+
+    // Rectilinear polygon with this shape:
+    //   XXX
+    // XXXXXXX
+    // XXXXXXX
+    //   XXX
+
+    var vertices = [{x:0, y:50}, {x:100, y:50}, {x:100, y:0}, {x:250, y:0}, {x:250, y:50}, {x:350, y:50}, {x:350, y:150}, {x:250, y:150}, {x:250, y:200}, {x:100, y:200}, {x:100, y:150}, {x:0, y:150}];
+    var lineHeight = 50;
+    var hasSubpixelSupport = false;  // Test results do not depend on subpixel layout.
+</script>
+
+<style id="stylesheet">
+    #polygon-shape-inside, #polygon-svg-shape {
+        position: absolute;
+        left: 0px;
+        top: 0px;
+    }
+</style>
+</head>
+
+<body _onload_="createPolygonShapeInsideTestCaseExpected();">
+  <svg id="polygon-svg-shape" xmlns="http://www.w3.org/2000/svg"></svg>
+  <div id="polygon-shape-inside"></div>
+  <p id="informative-text">
+      This test requires the Ahem font. It creates a rectilinear polygonal shape-inside and a
+      matching filled SVG polygon. The content should just fill the shape with alternating
+      black and empty rectangles on each line.</p>
+</body>
+
+</html>

Added: trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-rectilinear-polygon-002.html (0 => 132971)


--- trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-rectilinear-polygon-002.html	                        (rev 0)
+++ trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-rectilinear-polygon-002.html	2012-10-31 01:37:51 UTC (rev 132971)
@@ -0,0 +1,37 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script src=""
+<script>
+    if (window.internals)
+        window.internals.settings.setCSSExclusionsEnabled(true);
+
+    // Rectilinear polygon with this shape:
+    //   XXX
+    // XXXXXXX
+    // XXXXXXX
+    //   XXX
+    var vertices = [{x:0, y:50}, {x:100, y:50}, {x:100, y:0}, {x:250, y:0}, {x:250, y:50}, {x:350, y:50}, {x:350, y:150}, {x:250, y:150}, {x:250, y:200}, {x:100, y:200}, {x:100, y:150}, {x:0, y:150}];
+    var lineHeight = 50;
+    var hasSubpixelSupport = false;  // Test results do not depend on subpixel layout.
+</script>
+
+<style id="stylesheet">
+    #polygon-shape-inside, #polygon-svg-shape {
+        position: absolute;
+        left: 0px;
+        top: 0px;
+    }
+</style>
+</head>
+
+<body _onload_="createPolygonShapeInsideTestCase();">
+  <svg id="polygon-svg-shape" xmlns="http://www.w3.org/2000/svg"></svg>
+  <div id="polygon-shape-inside"></div>
+  <p id="informative-text">
+      This test requires the Ahem font. It creates a rectilinear polygonal shape-inside and a
+      matching filled SVG polygon. The content should just fill the shape with alternating
+      black and empty rectangles on each line.</p>
+</body>
+
+</html>

Modified: trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-simple-polygon-004-expected.html (132970 => 132971)


--- trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-simple-polygon-004-expected.html	2012-10-31 01:10:11 UTC (rev 132970)
+++ trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-simple-polygon-004-expected.html	2012-10-31 01:37:51 UTC (rev 132971)
@@ -8,7 +8,7 @@
 
     // Concave assymetric simple polygon with horizontal top and bottom edges.  A version of the 001
     // hourglass shape with vertical edges in the center.
-    var vertices = [{x:40, y:40}, {x:440, y:40}, {x:320, y:160}, {x:320, y:240}, {x:480, y:400}, {x:80, y:400}, {x:200, y:280}, {x:200, y:200}]};
+    var vertices = [{x:40, y:40}, {x:440, y:40}, {x:320, y:160}, {x:320, y:240}, {x:480, y:400}, {x:80, y:400}, {x:200, y:280}, {x:200, y:200}];
     var lineHeight = 40;
     var hasSubpixelSupport;
 

Modified: trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-simple-polygon-004.html (132970 => 132971)


--- trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-simple-polygon-004.html	2012-10-31 01:10:11 UTC (rev 132970)
+++ trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-simple-polygon-004.html	2012-10-31 01:37:51 UTC (rev 132971)
@@ -8,7 +8,7 @@
 
     // Concave assymetric simple polygon with horizontal top and bottom edges.  A version of the 001
     // hourglass shape with vertical edges in the center.
-    var vertices = [{x:40, y:40}, {x:440, y:40}, {x:320, y:160}, {x:320, y:240}, {x:480, y:400}, {x:80, y:400}, {x:200, y:280}, {x:200, y:200}]};
+    var vertices = [{x:40, y:40}, {x:440, y:40}, {x:320, y:160}, {x:320, y:240}, {x:480, y:400}, {x:80, y:400}, {x:200, y:280}, {x:200, y:200}];
     var lineHeight = 40;
     var hasSubpixelSupport;
 

Modified: trunk/Source/WebCore/ChangeLog (132970 => 132971)


--- trunk/Source/WebCore/ChangeLog	2012-10-31 01:10:11 UTC (rev 132970)
+++ trunk/Source/WebCore/ChangeLog	2012-10-31 01:37:51 UTC (rev 132971)
@@ -1,3 +1,31 @@
+2012-10-30  Hans Muller  <[email protected]>
+
+        [CSS Exclusions] Multiple segment polygon layout does not get all segments
+        https://bugs.webkit.org/show_bug.cgi?id=100039
+
+        Reviewed by Dirk Schulze.
+
+        Corrected the algorithm for computing included polygon intervals for rectilinear polygons,
+        and polygons with horizontal edges in general.
+
+        Tests: fast/exclusions/shape-inside/shape-inside-rectilinear-polygon-001.html
+               fast/exclusions/shape-inside/shape-inside-rectilinear-polygon-002.html
+
+        * rendering/ExclusionPolygon.cpp: Removed some internal dead code related to the no-longer-used sortedEdgesMinY Vector.
+        (WebCore::ExclusionPolygon::ExclusionPolygon): Initialize new ExclusionPolygonEdge edgeIndex field.
+        (WebCore::getVertexIntersectionVertices): Return the previous, next, and target vertex indices for a vertex intersection.
+        (WebCore::ExclusionPolygon::computeXIntersections): Refactored the core of this method to improve handling of horizontal edges.
+        (WebCore::ExclusionPolygon::computeEdgeIntersections): Ignore zero-width edges.
+        * rendering/ExclusionPolygon.h: Removed the rightVertexY() method, since it's no longer used.
+        (WebCore::ExclusionPolygon::edgeAt): New method.
+        (WebCore::ExclusionPolygon::numberOfEdges): New method.
+        (ExclusionPolygon): Added support for retrieving edges.
+        (WebCore::ExclusionPolygonEdge::vertex1): Use vertex1Index.
+        (WebCore::ExclusionPolygonEdge::vertex2): Use vertex2Index.
+        (ExclusionPolygonEdge): Renamed index1, index2 fields to vertex1Index, vertex2Index.
+        (WebCore::ExclusionPolygonEdge::previousEdge): New method.
+        (WebCore::ExclusionPolygonEdge::nextEdge): New method.
+
 2012-10-30  Chris Evans  <[email protected]>
 
         Improve performance of MaskPtr.

Modified: trunk/Source/WebCore/rendering/ExclusionPolygon.cpp (132970 => 132971)


--- trunk/Source/WebCore/rendering/ExclusionPolygon.cpp	2012-10-31 01:10:11 UTC (rev 132970)
+++ trunk/Source/WebCore/rendering/ExclusionPolygon.cpp	2012-10-31 01:37:51 UTC (rev 132971)
@@ -47,11 +47,6 @@
     EdgeIntersectionType type;
 };
 
-static bool compareEdgeMinY(const ExclusionPolygonEdge* e1, const ExclusionPolygonEdge* e2)
-{
-    return e1->minY() < e2->minY();
-}
-
 ExclusionPolygon::ExclusionPolygon(PassOwnPtr<Vector<FloatPoint> > vertices, WindRule fillRule)
     : ExclusionShape()
     , m_vertices(vertices)
@@ -60,7 +55,6 @@
     unsigned nVertices = numberOfVertices();
     m_edges.resize(nVertices);
     m_empty = nVertices < 3;
-    Vector<ExclusionPolygonEdge*> sortedEdgesMinY(nVertices);
 
     if (nVertices)
         m_boundingBox.setLocation(vertexAt(0));
@@ -69,14 +63,11 @@
         const FloatPoint& vertex = vertexAt(i);
         m_boundingBox.extend(vertex);
         m_edges[i].polygon = this;
-        m_edges[i].index1 = i;
-        m_edges[i].index2 = (i + 1) % nVertices;
-
-        sortedEdgesMinY[i] = &m_edges[i];
+        m_edges[i].vertexIndex1 = i;
+        m_edges[i].vertexIndex2 = (i + 1) % nVertices;
+        m_edges[i].edgeIndex = i;
     }
 
-    std::sort(sortedEdgesMinY.begin(), sortedEdgesMinY.end(), WebCore::compareEdgeMinY);
-
     for (unsigned i = 0; i < m_edges.size(); i++) {
         ExclusionPolygonEdge* edge = &m_edges[i];
         m_edgeTree.add(EdgeInterval(edge->minY(), edge->maxY(), edge));
@@ -118,15 +109,27 @@
     return true;
 }
 
-float ExclusionPolygon::rightVertexY(unsigned index) const
+static inline bool getVertexIntersectionVertices(const EdgeIntersection& intersection, FloatPoint& prevVertex, FloatPoint& thisVertex, FloatPoint& nextVertex)
 {
-    unsigned nVertices = numberOfVertices();
-    const FloatPoint& vertex1 = vertexAt((index + 1) % nVertices);
-    const FloatPoint& vertex2 = vertexAt((index - 1) % nVertices);
+    if (intersection.type != VertexMinY && intersection.type != VertexMaxY)
+        return false;
 
-    if (vertex1.x() == vertex2.x())
-        return vertex1.y() > vertex2.y() ? vertex1.y() : vertex2.y();
-    return vertex1.x() > vertex2.x() ? vertex1.y() : vertex2.y();
+    ASSERT(intersection.edge && intersection.edge->polygon);
+    const ExclusionPolygon& polygon = *(intersection.edge->polygon);
+    const ExclusionPolygonEdge& thisEdge = *(intersection.edge);
+
+    if ((intersection.type == VertexMinY && (thisEdge.vertex1().y() < thisEdge.vertex2().y()))
+        || (intersection.type == VertexMaxY && (thisEdge.vertex1().y() > thisEdge.vertex2().y()))) {
+        prevVertex = polygon.vertexAt(thisEdge.previousEdge().vertexIndex2);
+        thisVertex = polygon.vertexAt(thisEdge.vertexIndex1);
+        nextVertex = polygon.vertexAt(thisEdge.vertexIndex2);
+    } else {
+        prevVertex = polygon.vertexAt(thisEdge.vertexIndex1);
+        thisVertex = polygon.vertexAt(thisEdge.vertexIndex2);
+        nextVertex = polygon.vertexAt(thisEdge.nextEdge().vertexIndex1);
+    }
+
+    return true;
 }
 
 static bool appendIntervalX(float x, bool inside, Vector<ExclusionInterval>& result)
@@ -155,7 +158,7 @@
     EdgeIntersection intersection;
     for (unsigned i = 0; i < overlappingEdges.size(); i++) {
         ExclusionPolygonEdge* edge = static_cast<ExclusionPolygonEdge*>(overlappingEdges[i].data());
-        if (computeXIntersection(edge, y, intersection))
+        if (computeXIntersection(edge, y, intersection) && intersection.type != VertexYBoth)
             intersections.append(intersection);
     }
     if (intersections.size() < 2)
@@ -169,7 +172,6 @@
 
     while (index < intersections.size()) {
         const EdgeIntersection& thisIntersection = intersections[index];
-
         if (index + 1 < intersections.size()) {
             const EdgeIntersection& nextIntersection = intersections[index + 1];
             if ((thisIntersection.point.x() == nextIntersection.point.x()) && (thisIntersection.type == VertexMinY || thisIntersection.type == VertexMaxY)) {
@@ -177,9 +179,7 @@
                     // Skip pairs of intersections whose types are VertexMaxY,VertexMaxY and VertexMinY,VertexMinY.
                     index += 2;
                 } else {
-                    // Replace pairs of intersections whose types are VertexMinY,VertexMaxY or VertexMaxY,VertexMinY with one VertexMinY intersection.
-                    if (nextIntersection.type == VertexMaxY)
-                        intersections[index + 1] = thisIntersection;
+                    // Replace pairs of intersections whose types are VertexMinY,VertexMaxY or VertexMaxY,VertexMinY with one intersection.
                     index++;
                 }
                 continue;
@@ -187,22 +187,32 @@
         }
 
         const ExclusionPolygonEdge& thisEdge = *thisIntersection.edge;
-        bool crossing = !windCount;
+        bool evenOddCrossing = !windCount;
 
         if (fillRule() == RULE_EVENODD) {
             windCount += (thisEdge.vertex2().y() > thisEdge.vertex1().y()) ? 1 : -1;
-            crossing = crossing || !windCount;
+            evenOddCrossing = evenOddCrossing || !windCount;
         }
 
-        if ((thisIntersection.type == Normal) || (thisIntersection.type == VertexMinY)) {
-            if (crossing)
+        if (evenOddCrossing) {
+            bool edgeCrossing = false;
+            if (thisIntersection.type == Normal || !inside || index == intersections.size() - 1)
+                edgeCrossing = true;
+            else {
+                FloatPoint prevVertex;
+                FloatPoint thisVertex;
+                FloatPoint nextVertex;
+
+                if (getVertexIntersectionVertices(thisIntersection, prevVertex, thisVertex, nextVertex)) {
+                    if (prevVertex.y() == y)
+                        edgeCrossing =  (thisVertex.x() > prevVertex.x()) ? nextVertex.y() > y : nextVertex.y() < y;
+                    else
+                        edgeCrossing = (nextVertex.y() != y);
+                }
+            }
+            if (edgeCrossing)
                 inside = appendIntervalX(thisIntersection.point.x(), inside, result);
-        } else if (thisIntersection.type == VertexMaxY) {
-            int vertexIndex = (thisEdge.vertex2().y() > thisEdge.vertex1().y()) ? thisEdge.index2 : thisEdge.index1;
-            if (crossing && rightVertexY(vertexIndex) > y)
-                inside = appendIntervalX(thisEdge.maxX(), inside, result);
-        } else if (thisIntersection.type == VertexYBoth)
-            result.append(ExclusionInterval(thisEdge.minX(), thisEdge.maxX()));
+        }
 
         index++;
     }
@@ -235,7 +245,8 @@
         if (x1 > x2)
             std::swap(x1, x2);
 
-        result.append(ExclusionInterval(x1, x2));
+        if (x2 > x1)
+            result.append(ExclusionInterval(x1, x2));
     }
 
     sortExclusionIntervals(result);

Modified: trunk/Source/WebCore/rendering/ExclusionPolygon.h (132970 => 132971)


--- trunk/Source/WebCore/rendering/ExclusionPolygon.h	2012-10-31 01:10:11 UTC (rev 132970)
+++ trunk/Source/WebCore/rendering/ExclusionPolygon.h	2012-10-31 01:37:51 UTC (rev 132971)
@@ -59,13 +59,15 @@
     unsigned numberOfVertices() const { return m_vertices->size(); }
     WindRule fillRule() const { return m_fillRule; }
 
+    const ExclusionPolygonEdge& edgeAt(unsigned index) const { return m_edges[index]; }
+    unsigned numberOfEdges() const { return m_edges.size(); }
+
     virtual FloatRect shapeLogicalBoundingBox() const OVERRIDE { return internalToLogicalBoundingBox(m_boundingBox); }
     virtual bool isEmpty() const OVERRIDE { return m_empty; }
     virtual void getExcludedIntervals(float logicalTop, float logicalHeight, SegmentList&) const OVERRIDE;
     virtual void getIncludedIntervals(float logicalTop, float logicalHeight, SegmentList&) const OVERRIDE;
 
 private:
-    float rightVertexY(unsigned) const;
     void computeXIntersections(float y, Vector<ExclusionInterval>&) const;
     void computeEdgeIntersections(float minY, float maxY, Vector<ExclusionInterval>&) const;
 
@@ -87,23 +89,36 @@
     const FloatPoint& vertex1() const
     {
         ASSERT(polygon);
-        return polygon->vertexAt(index1);
+        return polygon->vertexAt(vertexIndex1);
     }
 
     const FloatPoint& vertex2() const
     {
         ASSERT(polygon);
-        return polygon->vertexAt(index2);
+        return polygon->vertexAt(vertexIndex2);
     }
 
+    const ExclusionPolygonEdge& previousEdge() const
+    {
+        ASSERT(polygon && polygon->numberOfEdges() > 1);
+        return polygon->edgeAt((edgeIndex + polygon->numberOfEdges() - 2) % polygon->numberOfEdges());
+    }
+
+    const ExclusionPolygonEdge& nextEdge() const
+    {
+        ASSERT(polygon && polygon->numberOfEdges() > 1);
+        return polygon->edgeAt((edgeIndex + 1) % polygon->numberOfEdges());
+    }
+
     float minX() const { return std::min(vertex1().x(), vertex2().x()); }
     float minY() const { return std::min(vertex1().y(), vertex2().y()); }
     float maxX() const { return std::max(vertex1().x(), vertex2().x()); }
     float maxY() const { return std::max(vertex1().y(), vertex2().y()); }
 
     const ExclusionPolygon* polygon;
-    unsigned index1;
-    unsigned index2;
+    unsigned vertexIndex1;
+    unsigned vertexIndex2;
+    unsigned edgeIndex;
 };
 
 // These structures are used by PODIntervalTree for debugging.1
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to