Commit 2a8e9f3b authored by hmuller@adobe.com's avatar hmuller@adobe.com

[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.

Source/WebCore:

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.

LayoutTests:

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.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@147831 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 191b1d5e
2013-04-05 Hans Muller <hmuller@adobe.com>
[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 <bpoulain@apple.com>
Modernize fast/events/autoscroll.html
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
<!DOCTYPE html>
<html>
<head>
<script>
if (window.internals)
window.internals.settings.setCSSExclusionsEnabled(true);
</script>
<script src="../../js/resources/js-test-pre.js"></script>
<script src="../resources/subpixel-utils.js"></script>
<style>
#container {
font: 20px/1 Ahem, sans-serif;
width: 200px;
height: 300px;
}
#float-left {
float: left;
position: relative;
overflow: visible;
-webkit-shape-outside: polygon(50px 0px, 100px 50px, 50px 100px, 0px 50px);
-webkit-shape-margin: 20px;
}
#svg-shape {
position: absolute;
display:block;
width: 100px;
height: 100px;
}
</style>
<body>
<p></p>
<div id="container">
<div id="float-left">
<svg id="svg-shape" xmlns="http://www.w3.org/2000/">
<polygon points="50,0 100,50 50,100 0,50" fill="rgba(0,150,0, 0.5)"/>
</svg>
</div>
<span id="l1">X</span></br><span id="l2">X</span><br/><span id="l3">X</span><br/><br/><span id="l4">X</span><br/><span id="l5">X</span><br/><span id="l6">X</span>
</div>
</body>
<script>
function elementRect(elementId)
{
var s = document.getElementById("container").getBoundingClientRect();
var r = document.getElementById(elementId).getBoundingClientRect();
return {left: r.left - s.left, top: r.top - s.top, width: r.width, height: r.height};
}
// The polygon's X coordinates are 0, 50, 100, specified relative to the "float-left" element. Its shape-marign is 20px.
// The horizontal center of the margin polygon, relative to the container element is 20*sqrt(2) + 50. So the left
// edge of the (20px square) Ahem character on the first "l1" line (y == 20) is: 20 + (20*sqrt(2) + 50) = 98.28.
// The second and third lines, "l2" and "l3" are similar, each one begins 20 pixels farther to the right.
// The left edges of "l4-l6" are the same as the first three, just in reverse order.
function marginLeftXIntercept(lineNumber)
{
return SubPixelLayout.roundLineLeft(lineNumber * 20 + 20 * Math.sqrt(2) + 50);
}
shouldBe("elementRect('l1').top", "0");
shouldBeCloseTo("elementRect('l1').left", marginLeftXIntercept(1), 1);
shouldBe("elementRect('l2').top", "20");
shouldBeCloseTo("elementRect('l2').left", marginLeftXIntercept(2), 1);
shouldBe("elementRect('l3').top", "40");
shouldBeCloseTo("elementRect('l3').left", marginLeftXIntercept(3), 1);
shouldBe("elementRect('l4').top", "80");
shouldBeCloseTo("elementRect('l4').left", marginLeftXIntercept(3), 1);
shouldBe("elementRect('l5').top", "100");
shouldBeCloseTo("elementRect('l5').left", marginLeftXIntercept(2), 1);
shouldBe("elementRect('l6').top", "120");
shouldBeCloseTo("elementRect('l6').left", marginLeftXIntercept(1), 1);
</script>
</html>
<!DOCTYPE html>
<html>
<head>
<style>
#container-border {
border: 1px solid black;
margin: 10px;
width: 200px;
}
#container {
font: 20px/1 Ahem, sans-serif;
width: 200px;
height: 300px;
}
#float-left {
float: left;
position: relative;
overflow: visible;
}
#svg-shape {
position: absolute;
display:block;
top: -1px;
left: -1px;
width: 142px;
height: 102px;
}
#expected-text {
position: relative;
top: 0px;
left: 140px;
}
</style>
<body>
<p>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.</p>
<div id="container">
<div id="float-left">
<div id="expected-text">X<br/>X<br/>X<br/>X<br/>X</div>
<svg id="svg-shape" xmlns="http://www.w3.org/2000/">
<rect x="20" y="20" width="100" height="60" fill="none" stroke="green"></rect>
<rect x="1" y="1" width="140" height="100" rx="20" ry="20" fill="none" stroke="green"></rect>
</svg>
</div>
</div>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<script>
if (window.internals)
window.internals.settings.setCSSExclusionsEnabled(true);
</script>
<style>
#container {
font: 20px/1 Ahem, sans-serif;
width: 200px;
height: 300px;
}
#float-left {
float: left;
position: relative;
overflow: visible;
-webkit-shape-outside: polygon(0px 0px, 100px 0px, 100px 60px, 0px 60px);
-webkit-shape-margin: 20px;
}
#svg-shape {
position: absolute;
display:block;
top: -21px;
left: -21px;
width: 142px;
height: 102px;
}
</style>
<body>
<p>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.</p>
<div id="container">
<div id="float-left">
<svg id="svg-shape" xmlns="http://www.w3.org/2000/">
<rect x="20" y="20" width="100" height="60" fill="none" stroke="green"></rect>
<rect x="1" y="1" width="140" height="100" rx="20" ry="20" fill="none" stroke="green"></rect>
</svg>
</div>
X<br/>X<br/>X<br/>X<br/>X
</div>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<style>
#container-border {
border: 1px solid black;
margin: 10px;
width: 200px;
}
#container {
font: 20px/1 Ahem, sans-serif;
width: 200px;
height: 300px;
}
#float-right {
float: right;
position: relative;
overflow: visible;
}
#svg-shape {
position: absolute;
display:block;
top: -1px;
left: -141px;
width: 142px;
height: 102px;
}
#expected-text {
position: absolute;
top: 0px;
left: -160px;
}
</style>
<body>
<p>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.</p>
<div id="container">
<div id="float-right">
<div id="expected-text">X<br/>X<br/>X<br/>X<br/>X</div>
<svg id="svg-shape" xmlns="http://www.w3.org/2000/">
<rect x="20" y="20" width="100" height="60" fill="none" stroke="green"></rect>
<rect x="1" y="1" width="140" height="100" rx="20" ry="20" fill="none" stroke="green"></rect>
</svg>
</div>
</div>
</body>
</html>
<!DOCTYPE html>
<html>
<head>
<script>
if (window.internals)
window.internals.settings.setCSSExclusionsEnabled(true);
</script>
<style>
#container {
font: 20px/1 Ahem, sans-serif;
width: 200px;
height: 300px;
text-align: right;
}
#float-right {
float: right;
position: relative;
overflow: visible;
-webkit-shape-outside: polygon(0px 0px, 100px 0px, 100px 60px, 0px 60px);
-webkit-shape-margin: 20px;
}
#svg-shape {
position: absolute;
display:block;
top: -21px;
left: -21px;
width: 142px;
height: 102px;
}
</style>
<body>
<p>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.</p>
<div id="container">
<div id="float-right">
<svg id="svg-shape" xmlns="http://www.w3.org/2000/">
<rect x="20" y="20" width="100" height="60" fill="none" stroke="green"></rect>
<rect x="1" y="1" width="140" height="100" rx="20" ry="20" fill="none" stroke="green"></rect>
</svg>
</div>
X<br/>X<br/>X<br/>X<br/>X
</div>
</body>
</html>
2013-04-05 Hans Muller <hmuller@adobe.com>
[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 <aestes@apple.com>
Returning NULL from willSendRequest should cancel a load from the memory cache
......@@ -108,20 +108,22 @@ static inline FloatSize outwardEdgeNormal(const FloatPolygonEdge& edge)
return -inwardEdgeNormal(edge);
}
static inline void appendArc(Vector<FloatPoint>& vertices, const FloatPoint& arcCenter, float arcRadius, const FloatPoint& startArcVertex, const FloatPoint& endArcVertex)
static inline void appendArc(Vector<FloatPoint>& 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<FloatPoint>* marginVertices = new Vector<FloatPoint>();
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<FloatPoint>* marginVertices = new Vector<FloatPoint>(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<ExclusionInterval> 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<ExclusionInterval> mergedIntervals;
mergeExclusionIntervals(y1XIntervals, y2XIntervals, mergedIntervals);
Vector<ExclusionInterval> edgeIntervals;
computeOverlappingEdgeXProjections(m_polygon, y1, y2, edgeIntervals);
computeOverlappingEdgeXProjections(polygon, y1, y2, edgeIntervals);
Vector<ExclusionInterval> excludedIntervals;
mergeExclusionIntervals(mergedIntervals, edgeIntervals, excludedIntervals);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment