Changeset 147111 in webkit
- Timestamp:
- Mar 28, 2013 7:20:13 AM (11 years ago)
- Location:
- trunk
- Files:
-
- 6 added
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r147102 r147111 1 2013-03-28 Hans Muller <hmuller@adobe.com> 2 3 [CSS Exclusions] Add support for the simple case of padding a polygonal shape-inside 4 https://bugs.webkit.org/show_bug.cgi?id=112592 5 6 Reviewed by Dirk Schulze. 7 8 Verify that the CSS shape-padding property works correctly for some simple polygonal shapes: 9 a rectangle, a rectangle rotated 45 degress, and rectangular shape with a single reflex vertex. 10 11 * fast/exclusions/shape-inside/shape-inside-polygon-padding-001-expected.html: Added. 12 * fast/exclusions/shape-inside/shape-inside-polygon-padding-001.html: Added. 13 * fast/exclusions/shape-inside/shape-inside-polygon-padding-002-expected.html: Added. 14 * fast/exclusions/shape-inside/shape-inside-polygon-padding-002.html: Added. 15 * fast/exclusions/shape-inside/shape-inside-polygon-padding-003-expected.html: Added. 16 * fast/exclusions/shape-inside/shape-inside-polygon-padding-003.html: Added. 17 1 18 2013-03-28 Vsevolod Vlasov <vsevik@chromium.org> 2 19 -
trunk/Source/WebCore/ChangeLog
r147110 r147111 1 2013-03-28 Hans Muller <hmuller@adobe.com> 2 3 [CSS Exclusions] Add support for the simple case of padding a polygonal shape-inside 4 https://bugs.webkit.org/show_bug.cgi?id=112592 5 6 Reviewed by Dirk Schulze. 7 8 First pass at computing the padded or inset boundary of a polygon. This version does not handle 9 self-intersecting polygons, or values of shape-padding large enough to change the shape of the 10 original polygon. The implementation computes an offset edge for each polgon edge, where the offset 11 edge is parallel to the original edge and separated by shape-padding. The padded polygon's vertices 12 are the intersections of each pair of adjacent offset edges. When adjacent offset edges do not intersect, 13 because they share a reflex vertex in the original polygon, an approximation to a circular arc 14 connects the offset edges. 15 16 Tests: fast/exclusions/shape-inside/shape-inside-polygon-padding-001.html 17 fast/exclusions/shape-inside/shape-inside-polygon-padding-002.html 18 fast/exclusions/shape-inside/shape-inside-polygon-padding-003.html 19 20 * rendering/ExclusionPolygon.cpp: 21 (WebCore::isReflexVertex): Just moved this function earlier in the file. 22 (WebCore::inwardEdgeNormal): Unit vector that's perpindicular to the edge and that points inwards. 23 (WebCore::outwardEdgeNormal): Unit vector that's perpindicular to the edge and that points outwards. 24 (WebCore::appendArc): Append a linear approximation to a circular arc to a vector of vertices. 25 (WebCore::computeShapePaddingBounds): Return a polygon whose edges are all inset by shape-padding from m_polygon. 26 (WebCore::computeShapeMarginBounds): Just a stub, see bug 112917. 27 (WebCore::ExclusionPolygon::shapePaddingBounds): Lazily use computeShapePaddingBounds() to initialize m_paddingBounds. 28 (WebCore::ExclusionPolygon::shapeMarginBounds): Lazily use computeShapeMarginBounds() to initialize m_marginBounds. 29 (WebCore::ExclusionPolygon::getIncludedIntervals): Now based on the value of shapePaddingBounds(). 30 (WebCore::ExclusionPolygon::firstIncludedIntervalLogicalTop): Now based on the value of shapePaddingBounds(). 31 * rendering/ExclusionPolygon.h: 32 (WebCore::ExclusionPolygon::ExclusionPolygon): 33 1 34 2013-03-28 Chris Hutten-Czapski <chutten@blackberry.com> 2 35 -
trunk/Source/WebCore/rendering/ExclusionPolygon.cpp
r145411 r147111 53 53 } 54 54 55 static inline bool isReflexVertex(const FloatPoint& prevVertex, const FloatPoint& vertex, const FloatPoint& nextVertex) 56 { 57 return leftSide(prevVertex, nextVertex, vertex) < 0; 58 } 59 55 60 static bool computeXIntersection(const FloatPolygonEdge* edgePointer, float y, EdgeIntersection& result) 56 61 { … … 86 91 87 92 return true; 93 } 94 95 static inline FloatSize inwardEdgeNormal(const FloatPolygonEdge& edge) 96 { 97 FloatSize edgeDelta = edge.vertex2() - edge.vertex1(); 98 if (!edgeDelta.width()) 99 return FloatSize((edgeDelta.height() > 0 ? -1 : 1), 0); 100 if (!edgeDelta.height()) 101 return FloatSize(0, (edgeDelta.width() > 0 ? 1 : -1)); 102 float edgeLength = edgeDelta.diagonalLength(); 103 return FloatSize(-edgeDelta.height() / edgeLength, edgeDelta.width() / edgeLength); 104 } 105 106 static inline FloatSize outwardEdgeNormal(const FloatPolygonEdge& edge) 107 { 108 return -inwardEdgeNormal(edge); 109 } 110 111 static inline void appendArc(Vector<FloatPoint>& vertices, const FloatPoint& arcCenter, float arcRadius, const FloatPoint& startArcVertex, const FloatPoint& endArcVertex) 112 { 113 float startAngle = atan2(startArcVertex.y() - arcCenter.y(), startArcVertex.x() - arcCenter.x()); 114 float endAngle = atan2(endArcVertex.y() - arcCenter.y(), endArcVertex.x() - arcCenter.x()); 115 if (startAngle < 0) 116 startAngle += piFloat * 2; 117 if (endAngle < 0) 118 endAngle += piFloat * 2; 119 const float arcSegmentCount = 5; // An odd number so that one arc vertex will be eactly arcRadius from arcCenter. 120 float angle5 = ((startAngle > endAngle) ? (startAngle - endAngle) : (startAngle + piFloat * 2 - endAngle)) / arcSegmentCount; 121 122 vertices.append(startArcVertex); 123 for (unsigned i = 1; i < arcSegmentCount; ++i) { 124 float angle = startAngle - angle5 * i; 125 vertices.append(arcCenter + FloatPoint(cos(angle) * arcRadius, sin(angle) * arcRadius)); 126 } 127 vertices.append(endArcVertex); 128 } 129 130 static inline FloatPolygon *computeShapePaddingBounds(const FloatPolygon& polygon, float padding, WindRule fillRule) 131 { 132 Vector<FloatPoint>* paddedVertices = new Vector<FloatPoint>(); 133 FloatPoint intersection; 134 135 for (unsigned i = 0; i < polygon.numberOfEdges(); ++i) { 136 const FloatPolygonEdge& thisEdge = polygon.edgeAt(i); 137 const FloatPolygonEdge& prevEdge = thisEdge.previousEdge(); 138 OffsetPolygonEdge thisOffsetEdge(thisEdge, inwardEdgeNormal(thisEdge) * padding); 139 OffsetPolygonEdge prevOffsetEdge(prevEdge, inwardEdgeNormal(prevEdge) * padding); 140 141 if (prevOffsetEdge.intersection(thisOffsetEdge, intersection)) 142 paddedVertices->append(intersection); 143 else if (isReflexVertex(prevEdge.vertex1(), thisEdge.vertex1(), thisEdge.vertex2())) 144 appendArc(*paddedVertices, thisEdge.vertex1(), padding, prevOffsetEdge.vertex2(), thisOffsetEdge.vertex1()); 145 } 146 147 return new FloatPolygon(adoptPtr(paddedVertices), fillRule); 148 } 149 150 // FIXME: this is just a stub (bug 112917) 151 static inline FloatPolygon *computeShapeMarginBounds(const FloatPolygon& polygon, float margin, WindRule fillRule) 152 { 153 UNUSED_PARAM(margin); 154 155 Vector<FloatPoint>* marginVertices = new Vector<FloatPoint>(polygon.numberOfVertices()); 156 for (unsigned i = 0; i < polygon.numberOfVertices(); ++i) 157 (*marginVertices)[i] = polygon.vertexAt(i); 158 return new FloatPolygon(adoptPtr(marginVertices), fillRule); 159 } 160 161 const FloatPolygon& ExclusionPolygon::shapePaddingBounds() const 162 { 163 ASSERT(shapePadding() >= 0); 164 if (!shapePadding()) 165 return m_polygon; 166 167 if (!m_paddingBounds) 168 m_paddingBounds = adoptPtr(computeShapePaddingBounds(m_polygon, shapePadding(), m_polygon.fillRule())); 169 170 return *m_paddingBounds; 171 } 172 173 const FloatPolygon& ExclusionPolygon::shapeMarginBounds() const 174 { 175 ASSERT(shapeMargin() >= 0); 176 if (!shapeMargin()) 177 return m_polygon; 178 179 if (!m_marginBounds) 180 m_marginBounds = adoptPtr(computeShapeMarginBounds(m_polygon, shapeMargin(), m_polygon.fillRule())); 181 182 return *m_marginBounds; 88 183 } 89 184 … … 261 356 void ExclusionPolygon::getIncludedIntervals(float logicalTop, float logicalHeight, SegmentList& result) const 262 357 { 263 if (isEmpty()) 358 const FloatPolygon& polygon = shapePaddingBounds(); 359 if (polygon.isEmpty()) 264 360 return; 265 361 … … 268 364 269 365 Vector<ExclusionInterval> y1XIntervals, y2XIntervals; 270 computeXIntersections( m_polygon, y1, true, y1XIntervals);271 computeXIntersections( m_polygon, y2, false, y2XIntervals);366 computeXIntersections(polygon, y1, true, y1XIntervals); 367 computeXIntersections(polygon, y2, false, y2XIntervals); 272 368 273 369 Vector<ExclusionInterval> commonIntervals; … … 275 371 276 372 Vector<ExclusionInterval> edgeIntervals; 277 computeOverlappingEdgeXProjections( m_polygon, y1, y2, edgeIntervals);373 computeOverlappingEdgeXProjections(polygon, y1, y2, edgeIntervals); 278 374 279 375 Vector<ExclusionInterval> includedIntervals; … … 284 380 result.append(LineSegment(interval.x1, interval.x2)); 285 381 } 286 }287 288 static inline bool isReflexVertex(const FloatPoint& prevVertex, const FloatPoint& vertex, const FloatPoint& nextVertex)289 {290 return leftSide(prevVertex, nextVertex, vertex) < 0;291 382 } 292 383 … … 317 408 bool ExclusionPolygon::firstIncludedIntervalLogicalTop(float minLogicalIntervalTop, const FloatSize& minLogicalIntervalSize, float& result) const 318 409 { 319 const FloatRect boundingBox = m_polygon.boundingBox(); 410 const FloatPolygon& polygon = shapePaddingBounds(); 411 const FloatRect boundingBox = polygon.boundingBox(); 320 412 if (minLogicalIntervalSize.width() > boundingBox.width()) 321 413 return false; … … 328 420 329 421 Vector<const FloatPolygonEdge*> edges; 330 m_polygon.overlappingEdges(minLogicalIntervalTop, boundingBox.maxY(), edges);422 polygon.overlappingEdges(minLogicalIntervalTop, boundingBox.maxY(), edges); 331 423 332 424 float dx = minLogicalIntervalSize.width() / 2; … … 365 457 } 366 458 367 offsetEdges.append(OffsetPolygonEdge( m_polygon, minLogicalIntervalTop, FloatSize(0, dy)));459 offsetEdges.append(OffsetPolygonEdge(polygon, minLogicalIntervalTop, FloatSize(0, dy))); 368 460 369 461 FloatPoint offsetEdgesIntersection; … … 378 470 if ((potentialFirstFitLocation.y() >= minLogicalIntervalTop) 379 471 && (!firstFitFound || aboveOrToTheLeft(potentialFirstFitRect, firstFitRect)) 380 && m_polygon.contains(offsetEdgesIntersection)381 && firstFitRectInPolygon( m_polygon, potentialFirstFitRect, offsetEdges[i].edgeIndex(), offsetEdges[j].edgeIndex())) {472 && polygon.contains(offsetEdgesIntersection) 473 && firstFitRectInPolygon(polygon, potentialFirstFitRect, offsetEdges[i].edgeIndex(), offsetEdges[j].edgeIndex())) { 382 474 firstFitFound = true; 383 475 firstFitRect = potentialFirstFitRect; -
trunk/Source/WebCore/rendering/ExclusionPolygon.h
r145411 r147111 76 76 : ExclusionShape() 77 77 , m_polygon(vertices, fillRule) 78 , m_marginBounds(nullptr) 79 , m_paddingBounds(nullptr) 78 80 { 79 81 } … … 85 87 virtual bool firstIncludedIntervalLogicalTop(float minLogicalIntervalTop, const FloatSize& minLogicalIntervalSize, float&) const OVERRIDE; 86 88 89 const FloatPolygon& shapeMarginBounds() const; 90 const FloatPolygon& shapePaddingBounds() const; 91 87 92 private: 88 93 FloatPolygon m_polygon; 94 mutable OwnPtr<FloatPolygon> m_marginBounds; 95 mutable OwnPtr<FloatPolygon> m_paddingBounds; 89 96 }; 90 97
Note: See TracChangeset
for help on using the changeset viewer.