Changeset 132971 in webkit
- Timestamp:
- Oct 30, 2012 6:37:51 PM (11 years ago)
- Location:
- trunk
- Files:
-
- 4 added
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r132969 r132971 1 2012-10-30 Hans Muller <hmuller@adobe.com> 2 3 [CSS Exclusions] Multiple segment polygon layout does not get all segments 4 https://bugs.webkit.org/show_bug.cgi?id=100039 5 6 Reviewed by Dirk Schulze. 7 8 Added tests for CSS Exclusion shape-inside polygons with horizontal edges. 9 Corrected the simple-polygon.js code for computing a polygon's included intervals. 10 11 * fast/exclusions/resources/simple-polygon.js: 12 * fast/exclusions/shape-inside/shape-inside-rectilinear-polygon-001-expected.html: Added. 13 * fast/exclusions/shape-inside/shape-inside-rectilinear-polygon-001.html: Added. 14 * fast/exclusions/shape-inside/shape-inside-rectilinear-polygon-002-expected.html: Added. 15 * fast/exclusions/shape-inside/shape-inside-rectilinear-polygon-002.html: Added. 16 * fast/exclusions/shape-inside/shape-inside-simple-polygon-004-expected.html: 17 * fast/exclusions/shape-inside/shape-inside-simple-polygon-004.html: 18 1 19 2012-10-30 Kenichi Ishibashi <bashi@chromium.org> 2 20 -
trunk/LayoutTests/fast/exclusions/resources/simple-polygon.js
r131610 r132971 39 39 40 40 // Return two X intercepts of the horizontal line at y. We're assuming that the polygon 41 // 0 or 2 intercepts for all y.Of course this isn't true for polygons in general,41 // has 0 or 2 intercepts for all y. Of course this isn't true for polygons in general, 42 42 // just the ones used by the test cases supported by this file. 43 43 44 44 function polygonXIntercepts(polygon, y) { 45 45 var vertices = polygon.vertices; 46 var vertex = null; // first intersecting non-horizontal edge vertex, vertex.y == y47 var xIntercepts = [];48 49 for(var i = 0; i < vertices.length && xIntercepts.length < 2; i++) {46 var foundXIntercept = false; 47 var interceptsMinX, interceptsMaxX; 48 49 for(var i = 0; i < vertices.length; i++) { 50 50 var v1 = vertices[i]; 51 51 var v2 = vertices[(i + 1) % vertices.length]; 52 52 53 if ( vertex == v1 || vertex == v2)53 if (Math.max(v1.y, v2.y) < y || Math.min(v1.y, v2.y) > y) 54 54 continue; 55 55 56 var minY = Math.min(v1.y, v2.y); 57 var maxY = Math.max(v1.y, v2.y); 58 59 if (maxY < y || minY > y) 60 continue; 61 62 if (minY == maxY) 63 return [v1.x, v2.x]; 64 65 if (v1.y == y) { 66 xIntercepts.push(v1.x); 67 if (!vertex) 68 vertex = v1; 69 } 70 else if (v2.y == y) { 71 xIntercepts.push(v2.x); 72 if (!vertex) 73 vertex = v2; 56 if (v1.y == y && v2.y == y) { // horizontal edge 57 if (y != polygon.maxY) 58 continue; 59 60 if (!foundXIntercept) { 61 interceptsMinX = Math.min(v1.x, v2.x); 62 interceptsMaxX = Math.max(v1.x, v2.x); 63 foundXIntercept = true; 64 } 65 else { 66 interceptsMinX = Math.min(v1.x, v2.x, interceptsMinX); 67 interceptsMaxX = Math.max(v1.x, v2.x, interceptsMaxX); 68 } 74 69 } 75 70 else { 76 xIntercepts.push( ((y - v1.y) * (v2.x - v1.x) / (v2.y - v1.y)) + v1.x ); 71 var interceptX; 72 73 if (v1.y == y) 74 interceptX = v1.x; 75 else if (v2.y == y) 76 interceptX = v2.x; 77 else 78 interceptX = ((y - v1.y) * (v2.x - v1.x) / (v2.y - v1.y)) + v1.x; 79 80 if (!foundXIntercept) { 81 interceptsMinX = interceptsMaxX = interceptX; 82 foundXIntercept = true; 83 } 84 else { 85 interceptsMinX = Math.min(interceptX, interceptsMinX); 86 interceptsMaxX = Math.max(interceptX, interceptsMaxX); 87 } 77 88 } 78 89 } 79 90 80 if ( xIntercepts.length != 2)91 if (!foundXIntercept) 81 92 return []; 82 93 83 return [subpixelRound( Math.min.apply(null, xIntercepts)), Math.floor(Math.max.apply(null, xIntercepts))];94 return [subpixelRound(interceptsMinX), Math.floor(interceptsMaxX)]; 84 95 } 85 96 -
trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-simple-polygon-004-expected.html
r131610 r132971 9 9 // Concave assymetric simple polygon with horizontal top and bottom edges. A version of the 001 10 10 // hourglass shape with vertical edges in the center. 11 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}] };11 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}]; 12 12 var lineHeight = 40; 13 13 var hasSubpixelSupport; -
trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-simple-polygon-004.html
r131610 r132971 9 9 // Concave assymetric simple polygon with horizontal top and bottom edges. A version of the 001 10 10 // hourglass shape with vertical edges in the center. 11 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}] };11 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}]; 12 12 var lineHeight = 40; 13 13 var hasSubpixelSupport; -
trunk/Source/WebCore/ChangeLog
r132970 r132971 1 2012-10-30 Hans Muller <hmuller@adobe.com> 2 3 [CSS Exclusions] Multiple segment polygon layout does not get all segments 4 https://bugs.webkit.org/show_bug.cgi?id=100039 5 6 Reviewed by Dirk Schulze. 7 8 Corrected the algorithm for computing included polygon intervals for rectilinear polygons, 9 and polygons with horizontal edges in general. 10 11 Tests: fast/exclusions/shape-inside/shape-inside-rectilinear-polygon-001.html 12 fast/exclusions/shape-inside/shape-inside-rectilinear-polygon-002.html 13 14 * rendering/ExclusionPolygon.cpp: Removed some internal dead code related to the no-longer-used sortedEdgesMinY Vector. 15 (WebCore::ExclusionPolygon::ExclusionPolygon): Initialize new ExclusionPolygonEdge edgeIndex field. 16 (WebCore::getVertexIntersectionVertices): Return the previous, next, and target vertex indices for a vertex intersection. 17 (WebCore::ExclusionPolygon::computeXIntersections): Refactored the core of this method to improve handling of horizontal edges. 18 (WebCore::ExclusionPolygon::computeEdgeIntersections): Ignore zero-width edges. 19 * rendering/ExclusionPolygon.h: Removed the rightVertexY() method, since it's no longer used. 20 (WebCore::ExclusionPolygon::edgeAt): New method. 21 (WebCore::ExclusionPolygon::numberOfEdges): New method. 22 (ExclusionPolygon): Added support for retrieving edges. 23 (WebCore::ExclusionPolygonEdge::vertex1): Use vertex1Index. 24 (WebCore::ExclusionPolygonEdge::vertex2): Use vertex2Index. 25 (ExclusionPolygonEdge): Renamed index1, index2 fields to vertex1Index, vertex2Index. 26 (WebCore::ExclusionPolygonEdge::previousEdge): New method. 27 (WebCore::ExclusionPolygonEdge::nextEdge): New method. 28 1 29 2012-10-30 Chris Evans <cevans@google.com> 2 30 -
trunk/Source/WebCore/rendering/ExclusionPolygon.cpp
r132127 r132971 48 48 }; 49 49 50 static bool compareEdgeMinY(const ExclusionPolygonEdge* e1, const ExclusionPolygonEdge* e2)51 {52 return e1->minY() < e2->minY();53 }54 55 50 ExclusionPolygon::ExclusionPolygon(PassOwnPtr<Vector<FloatPoint> > vertices, WindRule fillRule) 56 51 : ExclusionShape() … … 61 56 m_edges.resize(nVertices); 62 57 m_empty = nVertices < 3; 63 Vector<ExclusionPolygonEdge*> sortedEdgesMinY(nVertices);64 58 65 59 if (nVertices) … … 70 64 m_boundingBox.extend(vertex); 71 65 m_edges[i].polygon = this; 72 m_edges[i].index1 = i; 73 m_edges[i].index2 = (i + 1) % nVertices; 74 75 sortedEdgesMinY[i] = &m_edges[i]; 76 } 77 78 std::sort(sortedEdgesMinY.begin(), sortedEdgesMinY.end(), WebCore::compareEdgeMinY); 66 m_edges[i].vertexIndex1 = i; 67 m_edges[i].vertexIndex2 = (i + 1) % nVertices; 68 m_edges[i].edgeIndex = i; 69 } 79 70 80 71 for (unsigned i = 0; i < m_edges.size(); i++) { … … 119 110 } 120 111 121 float ExclusionPolygon::rightVertexY(unsigned index) const 122 { 123 unsigned nVertices = numberOfVertices(); 124 const FloatPoint& vertex1 = vertexAt((index + 1) % nVertices); 125 const FloatPoint& vertex2 = vertexAt((index - 1) % nVertices); 126 127 if (vertex1.x() == vertex2.x()) 128 return vertex1.y() > vertex2.y() ? vertex1.y() : vertex2.y(); 129 return vertex1.x() > vertex2.x() ? vertex1.y() : vertex2.y(); 112 static inline bool getVertexIntersectionVertices(const EdgeIntersection& intersection, FloatPoint& prevVertex, FloatPoint& thisVertex, FloatPoint& nextVertex) 113 { 114 if (intersection.type != VertexMinY && intersection.type != VertexMaxY) 115 return false; 116 117 ASSERT(intersection.edge && intersection.edge->polygon); 118 const ExclusionPolygon& polygon = *(intersection.edge->polygon); 119 const ExclusionPolygonEdge& thisEdge = *(intersection.edge); 120 121 if ((intersection.type == VertexMinY && (thisEdge.vertex1().y() < thisEdge.vertex2().y())) 122 || (intersection.type == VertexMaxY && (thisEdge.vertex1().y() > thisEdge.vertex2().y()))) { 123 prevVertex = polygon.vertexAt(thisEdge.previousEdge().vertexIndex2); 124 thisVertex = polygon.vertexAt(thisEdge.vertexIndex1); 125 nextVertex = polygon.vertexAt(thisEdge.vertexIndex2); 126 } else { 127 prevVertex = polygon.vertexAt(thisEdge.vertexIndex1); 128 thisVertex = polygon.vertexAt(thisEdge.vertexIndex2); 129 nextVertex = polygon.vertexAt(thisEdge.nextEdge().vertexIndex1); 130 } 131 132 return true; 130 133 } 131 134 … … 156 159 for (unsigned i = 0; i < overlappingEdges.size(); i++) { 157 160 ExclusionPolygonEdge* edge = static_cast<ExclusionPolygonEdge*>(overlappingEdges[i].data()); 158 if (computeXIntersection(edge, y, intersection) )161 if (computeXIntersection(edge, y, intersection) && intersection.type != VertexYBoth) 159 162 intersections.append(intersection); 160 163 } … … 170 173 while (index < intersections.size()) { 171 174 const EdgeIntersection& thisIntersection = intersections[index]; 172 173 175 if (index + 1 < intersections.size()) { 174 176 const EdgeIntersection& nextIntersection = intersections[index + 1]; … … 178 180 index += 2; 179 181 } else { 180 // Replace pairs of intersections whose types are VertexMinY,VertexMaxY or VertexMaxY,VertexMinY with one VertexMinY intersection. 181 if (nextIntersection.type == VertexMaxY) 182 intersections[index + 1] = thisIntersection; 182 // Replace pairs of intersections whose types are VertexMinY,VertexMaxY or VertexMaxY,VertexMinY with one intersection. 183 183 index++; 184 184 } … … 188 188 189 189 const ExclusionPolygonEdge& thisEdge = *thisIntersection.edge; 190 bool crossing = !windCount;190 bool evenOddCrossing = !windCount; 191 191 192 192 if (fillRule() == RULE_EVENODD) { 193 193 windCount += (thisEdge.vertex2().y() > thisEdge.vertex1().y()) ? 1 : -1; 194 crossing = crossing || !windCount;194 evenOddCrossing = evenOddCrossing || !windCount; 195 195 } 196 196 197 if ((thisIntersection.type == Normal) || (thisIntersection.type == VertexMinY)) { 198 if (crossing) 197 if (evenOddCrossing) { 198 bool edgeCrossing = false; 199 if (thisIntersection.type == Normal || !inside || index == intersections.size() - 1) 200 edgeCrossing = true; 201 else { 202 FloatPoint prevVertex; 203 FloatPoint thisVertex; 204 FloatPoint nextVertex; 205 206 if (getVertexIntersectionVertices(thisIntersection, prevVertex, thisVertex, nextVertex)) { 207 if (prevVertex.y() == y) 208 edgeCrossing = (thisVertex.x() > prevVertex.x()) ? nextVertex.y() > y : nextVertex.y() < y; 209 else 210 edgeCrossing = (nextVertex.y() != y); 211 } 212 } 213 if (edgeCrossing) 199 214 inside = appendIntervalX(thisIntersection.point.x(), inside, result); 200 } else if (thisIntersection.type == VertexMaxY) { 201 int vertexIndex = (thisEdge.vertex2().y() > thisEdge.vertex1().y()) ? thisEdge.index2 : thisEdge.index1; 202 if (crossing && rightVertexY(vertexIndex) > y) 203 inside = appendIntervalX(thisEdge.maxX(), inside, result); 204 } else if (thisIntersection.type == VertexYBoth) 205 result.append(ExclusionInterval(thisEdge.minX(), thisEdge.maxX())); 215 } 206 216 207 217 index++; … … 236 246 std::swap(x1, x2); 237 247 238 result.append(ExclusionInterval(x1, x2)); 248 if (x2 > x1) 249 result.append(ExclusionInterval(x1, x2)); 239 250 } 240 251 -
trunk/Source/WebCore/rendering/ExclusionPolygon.h
r132127 r132971 60 60 WindRule fillRule() const { return m_fillRule; } 61 61 62 const ExclusionPolygonEdge& edgeAt(unsigned index) const { return m_edges[index]; } 63 unsigned numberOfEdges() const { return m_edges.size(); } 64 62 65 virtual FloatRect shapeLogicalBoundingBox() const OVERRIDE { return internalToLogicalBoundingBox(m_boundingBox); } 63 66 virtual bool isEmpty() const OVERRIDE { return m_empty; } … … 66 69 67 70 private: 68 float rightVertexY(unsigned) const;69 71 void computeXIntersections(float y, Vector<ExclusionInterval>&) const; 70 72 void computeEdgeIntersections(float minY, float maxY, Vector<ExclusionInterval>&) const; … … 88 90 { 89 91 ASSERT(polygon); 90 return polygon->vertexAt( index1);92 return polygon->vertexAt(vertexIndex1); 91 93 } 92 94 … … 94 96 { 95 97 ASSERT(polygon); 96 return polygon->vertexAt(index2); 98 return polygon->vertexAt(vertexIndex2); 99 } 100 101 const ExclusionPolygonEdge& previousEdge() const 102 { 103 ASSERT(polygon && polygon->numberOfEdges() > 1); 104 return polygon->edgeAt((edgeIndex + polygon->numberOfEdges() - 2) % polygon->numberOfEdges()); 105 } 106 107 const ExclusionPolygonEdge& nextEdge() const 108 { 109 ASSERT(polygon && polygon->numberOfEdges() > 1); 110 return polygon->edgeAt((edgeIndex + 1) % polygon->numberOfEdges()); 97 111 } 98 112 … … 103 117 104 118 const ExclusionPolygon* polygon; 105 unsigned index1; 106 unsigned index2; 119 unsigned vertexIndex1; 120 unsigned vertexIndex2; 121 unsigned edgeIndex; 107 122 }; 108 123
Note: See TracChangeset
for help on using the changeset viewer.