Title: [136857] trunk
Revision
136857
Author
[email protected]
Date
2012-12-06 11:05:15 -0800 (Thu, 06 Dec 2012)

Log Message

[CSS Exclusions] Add support for computing the first included interval position.
https://bugs.webkit.org/show_bug.cgi?id=103327

Source/WebCore:

Patch by Hans Muller <[email protected]> on 2012-12-06
Reviewed by Levi Weintraub.

If the first "word" in a line doesn't fit within the shape-inside when lineTop
is the top of the shape's logical bounding box, adjust lineTop downwards to where
the word fits.  Currently only rounded rectangle shapes are supported.

Added ExclusionShape::firstIncludedIntervalLogicalTop(). The new virtual method
computes the topmost/leftmost location where a line segment with the specified
minLogicalIntervalSize will fit within the exclusion shape and returns the
corresponding logical Y coordinate.  The result is additionally constrained to
be at or below minLogicalIntervalTop. If the segment will not fit anywhere within
the shape, then false is returned.

During layout, minLogicalIntervalTop is the nominal top of the line being laid
out within the exclusion shape.

RenderBlock::layoutRunsAndFloatsInRange() now calls a new ExclusionShapeInsideInfo
method, adjustLogicalLineTop(), which uses firstIncludedIntervalLogicalTop() to
decide if the logical top of the line has to be moved downwards, for the first
word to fit within the exclusion shape.

Tests: fast/exclusions/shape-inside/shape-inside-rounded-rectangle-fit-001.html
       fast/exclusions/shape-inside/shape-inside-rounded-rectangle-fit-002.html

* rendering/ExclusionPolygon.cpp:
(WebCore::ExclusionPolygon::firstIncludedIntervalLogicalTop): This is a stub implementation.
* rendering/ExclusionPolygon.h:
* rendering/ExclusionRectangle.cpp:
(WebCore::ellipseXIntercept): Added spaces to conform to webkit style and to be consistent with ellipseYIntercept()
(WebCore::ellipseYIntercept): Compute an ellipse's Y intercept for an X coordinate.
(WebCore::ExclusionRectangle::firstIncludedIntervalLogicalTop): See the description above.
* rendering/ExclusionRectangle.h:
* rendering/ExclusionShape.h:
(ExclusionShape):
(WebCore::ExclusionShape::logicalTopForMinY): Internal to logical coordinate conversion.
* rendering/ExclusionShapeInsideInfo.cpp:
(WebCore::ExclusionShapeInsideInfo::adjustLogicalLineTop): A new method that updates m_lineTop with firstIncludedIntervalPosition().
* rendering/ExclusionShapeInsideInfo.h:
(ExclusionShapeInsideInfo):
(WebCore::ExclusionShapeInsideInfo::logicalLineTop): This is just a cover for the private m_lineTop field.
* rendering/RenderBlockLineLayout.cpp:
(WebCore::RenderBlock::layoutRunsAndFloatsInRange): Added code that restarts the layout loop if it's necessary to adjust the line's logicalTop.
(WebCore::RenderBlock::restartLayoutRunsAndFloatsInRange): Factored newly common code into this helper function.

LayoutTests:

Test the rounded rectangle support for adjusting the top of a line downwards
when the first word doesn't fit within the shape.

Patch by Hans Muller <[email protected]> on 2012-12-06
Reviewed by Levi Weintraub.

* fast/exclusions/shape-inside/shape-inside-rounded-rectangle-fit-001-expected.html: Added.
* fast/exclusions/shape-inside/shape-inside-rounded-rectangle-fit-001.html: Added.
* fast/exclusions/shape-inside/shape-inside-rounded-rectangle-fit-002-expected.html: Added.
* fast/exclusions/shape-inside/shape-inside-rounded-rectangle-fit-002.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (136856 => 136857)


--- trunk/LayoutTests/ChangeLog	2012-12-06 18:59:27 UTC (rev 136856)
+++ trunk/LayoutTests/ChangeLog	2012-12-06 19:05:15 UTC (rev 136857)
@@ -1,3 +1,18 @@
+2012-12-06  Hans Muller  <[email protected]>
+
+        [CSS Exclusions] Add support for computing the first included interval position.
+        https://bugs.webkit.org/show_bug.cgi?id=103327
+
+        Test the rounded rectangle support for adjusting the top of a line downwards
+        when the first word doesn't fit within the shape.
+
+        Reviewed by Levi Weintraub.
+
+        * fast/exclusions/shape-inside/shape-inside-rounded-rectangle-fit-001-expected.html: Added.
+        * fast/exclusions/shape-inside/shape-inside-rounded-rectangle-fit-001.html: Added.
+        * fast/exclusions/shape-inside/shape-inside-rounded-rectangle-fit-002-expected.html: Added.
+        * fast/exclusions/shape-inside/shape-inside-rounded-rectangle-fit-002.html: Added.
+
 2012-12-06  Stephen Chenney  <[email protected]>
 
         Rebaseline some expectations

Added: trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-rounded-rectangle-fit-001-expected.html (0 => 136857)


--- trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-rounded-rectangle-fit-001-expected.html	                        (rev 0)
+++ trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-rounded-rectangle-fit-001-expected.html	2012-12-06 19:05:15 UTC (rev 136857)
@@ -0,0 +1,44 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+    if (window.internals)
+        window.internals.settings.setCSSExclusionsEnabled(true);
+</script>
+<style>
+.shape-container {
+    position: relative;
+    width: 400px;
+    height: 20px;
+    margin: 10px;
+}
+
+.shape-background {
+    position: absolute;
+    top: 0px;
+    left: 0px;
+    width: 400px;
+    height: 200px;
+    border-radius: 200px / 50px;
+    background-color: rgb(200,200,200);
+}
+
+.shape-inside {
+    position: absolute;
+    top: 50px;
+    left: 0px;
+    width: 400px;
+    height: 200px;
+    font: 50px/1 Ahem, sans-serif;
+    color: green;
+}
+</style>
+</head>
+<body>
+<p>The green rectangle should appear just below the grey rounded rectangle's upper corners.</p>
+<div class="shape-container">
+  <div class="shape-background"></div>
+  <div class="shape-inside">XXXXXXXX</div>
+</div>
+</body>
+</html>

Added: trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-rounded-rectangle-fit-001.html (0 => 136857)


--- trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-rounded-rectangle-fit-001.html	                        (rev 0)
+++ trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-rounded-rectangle-fit-001.html	2012-12-06 19:05:15 UTC (rev 136857)
@@ -0,0 +1,45 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+    if (window.internals)
+        window.internals.settings.setCSSExclusionsEnabled(true);
+</script>
+<style>
+.shape-container {
+    position: relative;
+    width: 400px;
+    height: 20px;
+    margin: 10px;
+}
+
+.shape-background {
+    position: absolute;
+    top: 0px;
+    left: 0px;
+    width: 400px;
+    height: 200px;
+    border-radius: 200px / 50px;
+    background-color: rgb(200,200,200);
+}
+
+.shape-inside {
+    position: absolute;
+    top: 0px;
+    left: 0px;
+    width: 400px;
+    height: 200px;
+    -webkit-shape-inside: rectangle(0px, 0px, 400px, 200px, 200px, 50px);
+    font: 50px/1 Ahem, sans-serif;
+    color: green;
+}
+</style>
+</head>
+<body>
+<p>The green rectangle should appear just below the grey rounded rectangle's upper corners.</p>
+<div class="shape-container">
+  <div class="shape-background"></div>
+  <div class="shape-inside">XXXXXXXX</div>
+</div>
+</body>
+</html>

Added: trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-rounded-rectangle-fit-002-expected.html (0 => 136857)


--- trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-rounded-rectangle-fit-002-expected.html	                        (rev 0)
+++ trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-rounded-rectangle-fit-002-expected.html	2012-12-06 19:05:15 UTC (rev 136857)
@@ -0,0 +1,53 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+    if (window.internals)
+        window.internals.settings.setCSSExclusionsEnabled(true);
+</script>
+<!-- 
+In this test the shape-inside shape is a rounded rectangle configured as a circle with radius of 100px.
+The shape-inside element contains a single square Ahem font character that just fits wthin the circle. 
+That means that the character's size is sqrt(2)*100px, which is 141.41356px.
+
+The x and y coordinates of the points at which the square intersects the circle are half of the 
+difference between circle's diameter and the size of the square: (200px - sqrt(2)*100px) / 2 = 29.2893219px.
+-->
+<style>
+#shape-container {
+    position: relative;
+    display: inline-block;
+    width: 200px;
+    height: 200px;
+    margin: 10px;
+}
+
+#shape-background {
+    position: absolute;
+    top: 0px;
+    left: 0px;
+    width: 200px;
+    height: 200px;
+    border-radius:  100px / 100px;
+    background-color: rgb(200,200,200);
+}
+
+#shape-inside {
+    position: absolute;
+    top: 29.2893219px;
+    left: 29.2893219px;
+    width: 200px;
+    height: 200px;
+    font: 141.421356px/1 Ahem, sans-serif;
+    color: green;
+}
+</style>
+</head>
+<body>
+<p>The green rectangle should appear within the grey circle.</p>
+<div id="shape-container">
+  <div id="shape-background"></div>
+  <div id="shape-inside">X</div>
+</div>
+</body>
+</html>

Added: trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-rounded-rectangle-fit-002.html (0 => 136857)


--- trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-rounded-rectangle-fit-002.html	                        (rev 0)
+++ trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-rounded-rectangle-fit-002.html	2012-12-06 19:05:15 UTC (rev 136857)
@@ -0,0 +1,51 @@
+<!DOCTYPE html>
+<html>
+<head>
+<script>
+    if (window.internals)
+        window.internals.settings.setCSSExclusionsEnabled(true);
+</script>
+<!-- 
+In this test the shape-inside shape is a rounded rectangle configured as a circle with radius of 100px.
+The shape-inside element contains a single square Ahem font character that just fits wthin the circle. 
+That means that the character's size is sqrt(2)*100px, which is 141.41356px.
+-->
+<style>
+#shape-container {
+    position: relative;
+    display: inline-block;
+    width: 200px;
+    height: 200px;
+    margin: 10px;
+}
+
+#shape-background {
+    position: absolute;
+    top: 0px;
+    left: 0px;
+    width: 200px;
+    height: 200px;
+    border-radius:  100px / 100px;
+    background-color: rgb(200,200,200);
+}
+
+#shape-inside {
+    position: absolute;
+    top: 0px;
+    left: 0px;
+    width: 200px;
+    height: 200px;
+    -webkit-shape-inside: rectangle(0px, 0px, 200px, 200px, 100px, 100px);
+    font: 141.421356px/1 Ahem, sans-serif;
+    color: green;
+}
+</style>
+</head>
+<body>
+<p>The green rectangle should appear within the grey circle.</p>
+<div id="shape-container">
+  <div id="shape-background"></div>
+  <div id="shape-inside">X</div>
+</div>
+</body>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (136856 => 136857)


--- trunk/Source/WebCore/ChangeLog	2012-12-06 18:59:27 UTC (rev 136856)
+++ trunk/Source/WebCore/ChangeLog	2012-12-06 19:05:15 UTC (rev 136857)
@@ -1,3 +1,52 @@
+2012-12-06  Hans Muller  <[email protected]>
+
+        [CSS Exclusions] Add support for computing the first included interval position.
+        https://bugs.webkit.org/show_bug.cgi?id=103327
+
+        Reviewed by Levi Weintraub.
+
+        If the first "word" in a line doesn't fit within the shape-inside when lineTop
+        is the top of the shape's logical bounding box, adjust lineTop downwards to where
+        the word fits.  Currently only rounded rectangle shapes are supported.
+
+        Added ExclusionShape::firstIncludedIntervalLogicalTop(). The new virtual method
+        computes the topmost/leftmost location where a line segment with the specified
+        minLogicalIntervalSize will fit within the exclusion shape and returns the
+        corresponding logical Y coordinate.  The result is additionally constrained to
+        be at or below minLogicalIntervalTop. If the segment will not fit anywhere within
+        the shape, then false is returned.
+
+        During layout, minLogicalIntervalTop is the nominal top of the line being laid
+        out within the exclusion shape.
+
+        RenderBlock::layoutRunsAndFloatsInRange() now calls a new ExclusionShapeInsideInfo
+        method, adjustLogicalLineTop(), which uses firstIncludedIntervalLogicalTop() to
+        decide if the logical top of the line has to be moved downwards, for the first
+        word to fit within the exclusion shape.
+
+        Tests: fast/exclusions/shape-inside/shape-inside-rounded-rectangle-fit-001.html
+               fast/exclusions/shape-inside/shape-inside-rounded-rectangle-fit-002.html
+
+        * rendering/ExclusionPolygon.cpp:
+        (WebCore::ExclusionPolygon::firstIncludedIntervalLogicalTop): This is a stub implementation.
+        * rendering/ExclusionPolygon.h:
+        * rendering/ExclusionRectangle.cpp:
+        (WebCore::ellipseXIntercept): Added spaces to conform to webkit style and to be consistent with ellipseYIntercept()
+        (WebCore::ellipseYIntercept): Compute an ellipse's Y intercept for an X coordinate.
+        (WebCore::ExclusionRectangle::firstIncludedIntervalLogicalTop): See the description above.
+        * rendering/ExclusionRectangle.h:
+        * rendering/ExclusionShape.h:
+        (ExclusionShape):
+        (WebCore::ExclusionShape::logicalTopForMinY): Internal to logical coordinate conversion.
+        * rendering/ExclusionShapeInsideInfo.cpp:
+        (WebCore::ExclusionShapeInsideInfo::adjustLogicalLineTop): A new method that updates m_lineTop with firstIncludedIntervalPosition().
+        * rendering/ExclusionShapeInsideInfo.h:
+        (ExclusionShapeInsideInfo):
+        (WebCore::ExclusionShapeInsideInfo::logicalLineTop): This is just a cover for the private m_lineTop field.
+        * rendering/RenderBlockLineLayout.cpp:
+        (WebCore::RenderBlock::layoutRunsAndFloatsInRange): Added code that restarts the layout loop if it's necessary to adjust the line's logicalTop.
+        (WebCore::RenderBlock::restartLayoutRunsAndFloatsInRange): Factored newly common code into this helper function.
+
 2012-12-06  Ryosuke Niwa  <[email protected]>
 
         Use ownerNode() instead of base() in HTMLCollection

Modified: trunk/Source/WebCore/rendering/ExclusionPolygon.cpp (136856 => 136857)


--- trunk/Source/WebCore/rendering/ExclusionPolygon.cpp	2012-12-06 18:59:27 UTC (rev 136856)
+++ trunk/Source/WebCore/rendering/ExclusionPolygon.cpp	2012-12-06 19:05:15 UTC (rev 136857)
@@ -376,4 +376,20 @@
     }
 }
 
+bool ExclusionPolygon::firstIncludedIntervalLogicalTop(float minLogicalIntervalTop, const FloatSize& minLogicalIntervalSize, float& result) const
+{
+    // FIXME: This is just a temporary stub, https://bugs.webkit.org/show_bug.cgi?id=103429
+
+    if (minLogicalIntervalSize.width() > m_boundingBox.width())
+        return false;
+
+    float minY = minYForLogicalLine(minLogicalIntervalTop, minLogicalIntervalSize.height());
+    float maxY = maxYForLogicalLine(minLogicalIntervalTop, minLogicalIntervalSize.height());
+    if (minY < m_boundingBox.y() || maxY > m_boundingBox.maxY())
+        return false;
+
+    result = minLogicalIntervalTop;
+    return true;
+}
+
 } // namespace WebCore

Modified: trunk/Source/WebCore/rendering/ExclusionPolygon.h (136856 => 136857)


--- trunk/Source/WebCore/rendering/ExclusionPolygon.h	2012-12-06 18:59:27 UTC (rev 136856)
+++ trunk/Source/WebCore/rendering/ExclusionPolygon.h	2012-12-06 19:05:15 UTC (rev 136857)
@@ -66,6 +66,7 @@
     virtual bool isEmpty() const OVERRIDE { return m_empty; }
     virtual void getExcludedIntervals(float logicalTop, float logicalHeight, SegmentList&) const OVERRIDE;
     virtual void getIncludedIntervals(float logicalTop, float logicalHeight, SegmentList&) const OVERRIDE;
+    virtual bool firstIncludedIntervalLogicalTop(float minLogicalIntervalTop, const FloatSize& minLogicalIntervalSize, float&) const OVERRIDE;
 
 private:
     void computeXIntersections(float y, bool isMinY, Vector<ExclusionInterval>&) const;

Modified: trunk/Source/WebCore/rendering/ExclusionRectangle.cpp (136856 => 136857)


--- trunk/Source/WebCore/rendering/ExclusionRectangle.cpp	2012-12-06 18:59:27 UTC (rev 136856)
+++ trunk/Source/WebCore/rendering/ExclusionRectangle.cpp	2012-12-06 19:05:15 UTC (rev 136857)
@@ -37,9 +37,15 @@
 static inline float ellipseXIntercept(float y, float rx, float ry)
 {
     ASSERT(ry > 0);
-    return rx * sqrt(1 - (y*y) / (ry*ry));
+    return rx * sqrt(1 - (y * y) / (ry * ry));
 }
 
+static inline float ellipseYIntercept(float x, float rx, float ry)
+{
+    ASSERT(rx > 0);
+    return ry * sqrt(1 - (x * x) / (rx * rx));
+}
+
 void ExclusionRectangle::getExcludedIntervals(float logicalTop, float logicalHeight, SegmentList& result) const
 {
     if (isEmpty())
@@ -115,4 +121,55 @@
     result.append(LineSegment(x1, x2));
 }
 
+FloatPoint ExclusionRectangle::cornerInterceptForWidth(float width) const
+{
+    float xi = (m_width - width) / 2;
+    float yi = m_ry - ellipseYIntercept(m_rx - xi, m_rx, m_ry);
+    return FloatPoint(xi, yi);
+}
+
+bool ExclusionRectangle::firstIncludedIntervalLogicalTop(float minLogicalIntervalTop, const FloatSize& minLogicalIntervalSize, float& result) const
+{
+    if (minLogicalIntervalSize.width() > m_width)
+        return false;
+
+    float minY = std::max(m_y, minYForLogicalLine(minLogicalIntervalTop, minLogicalIntervalSize.height()));
+    float maxY = minY + minLogicalIntervalSize.height();
+    if (maxY > m_y + m_height)
+        return false;
+
+    bool intervalOverlapsMinCorner = minY < m_y + m_ry;
+    bool intervalOverlapsMaxCorner = maxY > m_y + m_height - m_ry;
+
+    if (!intervalOverlapsMinCorner && !intervalOverlapsMaxCorner) {
+        result = logicalTopForMinY(minY, minLogicalIntervalSize.height());
+        return true;
+    }
+
+    float centerY = m_y + m_height / 2;
+    bool minCornerDefinesX = fabs(centerY - minY) > fabs(centerY - maxY);
+    bool intervalFitsWithinCorners = minLogicalIntervalSize.width() + 2 * m_rx <= m_width;
+    FloatPoint cornerIntercept = cornerInterceptForWidth(minLogicalIntervalSize.width());
+
+    if (intervalOverlapsMinCorner && (!intervalOverlapsMaxCorner || minCornerDefinesX)) {
+        if (intervalFitsWithinCorners || m_y + cornerIntercept.y() < minY) {
+            result = logicalTopForMinY(minY, minLogicalIntervalSize.height());
+            return true;
+        }
+        if (minLogicalIntervalSize.height() < m_height - (2 * cornerIntercept.y())) {
+            result = logicalTopForMinY(m_y + cornerIntercept.y(), minLogicalIntervalSize.height());
+            return true;
+        }
+    }
+
+    if (intervalOverlapsMaxCorner && (!intervalOverlapsMinCorner || !minCornerDefinesX)) {
+        if (intervalFitsWithinCorners || minY <=  m_y + m_height - cornerIntercept.y() - minLogicalIntervalSize.height()) {
+            result = logicalTopForMinY(minY, minLogicalIntervalSize.height());
+            return true;
+        }
+    }
+
+    return false;
+}
+
 } // namespace WebCore

Modified: trunk/Source/WebCore/rendering/ExclusionRectangle.h (136856 => 136857)


--- trunk/Source/WebCore/rendering/ExclusionRectangle.h	2012-12-06 18:59:27 UTC (rev 136856)
+++ trunk/Source/WebCore/rendering/ExclusionRectangle.h	2012-12-06 19:05:15 UTC (rev 136857)
@@ -31,6 +31,7 @@
 #define ExclusionRectangle_h
 
 #include "ExclusionShape.h"
+#include "FloatPoint.h"
 #include "FloatSize.h"
 #include <wtf/Assertions.h>
 #include <wtf/Vector.h>
@@ -54,8 +55,11 @@
     virtual bool isEmpty() const OVERRIDE { return m_width <= 0 || m_height <= 0; }
     virtual void getExcludedIntervals(float logicalTop, float logicalHeight, SegmentList&) const OVERRIDE;
     virtual void getIncludedIntervals(float logicalTop, float logicalHeight, SegmentList&) const OVERRIDE;
+    virtual bool firstIncludedIntervalLogicalTop(float minLogicalIntervalTop, const FloatSize& minLogicalIntervalSize, float&) const OVERRIDE;
 
 private:
+    FloatPoint cornerInterceptForWidth(float width) const;
+
     float m_x;
     float m_y;
     float m_width;

Modified: trunk/Source/WebCore/rendering/ExclusionShape.h (136856 => 136857)


--- trunk/Source/WebCore/rendering/ExclusionShape.h	2012-12-06 18:59:27 UTC (rev 136856)
+++ trunk/Source/WebCore/rendering/ExclusionShape.h	2012-12-06 19:05:15 UTC (rev 136857)
@@ -67,11 +67,13 @@
     virtual bool isEmpty() const = 0;
     virtual void getIncludedIntervals(float logicalTop, float logicalHeight, SegmentList&) const = 0;
     virtual void getExcludedIntervals(float logicalTop, float logicalHeight, SegmentList&) const = 0;
+    virtual bool firstIncludedIntervalLogicalTop(float minLogicalIntervalTop, const FloatSize& minLogicalIntervalSize, float& result) const = 0;
 
 protected:
     float minYForLogicalLine(float logicalTop, float logicalHeight) const { return isFlippedBlocksWritingMode(m_writingMode) ? m_logicalBoxHeight - logicalTop - logicalHeight : logicalTop; }
     float maxYForLogicalLine(float logicalTop, float logicalHeight) const { return  isFlippedBlocksWritingMode(m_writingMode) ? m_logicalBoxHeight - logicalTop : logicalTop + logicalHeight; }
     FloatRect internalToLogicalBoundingBox(const FloatRect& r) const { return isFlippedBlocksWritingMode(m_writingMode) ? FloatRect(r.x(), m_logicalBoxHeight - r.maxY(), r.width(), r.height()) : r; }
+    float logicalTopForMinY(float minY, float logicalHeight) const { return isFlippedBlocksWritingMode(m_writingMode) ? m_logicalBoxHeight - minY - logicalHeight : minY; }
 
 private:
     WritingMode m_writingMode;

Modified: trunk/Source/WebCore/rendering/ExclusionShapeInsideInfo.cpp (136856 => 136857)


--- trunk/Source/WebCore/rendering/ExclusionShapeInsideInfo.cpp	2012-12-06 18:59:27 UTC (rev 136856)
+++ trunk/Source/WebCore/rendering/ExclusionShapeInsideInfo.cpp	2012-12-06 19:05:15 UTC (rev 136857)
@@ -118,5 +118,23 @@
     return m_segments.size();
 }
 
+bool ExclusionShapeInsideInfo::adjustLogicalLineTop(float minSegmentWidth)
+{
+    if (!m_shape || m_lineHeight <= 0 || m_lineTop > shapeLogicalBottom())
+        return false;
+
+    float floatNewLineTop;
+    if (m_shape->firstIncludedIntervalLogicalTop(m_lineTop, FloatSize(minSegmentWidth, m_lineHeight), floatNewLineTop)) {
+        // Use fromFloatCeil() to ensure that the returned LayoutUnit value is within the shape's bounds.
+        LayoutUnit newLineTop = LayoutUnit::fromFloatCeil(floatNewLineTop);
+        if (newLineTop > m_lineTop) {
+            m_lineTop = newLineTop;
+            return true;
+        }
+    }
+
+    return false;
 }
+
+}
 #endif

Modified: trunk/Source/WebCore/rendering/ExclusionShapeInsideInfo.h (136856 => 136857)


--- trunk/Source/WebCore/rendering/ExclusionShapeInsideInfo.h	2012-12-06 18:59:27 UTC (rev 136856)
+++ trunk/Source/WebCore/rendering/ExclusionShapeInsideInfo.h	2012-12-06 19:05:15 UTC (rev 136857)
@@ -89,9 +89,12 @@
         return &m_segments[m_segmentRanges.size()];
     }
     bool computeSegmentsForLine(LayoutUnit lineTop, LayoutUnit lineHeight);
+    bool adjustLogicalLineTop(float minSegmentWidth);
     void computeShapeSize(LayoutUnit logicalWidth, LayoutUnit logicalHeight);
     void dirtyShapeSize() { m_shapeSizeDirty = true; }
 
+    LayoutUnit logicalLineTop() const { return m_lineTop; }
+
 private:
     ExclusionShapeInsideInfo(RenderBlock*);
 

Modified: trunk/Source/WebCore/rendering/RenderBlock.h (136856 => 136857)


--- trunk/Source/WebCore/rendering/RenderBlock.h	2012-12-06 18:59:27 UTC (rev 136856)
+++ trunk/Source/WebCore/rendering/RenderBlock.h	2012-12-06 19:05:15 UTC (rev 136857)
@@ -995,6 +995,7 @@
     RootInlineBox* createLineBoxesFromBidiRuns(BidiRunList<BidiRun>&, const InlineIterator& end, LineInfo&, VerticalPositionCache&, BidiRun* trailingSpaceRun, WordMeasurements&);
     void layoutRunsAndFloats(LineLayoutState&, bool hasInlineChild);
     void layoutRunsAndFloatsInRange(LineLayoutState&, InlineBidiResolver&, const InlineIterator& cleanLineStart, const BidiStatus& cleanLineBidiStatus, unsigned consecutiveHyphenatedLines);
+    const InlineIterator& restartLayoutRunsAndFloatsInRange(LayoutUnit oldLogicalHeight, LayoutUnit newLogicalHeight,  FloatingObject* lastFloatFromPreviousLine, InlineBidiResolver&,  const InlineIterator&);
     void linkToEndLineIfNeeded(LineLayoutState&);
     static void repaintDirtyFloats(Vector<FloatWithRect>& floats);
 

Modified: trunk/Source/WebCore/rendering/RenderBlockLineLayout.cpp (136856 => 136857)


--- trunk/Source/WebCore/rendering/RenderBlockLineLayout.cpp	2012-12-06 18:59:27 UTC (rev 136856)
+++ trunk/Source/WebCore/rendering/RenderBlockLineLayout.cpp	2012-12-06 19:05:15 UTC (rev 136857)
@@ -1464,6 +1464,15 @@
 {
 }
 
+// Before restarting the layout loop with a new logicalHeight, remove all floats that were added and reset the resolver.
+inline const InlineIterator& RenderBlock::restartLayoutRunsAndFloatsInRange(LayoutUnit oldLogicalHeight, LayoutUnit newLogicalHeight,  FloatingObject* lastFloatFromPreviousLine, InlineBidiResolver& resolver,  const InlineIterator& oldEnd)
+{
+    removeFloatingObjectsBelow(lastFloatFromPreviousLine, oldLogicalHeight);
+    setLogicalHeight(newLogicalHeight);
+    resolver.setPositionIgnoringNestedIsolates(oldEnd);
+    return oldEnd;
+}
+
 void RenderBlock::layoutRunsAndFloatsInRange(LineLayoutState& layoutState, InlineBidiResolver& resolver, const InlineIterator& cleanLineStart, const BidiStatus& cleanLineBidiStatus, unsigned consecutiveHyphenatedLines)
 {
     RenderStyle* styleToUse = style();
@@ -1530,6 +1539,13 @@
         }
         ASSERT(end != resolver.position());
 
+#if ENABLE(CSS_EXCLUSIONS)
+        if (exclusionShapeInsideInfo && wordMeasurements.size() && exclusionShapeInsideInfo->adjustLogicalLineTop(wordMeasurements[0].width)) {
+            end = restartLayoutRunsAndFloatsInRange(logicalHeight(), exclusionShapeInsideInfo->logicalLineTop() - absoluteLogicalTop, lastFloatFromPreviousLine, resolver, oldEnd);
+            continue;
+        }
+#endif
+
         // This is a short-cut for empty lines.
         if (layoutState.lineInfo().isEmpty()) {
             if (lastRootBox())
@@ -1582,10 +1598,7 @@
                         if (availableLogicalWidthForLine(oldLogicalHeight + adjustment, layoutState.lineInfo().isFirstLine()) != oldLineWidth) {
                             // We have to delete this line, remove all floats that got added, and let line layout re-run.
                             lineBox->deleteLine(renderArena());
-                            removeFloatingObjectsBelow(lastFloatFromPreviousLine, oldLogicalHeight);
-                            setLogicalHeight(oldLogicalHeight + adjustment);
-                            resolver.setPositionIgnoringNestedIsolates(oldEnd);
-                            end = oldEnd;
+                            end = restartLayoutRunsAndFloatsInRange(oldLogicalHeight, oldLogicalHeight + adjustment, lastFloatFromPreviousLine, resolver, oldEnd);
                             continue;
                         }
 
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to