Diff
Modified: trunk/LayoutTests/ChangeLog (133489 => 133490)
--- trunk/LayoutTests/ChangeLog 2012-11-05 17:37:13 UTC (rev 133489)
+++ trunk/LayoutTests/ChangeLog 2012-11-05 17:53:01 UTC (rev 133490)
@@ -1,3 +1,18 @@
+2012-11-05 Hans Muller <[email protected]>
+
+ [CSS Exclusions] Polygon edges should span colinear vertices
+ https://bugs.webkit.org/show_bug.cgi?id=99343
+
+ Reviewed by Dirk Schulze.
+
+ Verify that exclusion polygonal shape-inside layout is unaffected by coincident
+ or collinear vertices.
+
+ * fast/exclusions/shape-inside/shape-inside-coincident-vertices-expected.html: Added.
+ * fast/exclusions/shape-inside/shape-inside-coincident-vertices.html: Added.
+ * fast/exclusions/shape-inside/shape-inside-collinear-vertices-expected.html: Added.
+ * fast/exclusions/shape-inside/shape-inside-collinear-vertices.html: Added.
+
2012-11-05 Csaba Osztrogonác <[email protected]>
[Qt] Unreviewed gardening, unskip now passing tests.
Added: trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-coincident-vertices-expected.html (0 => 133490)
--- trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-coincident-vertices-expected.html (rev 0)
+++ trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-coincident-vertices-expected.html 2012-11-05 17:53:01 UTC (rev 133490)
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+ if (window.internals)
+ window.internals.settings.setCSSExclusionsEnabled(true);
+</script>
+<style>
+ #shape-inside {
+ position: relative;
+ top: 50px;
+ left: 50px;
+ width: 250px;
+ height: 250px;
+ font: 50px/1 Ahem, sans-serif;
+ color: green;
+ }
+</style>
+</head>
+<body>
+ Requires Ahem font. Verifies that polygonal shapes with multiple coincident vertices produce
+ the same output as they would with only the unique vertices. This test should display two
+ indentical solid green squares.
+ <div id="shape-inside">XXXX XXXX XXXX XXXX</div>
+ <div id="shape-inside">XXXX XXXX XXXX XXXX</div>
+</body>
+</html>
Added: trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-coincident-vertices.html (0 => 133490)
--- trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-coincident-vertices.html (rev 0)
+++ trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-coincident-vertices.html 2012-11-05 17:53:01 UTC (rev 133490)
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+ if (window.internals)
+ window.internals.settings.setCSSExclusionsEnabled(true);
+</script>
+<style>
+ #shape-inside-coincident-vertices {
+ font: 50px/1 Ahem, sans-serif;
+ color: green;
+ width: 250px;
+ height: 250px;
+ -webkit-shape-inside: polygon(50px 50px, 50px 50px, 250px 50px, 250px 50px, 250px 250px, 50px 250px, 50px 50px, 50px 50px);
+ }
+ #shape-inside {
+ font: 50px/1 Ahem, sans-serif;
+ color: green;
+ width: 250px;
+ height: 250px;
+ -webkit-shape-inside: polygon(50px 50px, 250px 50px, 250px 250px, 50px 250px);
+ }
+</style>
+</head>
+<body>
+ Requires Ahem font. Verifies that polygonal shapes with multiple coincident vertices produce
+ the same output as they would with only the unique vertices. This test should display two
+ indentical solid green squares.
+ <div id="shape-inside-coincident-vertices">XXXX XXXX XXXX XXXX</div>
+ <div id="shape-inside">XXXX XXXX XXXX XXXX</div>
+</body>
+</html>
Added: trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-collinear-vertices-expected.html (0 => 133490)
--- trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-collinear-vertices-expected.html (rev 0)
+++ trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-collinear-vertices-expected.html 2012-11-05 17:53:01 UTC (rev 133490)
@@ -0,0 +1,27 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+ if (window.internals)
+ window.internals.settings.setCSSExclusionsEnabled(true);
+</script>
+<style>
+ #shape-inside {
+ position: relative;
+ top: 50px;
+ left: 50px;
+ width: 250px;
+ height: 250px;
+ font: 50px/1 Ahem, sans-serif;
+ color: green;
+ }
+</style>
+</head>
+<body>
+ Requires Ahem font. Verifies that polygonal shapes with multiple coincident vertices produce
+ the same output as they would with only the unique vertices. This test should display two
+ indentical solid green rectilinear triangles.
+ <div id="shape-inside">XXX<br/>XX<br/>X</div>
+ <div id="shape-inside">XXX<br/>XX<br/>X</div>
+</body>
+</html>
Added: trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-collinear-vertices.html (0 => 133490)
--- trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-collinear-vertices.html (rev 0)
+++ trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-collinear-vertices.html 2012-11-05 17:53:01 UTC (rev 133490)
@@ -0,0 +1,32 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+ if (window.internals)
+ window.internals.settings.setCSSExclusionsEnabled(true);
+</script>
+<style>
+ #shape-inside-collinear-vertices {
+ font: 50px/1 Ahem, sans-serif;
+ color: green;
+ width: 250px;
+ height: 250px;
+ -webkit-shape-inside: polygon(200px 100px, 150px 150px, 100px 200px, 50px 250px, 50px 50px, 60px 50px, 61px 50px, 250px 50px);
+ }
+ #shape-inside {
+ font: 50px/1 Ahem, sans-serif;
+ color: green;
+ width: 250px;
+ height: 250px;
+ -webkit-shape-inside: polygon(50px 50px, 250px 50px, 250px 50px, 50px 250px);
+ }
+</style>
+</head>
+<body>
+ Requires Ahem font. Verifies that polygonal shapes with multiple coincident vertices produce
+ the same output as they would with only the unique vertices. This test should display two
+ indentical solid green rectilinear triangles.
+ <div id="shape-inside-collinear-vertices">XXX XX X</div>
+ <div id="shape-inside">XXX XX X</div>
+</body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (133489 => 133490)
--- trunk/Source/WebCore/ChangeLog 2012-11-05 17:37:13 UTC (rev 133489)
+++ trunk/Source/WebCore/ChangeLog 2012-11-05 17:53:01 UTC (rev 133490)
@@ -1,3 +1,29 @@
+2012-11-05 Hans Muller <[email protected]>
+
+ [CSS Exclusions] Polygon edges should span colinear vertices
+ https://bugs.webkit.org/show_bug.cgi?id=99343
+
+ Reviewed by Dirk Schulze.
+
+ ExclusionPolygonEdges now span coincident and collinear vertices. Currently
+ pairs of vertices are only considered coincident if their coordinates are exactly
+ equal. Similarly, a vertex is only considered collinear with an edge if the area
+ of the triangle defined by the three vertices is exactly zero. In the future it
+ may be useful to relax the comparison with zero.
+
+ Tests: fast/exclusions/shape-inside/shape-inside-coincident-vertices.html
+ fast/exclusions/shape-inside/shape-inside-collinear-vertices.html
+
+ * rendering/ExclusionPolygon.cpp:
+ (WebCore::determinant): Used to measure collinearity.
+ (WebCore):
+ (WebCore::areCollinearPoints): True if three FloatPoint arguments are collinear per the test outlined above.
+ (WebCore::areCoincidentPoints): True if the two FloatPoint arguments are equal.
+ (WebCore::nextVertexIndex): The next vertex index in clockwise or counterclockwise order.
+ (WebCore::ExclusionPolygon::findNextEdgeVertexIndex): Return the index of the next non-coincident, non-collinear vertex.
+ (WebCore::ExclusionPolygon::ExclusionPolygon): Skip coincident and collinear vertices when building the list of edges.
+ * rendering/ExclusionPolygon.h: Added private findNextEdgeVertexIndex() declaration.
+
2012-11-05 Christophe Dumez <[email protected]>
[EFL] Use POSIX implementation of SharedBuffer::createWithContentsOfFile()
Modified: trunk/Source/WebCore/rendering/ExclusionPolygon.cpp (133489 => 133490)
--- trunk/Source/WebCore/rendering/ExclusionPolygon.cpp 2012-11-05 17:37:13 UTC (rev 133489)
+++ trunk/Source/WebCore/rendering/ExclusionPolygon.cpp 2012-11-05 17:53:01 UTC (rev 133490)
@@ -47,6 +47,45 @@
EdgeIntersectionType type;
};
+static inline float determinant(const FloatSize& a, const FloatSize& b)
+{
+ return a.width() * b.height() - a.height() * b.width();
+}
+
+static inline bool areCollinearPoints(const FloatPoint& p0, const FloatPoint& p1, const FloatPoint& p2)
+{
+ return !determinant(p1 - p0, p2 - p0);
+}
+
+static inline bool areCoincidentPoints(const FloatPoint& p0, const FloatPoint& p1)
+{
+ return p0.x() == p1.x() && p0.y() == p1.y();
+}
+
+static inline unsigned nextVertexIndex(unsigned vertexIndex, unsigned nVertices, bool clockwise)
+{
+ return ((clockwise) ? vertexIndex + 1 : vertexIndex - 1 + nVertices) % nVertices;
+}
+
+unsigned ExclusionPolygon::findNextEdgeVertexIndex(unsigned vertexIndex1, bool clockwise) const
+{
+ unsigned nVertices = numberOfVertices();
+ unsigned vertexIndex2 = nextVertexIndex(vertexIndex1, nVertices, clockwise);
+ unsigned lastVertexIndex = (clockwise) ? 0 : nVertices - 1;
+
+ while (vertexIndex2 != lastVertexIndex && areCoincidentPoints(vertexAt(vertexIndex1), vertexAt(vertexIndex2)))
+ vertexIndex2 = nextVertexIndex(vertexIndex2, nVertices, clockwise);
+
+ while (vertexIndex2 != lastVertexIndex) {
+ unsigned vertexIndex3 = nextVertexIndex(vertexIndex2, nVertices, clockwise);
+ if (!areCollinearPoints(vertexAt(vertexIndex1), vertexAt(vertexIndex2), vertexAt(vertexIndex3)))
+ break;
+ vertexIndex2 = vertexIndex3;
+ }
+
+ return vertexIndex2;
+}
+
ExclusionPolygon::ExclusionPolygon(PassOwnPtr<Vector<FloatPoint> > vertices, WindRule fillRule)
: ExclusionShape()
, m_vertices(vertices)
@@ -59,19 +98,42 @@
if (nVertices)
m_boundingBox.setLocation(vertexAt(0));
- for (unsigned i = 0; i < nVertices; i++) {
- const FloatPoint& vertex = vertexAt(i);
- m_boundingBox.extend(vertex);
- m_edges[i].polygon = this;
- m_edges[i].vertexIndex1 = i;
- m_edges[i].vertexIndex2 = (i + 1) % nVertices;
- m_edges[i].edgeIndex = i;
+ if (m_empty)
+ return;
+
+ unsigned edgeIndex = 0;
+ unsigned vertexIndex1 = 0;
+ do {
+ m_boundingBox.extend(vertexAt(vertexIndex1));
+ unsigned vertexIndex2 = findNextEdgeVertexIndex(vertexIndex1, true);
+ m_edges[edgeIndex].polygon = this;
+ m_edges[edgeIndex].vertexIndex1 = vertexIndex1;
+ m_edges[edgeIndex].vertexIndex2 = vertexIndex2;
+ m_edges[edgeIndex].edgeIndex = edgeIndex;
+ edgeIndex++;
+ vertexIndex1 = vertexIndex2;
+ } while (vertexIndex1);
+
+ if (edgeIndex > 3) {
+ const ExclusionPolygonEdge& firstEdge = m_edges[0];
+ const ExclusionPolygonEdge& lastEdge = m_edges[edgeIndex - 1];
+ if (areCollinearPoints(lastEdge.vertex1(), lastEdge.vertex2(), firstEdge.vertex2())) {
+ m_edges[0].vertexIndex1 = lastEdge.vertexIndex1;
+ edgeIndex--;
+ }
}
+ m_edges.resize(edgeIndex);
+ m_empty = m_edges.size() < 3;
+
+ if (m_empty)
+ return;
+
for (unsigned i = 0; i < m_edges.size(); i++) {
ExclusionPolygonEdge* edge = &m_edges[i];
m_edgeTree.add(EdgeInterval(edge->minY(), edge->maxY(), edge));
}
+
}
static bool computeXIntersection(const ExclusionPolygonEdge* edgePointer, float y, EdgeIntersection& result)
Modified: trunk/Source/WebCore/rendering/ExclusionPolygon.h (133489 => 133490)
--- trunk/Source/WebCore/rendering/ExclusionPolygon.h 2012-11-05 17:37:13 UTC (rev 133489)
+++ trunk/Source/WebCore/rendering/ExclusionPolygon.h 2012-11-05 17:53:01 UTC (rev 133490)
@@ -70,6 +70,7 @@
private:
void computeXIntersections(float y, Vector<ExclusionInterval>&) const;
void computeEdgeIntersections(float minY, float maxY, Vector<ExclusionInterval>&) const;
+ unsigned findNextEdgeVertexIndex(unsigned vertexIndex1, bool clockwise) const;
typedef PODInterval<float, ExclusionPolygonEdge*> EdgeInterval;
typedef PODIntervalTree<float, ExclusionPolygonEdge*> EdgeIntervalTree;