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