diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog index de51d3dbc6d6f3f3218810fdaf2c1b67508ee63d..459963c8cd2dd45bd52da4202b4d386fbfeb7e54 100644 --- a/LayoutTests/ChangeLog +++ b/LayoutTests/ChangeLog @@ -1,3 +1,19 @@ +2013-04-05 Hans Muller + + [CSS Exclusions] Add support for the simple case of shape-margin polygonal shape-outside + https://bugs.webkit.org/show_bug.cgi?id=113726 + + Reviewed by Dirk Schulze. + + Verify that shape-outside layout works correctly on floats, when shape-margin is specifed. + + * fast/exclusions/shape-outside-floats/shape-outside-floats-diamond-margin-polygon-expected.txt: Added. + * fast/exclusions/shape-outside-floats/shape-outside-floats-diamond-margin-polygon.html: Added. + * fast/exclusions/shape-outside-floats/shape-outside-floats-left-margin-polygon-expected.html: Added. + * fast/exclusions/shape-outside-floats/shape-outside-floats-left-margin-polygon.html: Added. + * fast/exclusions/shape-outside-floats/shape-outside-floats-right-margin-polygon-expected.html: Added. + * fast/exclusions/shape-outside-floats/shape-outside-floats-right-margin-polygon.html: Added. + 2013-04-05 Benjamin Poulain Modernize fast/events/autoscroll.html diff --git a/LayoutTests/fast/exclusions/shape-outside-floats/shape-outside-floats-diamond-margin-polygon-expected.txt b/LayoutTests/fast/exclusions/shape-outside-floats/shape-outside-floats-diamond-margin-polygon-expected.txt new file mode 100644 index 0000000000000000000000000000000000000000..b86d8f83c0f93a44983f1d1408bc54aa5bb7903f --- /dev/null +++ b/LayoutTests/fast/exclusions/shape-outside-floats/shape-outside-floats-diamond-margin-polygon-expected.txt @@ -0,0 +1,19 @@ +PASS elementRect('l1').top is 0 +PASS elementRect('l1').left is within 1 of 98 +PASS elementRect('l2').top is 20 +PASS elementRect('l2').left is within 1 of 118 +PASS elementRect('l3').top is 40 +PASS elementRect('l3').left is within 1 of 138 +PASS elementRect('l4').top is 80 +PASS elementRect('l4').left is within 1 of 138 +PASS elementRect('l5').top is 100 +PASS elementRect('l5').left is within 1 of 118 +PASS elementRect('l6').top is 120 +PASS elementRect('l6').left is within 1 of 98 +X +X +X + +X +X +X diff --git a/LayoutTests/fast/exclusions/shape-outside-floats/shape-outside-floats-diamond-margin-polygon.html b/LayoutTests/fast/exclusions/shape-outside-floats/shape-outside-floats-diamond-margin-polygon.html new file mode 100644 index 0000000000000000000000000000000000000000..7a7fa9f0c7fe1150fd647eeaf888f368225d94e1 --- /dev/null +++ b/LayoutTests/fast/exclusions/shape-outside-floats/shape-outside-floats-diamond-margin-polygon.html @@ -0,0 +1,84 @@ + + + + + + + + + + +

+
+
+ + + +
+ X
X
X

X
X
X +
+ + + + diff --git a/LayoutTests/fast/exclusions/shape-outside-floats/shape-outside-floats-left-margin-polygon-expected.html b/LayoutTests/fast/exclusions/shape-outside-floats/shape-outside-floats-left-margin-polygon-expected.html new file mode 100644 index 0000000000000000000000000000000000000000..c03758af469224fda549630ec3338c1aa885d6e0 --- /dev/null +++ b/LayoutTests/fast/exclusions/shape-outside-floats/shape-outside-floats-left-margin-polygon-expected.html @@ -0,0 +1,53 @@ + + + + + + +

The left edges of the five black squares should follow the right side of the outer rounded rectangle boundary and each square should appear on a subsequent line.

+
+
+
X
X
X
X
X
+ + + + +
+
+ + + diff --git a/LayoutTests/fast/exclusions/shape-outside-floats/shape-outside-floats-left-margin-polygon.html b/LayoutTests/fast/exclusions/shape-outside-floats/shape-outside-floats-left-margin-polygon.html new file mode 100644 index 0000000000000000000000000000000000000000..fbe005bffc8bd9a31a6d4fcebad242a080b16788 --- /dev/null +++ b/LayoutTests/fast/exclusions/shape-outside-floats/shape-outside-floats-left-margin-polygon.html @@ -0,0 +1,47 @@ + + + + + + + + +

The left edges of the five black squares should follow the right side of the outer rounded rectangle boundary and each square should appear on a subsequent line.

+
+
+ + + + +
+ X
X
X
X
X +
+ + + diff --git a/LayoutTests/fast/exclusions/shape-outside-floats/shape-outside-floats-right-margin-polygon-expected.html b/LayoutTests/fast/exclusions/shape-outside-floats/shape-outside-floats-right-margin-polygon-expected.html new file mode 100644 index 0000000000000000000000000000000000000000..2469f894869a69feed1aa532e01af486feb55362 --- /dev/null +++ b/LayoutTests/fast/exclusions/shape-outside-floats/shape-outside-floats-right-margin-polygon-expected.html @@ -0,0 +1,53 @@ + + + + + + +

The right edges of the five black squares should follow the left side of the outer rounded rectangle boundary and each square should appear on a subsequent line.

+
+
+
X
X
X
X
X
+ + + + +
+
+ + + diff --git a/LayoutTests/fast/exclusions/shape-outside-floats/shape-outside-floats-right-margin-polygon.html b/LayoutTests/fast/exclusions/shape-outside-floats/shape-outside-floats-right-margin-polygon.html new file mode 100644 index 0000000000000000000000000000000000000000..1aaec9ad947b1e19df642eaffeb41224cc8ed0f1 --- /dev/null +++ b/LayoutTests/fast/exclusions/shape-outside-floats/shape-outside-floats-right-margin-polygon.html @@ -0,0 +1,48 @@ + + + + + + + + +

The right edges of the five black squares should follow the left side of the outer rounded rectangle boundary and each square should appear on a subsequent line.

+
+
+ + + + +
+ X
X
X
X
X +
+ + + diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog index 39ed3df20b22d711f5be8ef5ba7536db11dde523..233874a81a1ecf56fa0dfca1c1e4c111b9d64605 100644 --- a/Source/WebCore/ChangeLog +++ b/Source/WebCore/ChangeLog @@ -1,3 +1,26 @@ +2013-04-05 Hans Muller + + [CSS Exclusions] Add support for the simple case of shape-margin polygonal shape-outside + https://bugs.webkit.org/show_bug.cgi?id=113726 + + Reviewed by Dirk Schulze. + + Add support for computing the shape-outside shape-margin boundary for a polygon. + This change is similar to the one added for padding polygons, see bug 112592. + The algorithm used for computing the margin boundary is is provisional. It works + correctly for convex polygons and will work correctly for non self-intersecting + polygons whose margin boundary is the same shape as the original polygon. + + Tests: fast/exclusions/shape-outside-floats/shape-outside-floats-diamond-margin-polygon.html + fast/exclusions/shape-outside-floats/shape-outside-floats-left-margin-polygon.html + fast/exclusions/shape-outside-floats/shape-outside-floats-right-margin-polygon.html + + * rendering/ExclusionPolygon.cpp: + (WebCore::appendArc): Generalized this method a little, to deal with margin and padding connecting arcs. + (WebCore::computeShapePaddingBounds): Pass the new appendArc() parameter. + (WebCore::computeShapeMarginBounds): Compute the margin boundary for a polygon, per the constraints summarized above. + (WebCore::ExclusionPolygon::getExcludedIntervals): Use the margin polygon for this computation. + 2013-04-05 Andy Estes Returning NULL from willSendRequest should cancel a load from the memory cache diff --git a/Source/WebCore/rendering/ExclusionPolygon.cpp b/Source/WebCore/rendering/ExclusionPolygon.cpp index 760699efb962b1b07bca8a4283e6297e20f5be02..91f643eb7993ccde9ba1c842bf8fc88c4e40c458 100644 --- a/Source/WebCore/rendering/ExclusionPolygon.cpp +++ b/Source/WebCore/rendering/ExclusionPolygon.cpp @@ -108,20 +108,22 @@ static inline FloatSize outwardEdgeNormal(const FloatPolygonEdge& edge) return -inwardEdgeNormal(edge); } -static inline void appendArc(Vector& vertices, const FloatPoint& arcCenter, float arcRadius, const FloatPoint& startArcVertex, const FloatPoint& endArcVertex) +static inline void appendArc(Vector& vertices, const FloatPoint& arcCenter, float arcRadius, const FloatPoint& startArcVertex, const FloatPoint& endArcVertex, bool padding) { float startAngle = atan2(startArcVertex.y() - arcCenter.y(), startArcVertex.x() - arcCenter.x()); float endAngle = atan2(endArcVertex.y() - arcCenter.y(), endArcVertex.x() - arcCenter.x()); + const float twoPI = piFloat * 2; if (startAngle < 0) - startAngle += piFloat * 2; + startAngle += twoPI; if (endAngle < 0) - endAngle += piFloat * 2; + endAngle += twoPI; + float angle = (startAngle > endAngle) ? (startAngle - endAngle) : (startAngle + twoPI - endAngle); const float arcSegmentCount = 5; // An odd number so that one arc vertex will be eactly arcRadius from arcCenter. - float angle5 = ((startAngle > endAngle) ? (startAngle - endAngle) : (startAngle + piFloat * 2 - endAngle)) / arcSegmentCount; + float angle5 = ((padding) ? -angle : twoPI - angle) / arcSegmentCount; vertices.append(startArcVertex); for (unsigned i = 1; i < arcSegmentCount; ++i) { - float angle = startAngle - angle5 * i; + float angle = startAngle + angle5 * i; vertices.append(arcCenter + FloatPoint(cos(angle) * arcRadius, sin(angle) * arcRadius)); } vertices.append(endArcVertex); @@ -141,20 +143,29 @@ static inline FloatPolygon *computeShapePaddingBounds(const FloatPolygon& polygo if (prevOffsetEdge.intersection(thisOffsetEdge, intersection)) paddedVertices->append(intersection); else if (isReflexVertex(prevEdge.vertex1(), thisEdge.vertex1(), thisEdge.vertex2())) - appendArc(*paddedVertices, thisEdge.vertex1(), padding, prevOffsetEdge.vertex2(), thisOffsetEdge.vertex1()); + appendArc(*paddedVertices, thisEdge.vertex1(), padding, prevOffsetEdge.vertex2(), thisOffsetEdge.vertex1(), true); } return new FloatPolygon(adoptPtr(paddedVertices), fillRule); } -// FIXME: this is just a stub (bug 112917) static inline FloatPolygon *computeShapeMarginBounds(const FloatPolygon& polygon, float margin, WindRule fillRule) { - UNUSED_PARAM(margin); + Vector* marginVertices = new Vector(); + FloatPoint intersection; + + for (unsigned i = 0; i < polygon.numberOfEdges(); ++i) { + const FloatPolygonEdge& thisEdge = polygon.edgeAt(i); + const FloatPolygonEdge& prevEdge = thisEdge.previousEdge(); + OffsetPolygonEdge thisOffsetEdge(thisEdge, outwardEdgeNormal(thisEdge) * margin); + OffsetPolygonEdge prevOffsetEdge(prevEdge, outwardEdgeNormal(prevEdge) * margin); + + if (prevOffsetEdge.intersection(thisOffsetEdge, intersection)) + marginVertices->append(intersection); + else + appendArc(*marginVertices, thisEdge.vertex1(), margin, prevOffsetEdge.vertex2(), thisOffsetEdge.vertex1(), false); + } - Vector* marginVertices = new Vector(polygon.numberOfVertices()); - for (unsigned i = 0; i < polygon.numberOfVertices(); ++i) - (*marginVertices)[i] = polygon.vertexAt(i); return new FloatPolygon(adoptPtr(marginVertices), fillRule); } @@ -328,21 +339,22 @@ static void computeOverlappingEdgeXProjections(const FloatPolygon& polygon, floa void ExclusionPolygon::getExcludedIntervals(float logicalTop, float logicalHeight, SegmentList& result) const { - if (isEmpty()) + const FloatPolygon& polygon = shapeMarginBounds(); + if (polygon.isEmpty()) return; float y1 = logicalTop; float y2 = y1 + logicalHeight; Vector y1XIntervals, y2XIntervals; - computeXIntersections(m_polygon, y1, true, y1XIntervals); - computeXIntersections(m_polygon, y2, false, y2XIntervals); + computeXIntersections(polygon, y1, true, y1XIntervals); + computeXIntersections(polygon, y2, false, y2XIntervals); Vector mergedIntervals; mergeExclusionIntervals(y1XIntervals, y2XIntervals, mergedIntervals); Vector edgeIntervals; - computeOverlappingEdgeXProjections(m_polygon, y1, y2, edgeIntervals); + computeOverlappingEdgeXProjections(polygon, y1, y2, edgeIntervals); Vector excludedIntervals; mergeExclusionIntervals(mergedIntervals, edgeIntervals, excludedIntervals);