Title: [142164] trunk
Revision
142164
Author
[email protected]
Date
2013-02-07 12:50:21 -0800 (Thu, 07 Feb 2013)

Log Message

[CSS Exclusions] shape-inside does not properly handle padding or border
https://bugs.webkit.org/show_bug.cgi?id=102715

Patch by Bear Travis <[email protected]> on 2013-02-07
Reviewed by David Hyatt.

Source/WebCore:

This patch positions the exclusion shape based on the value of the css box sizing
property. Geometry calculations happen in the shape coordinate space. For layout,
these coordinates are translated to the border-box coordinate system by adding
the appropriate offsets.

Test: fast/exclusions/shape-inside/shape-inside-box-sizing.html

* rendering/ExclusionShapeInfo.cpp:
(WebCore::::computedShape): Pass m_shapeLogicalWidth to the exclusion shape
geometry code.
* rendering/ExclusionShapeInfo.h:
(WebCore::ExclusionShapeInfo::setShapeSize): Adjust block layout dimensions to
shape dimensions when checking to see if the shape geometry must be recalculated.
(WebCore::ExclusionShapeInfo::shapeLogicalTop): Account for layout offsets.
(WebCore::ExclusionShapeInfo::shapeLogicalBottom): Ditto.
(WebCore::ExclusionShapeInfo::shapeLogicalLeft): Ditto.
(WebCore::ExclusionShapeInfo::shapeLogicalRight): Ditto.
(WebCore::ExclusionShapeInfo::logicalTopOffset): Return the offset from the logical
top of the border box to the logical top of the shape.
(WebCore::ExclusionShapeInfo::logicalLeftOffset): Return the offset from the logical
left of the border box to the logical left of the shape.
(ExclusionShapeInfo):
* rendering/ExclusionShapeInsideInfo.cpp:
(WebCore::ExclusionShapeInsideInfo::computeSegmentsForLine): Adjust line top to
be in shape coordinates.
(WebCore::ExclusionShapeInsideInfo::adjustLogicalLineTop): Ditto.
* rendering/ExclusionShapeInsideInfo.h:
(WebCore::ExclusionShapeInsideInfo::lineOverlapsShapeBounds): Use consistent
coordinate system (border box) to test for whether a line overlaps a shape.
(WebCore::ExclusionShapeInsideInfo::logicalLineTop): Include the logical offset
from the border box.
(WebCore::ExclusionShapeInsideInfo::logicalLineBottom): Ditto.

LayoutTests:

Test that borders and padding are properly accounted for when laying out text in
a shape inside.

* fast/exclusions/shape-inside/shape-inside-bottom-edge.html: Modified to no longer
use padding.
* fast/exclusions/shape-inside/shape-inside-box-sizing-expected.html: Added.
* fast/exclusions/shape-inside/shape-inside-box-sizing.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (142163 => 142164)


--- trunk/LayoutTests/ChangeLog	2013-02-07 20:35:09 UTC (rev 142163)
+++ trunk/LayoutTests/ChangeLog	2013-02-07 20:50:21 UTC (rev 142164)
@@ -1,3 +1,18 @@
+2013-02-07  Bear Travis  <[email protected]>
+
+        [CSS Exclusions] shape-inside does not properly handle padding or border
+        https://bugs.webkit.org/show_bug.cgi?id=102715
+
+        Reviewed by David Hyatt.
+
+        Test that borders and padding are properly accounted for when laying out text in
+        a shape inside.
+
+        * fast/exclusions/shape-inside/shape-inside-bottom-edge.html: Modified to no longer
+        use padding.
+        * fast/exclusions/shape-inside/shape-inside-box-sizing-expected.html: Added.
+        * fast/exclusions/shape-inside/shape-inside-box-sizing.html: Added.
+
 2013-01-27  Robert Hogan  <[email protected]>
 
         CSS 2.1 failure: floats-149 fails

Modified: trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-bottom-edge.html (142163 => 142164)


--- trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-bottom-edge.html	2013-02-07 20:35:09 UTC (rev 142163)
+++ trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-bottom-edge.html	2013-02-07 20:50:21 UTC (rev 142164)
@@ -28,16 +28,21 @@
 
 #shape-inside-no-overlap {
     top: 0px;
-    padding-top: 150px;
 }
-
+#shape-inside-no-overlap::before, #shape-inside-overlap::before {
+    display: block;
+    height: 150px;
+    content: ' ';
+}
+#shape-inside-overlap::before {
+    height: 149.9px;
+}
 #shape-background-overlap {
     top: 250px;
 }
 
 #shape-inside-overlap {
     top: 200px;
-    padding-top: 149.9px;
 }
 </style>
 </head>

Added: trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-box-sizing-expected.html (0 => 142164)


--- trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-box-sizing-expected.html	                        (rev 0)
+++ trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-box-sizing-expected.html	2013-02-07 20:50:21 UTC (rev 142164)
@@ -0,0 +1,88 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <style>
+    .border {
+        border-left: 5px solid blue;
+        border-top: 10px solid blue;
+        border-right: 15px solid blue;
+        border-bottom: 20px solid blue;
+        padding: 10px 15px 20px 5px;
+        width: 30px;
+        height: 40px;
+        border-style: solid;
+    }
+    .padding {
+        padding: 20px 30px 40px 10px;
+    }
+    .border-box {
+        -webkit-box-sizing: border-box;
+    }
+    .border-box.border {
+        width: 70px;
+        height: 100px;
+    }
+    .border-box.border.padding {
+        width: 90px;
+        height: 130px;
+    }
+    .shape-inside {
+        font-family: Ahem, sans-serif;
+        font-size: 10px;
+        color: green;
+    }
+    .vertical-lr {
+        -webkit-writing-mode: vertical-lr;
+    }
+    .vertical-rl {
+        -webkit-writing-mode: vertical-rl;
+    }
+    .horizontal-tb {
+        -webkit-writing-mode: horizontal-tb;
+    }
+    </style>
+</head>
+<body>
+    <p>These tests check that shape inside correctly offsets from the correct box-sizing box. They require the Ahem font.</p>
+    <p>The following tests check writing modes on a box with a 5 10 15 20px blue border, and 5 10 15 20px shape offsets.</p>
+    <div class='border shape-inside horizontal-tb'>
+    xxx xxx xxx xxx
+    </div>
+    <div class='border shape-inside vertical-lr'>
+        xxxx xxxx xxxx
+    </div>
+    <div class='border shape-inside vertical-rl'>
+        xxxx xxxx xxxx
+    </div>
+    <p>The following tests should look the same, but use box-sizing: border-box.</p>
+    <div class='border-box border shape-inside horizontal-tb'>
+    xxx xxx xxx xxx
+    </div>
+    <div class='border-box border shape-inside vertical-lr'>
+        xxxx xxxx xxxx
+    </div>
+    <div class='border-box border shape-inside vertical-rl'>
+        xxxx xxxx xxxx
+    </div>
+    <p>The following tests add 5 10 15 20px of padding.</p>
+    <div class='border padding shape-inside horizontal-tb'>
+    xxx xxx xxx xxx
+    </div>
+    <div class='border padding shape-inside vertical-lr'>
+        xxxx xxxx xxxx
+    </div>
+    <div class='border padding shape-inside vertical-rl'>
+        xxxx xxxx xxxx
+    </div>
+    <p>The following tests should look the same, but use box-sizing: border-box.</p>
+    <div class='border-box border padding shape-inside horizontal-tb'>
+    xxx xxx xxx xxx
+    </div>
+    <div class='border-box border padding shape-inside vertical-lr'>
+        xxxx xxxx xxxx
+    </div>
+    <div class='border-box border padding shape-inside vertical-rl'>
+        xxxx xxxx xxxx
+    </div>
+</body>
+</html>
\ No newline at end of file

Added: trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-box-sizing.html (0 => 142164)


--- trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-box-sizing.html	                        (rev 0)
+++ trunk/LayoutTests/fast/exclusions/shape-inside/shape-inside-box-sizing.html	2013-02-07 20:50:21 UTC (rev 142164)
@@ -0,0 +1,98 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <script>
+    if (window.internals)
+        window.internals.settings.setCSSExclusionsEnabled(true);
+    </script>
+    <style>
+    .border {
+        border-left: 5px solid blue;
+        border-top: 10px solid blue;
+        border-right: 15px solid blue;
+        border-bottom: 20px solid blue;
+        width: 50px;
+        height: 70px;
+        border-style: solid;
+    }
+    .padding {
+        padding: 10px 15px 20px 5px;
+    }
+    .border-box {
+        -webkit-box-sizing: border-box;
+    }
+    .border-box.border {
+        width: 70px;
+        height: 100px;
+    }
+    .border-box.border.padding {
+        width: 90px;
+        height: 130px;
+    }
+    .shape-inside {
+        -webkit-shape-inside: rectangle(5px, 10px, 30px, 40px);
+        font-family: Ahem, sans-serif;
+        font-size: 10px;
+        color: green;
+    }
+    .border-box.shape-inside {
+        -webkit-shape-inside: rectangle(10px, 20px, 30px, 40px);
+    }
+    .border-box.border.padding.shape-inside {
+        -webkit-shape-inside: rectangle(15px, 30px, 30px, 40px);
+    }
+    .vertical-lr {
+        -webkit-writing-mode: vertical-lr;
+    }
+    .vertical-rl {
+        -webkit-writing-mode: vertical-rl;
+    }
+    .horizontal-tb {
+        -webkit-writing-mode: horizontal-tb;
+    }
+    </style>
+</head>
+<body>
+    <p>These tests check that shape inside correctly offsets from the correct box-sizing box. They require the Ahem font.</p>
+    <p>The following tests check writing modes on a box with a 5 10 15 20px blue border, and 5 10 15 20px shape offsets.</p>
+    <div class='border shape-inside horizontal-tb'>
+    xxx xxx xxx xxx
+    </div>
+    <div class='border shape-inside vertical-lr'>
+        xxxx xxxx xxxx
+    </div>
+    <div class='border shape-inside vertical-rl'>
+        xxxx xxxx xxxx
+    </div>
+    <p>The following tests should look the same, but use box-sizing: border-box.</p>
+    <div class='border-box border shape-inside horizontal-tb'>
+    xxx xxx xxx xxx
+    </div>
+    <div class='border-box border shape-inside vertical-lr'>
+        xxxx xxxx xxxx
+    </div>
+    <div class='border-box border shape-inside vertical-rl'>
+        xxxx xxxx xxxx
+    </div>
+    <p>The following tests add 5 10 15 20px of padding.</p>
+    <div class='border padding shape-inside horizontal-tb'>
+    xxx xxx xxx xxx
+    </div>
+    <div class='border padding shape-inside vertical-lr'>
+        xxxx xxxx xxxx
+    </div>
+    <div class='border padding shape-inside vertical-rl'>
+        xxxx xxxx xxxx
+    </div>
+    <p>The following tests should look the same, but use box-sizing: border-box.</p>
+    <div class='border-box border padding shape-inside horizontal-tb'>
+    xxx xxx xxx xxx
+    </div>
+    <div class='border-box border padding shape-inside vertical-lr'>
+        xxxx xxxx xxxx
+    </div>
+    <div class='border-box border padding shape-inside vertical-rl'>
+        xxxx xxxx xxxx
+    </div>
+</body>
+</html>
\ No newline at end of file

Modified: trunk/Source/WebCore/ChangeLog (142163 => 142164)


--- trunk/Source/WebCore/ChangeLog	2013-02-07 20:35:09 UTC (rev 142163)
+++ trunk/Source/WebCore/ChangeLog	2013-02-07 20:50:21 UTC (rev 142164)
@@ -1,3 +1,43 @@
+2013-02-07  Bear Travis  <[email protected]>
+
+        [CSS Exclusions] shape-inside does not properly handle padding or border
+        https://bugs.webkit.org/show_bug.cgi?id=102715
+
+        Reviewed by David Hyatt.
+
+        This patch positions the exclusion shape based on the value of the css box sizing
+        property. Geometry calculations happen in the shape coordinate space. For layout,
+        these coordinates are translated to the border-box coordinate system by adding
+        the appropriate offsets.
+
+        Test: fast/exclusions/shape-inside/shape-inside-box-sizing.html
+
+        * rendering/ExclusionShapeInfo.cpp:
+        (WebCore::::computedShape): Pass m_shapeLogicalWidth to the exclusion shape
+        geometry code.
+        * rendering/ExclusionShapeInfo.h:
+        (WebCore::ExclusionShapeInfo::setShapeSize): Adjust block layout dimensions to
+        shape dimensions when checking to see if the shape geometry must be recalculated.
+        (WebCore::ExclusionShapeInfo::shapeLogicalTop): Account for layout offsets.
+        (WebCore::ExclusionShapeInfo::shapeLogicalBottom): Ditto.
+        (WebCore::ExclusionShapeInfo::shapeLogicalLeft): Ditto.
+        (WebCore::ExclusionShapeInfo::shapeLogicalRight): Ditto.
+        (WebCore::ExclusionShapeInfo::logicalTopOffset): Return the offset from the logical
+        top of the border box to the logical top of the shape.
+        (WebCore::ExclusionShapeInfo::logicalLeftOffset): Return the offset from the logical
+        left of the border box to the logical left of the shape.
+        (ExclusionShapeInfo):
+        * rendering/ExclusionShapeInsideInfo.cpp:
+        (WebCore::ExclusionShapeInsideInfo::computeSegmentsForLine): Adjust line top to
+        be in shape coordinates.
+        (WebCore::ExclusionShapeInsideInfo::adjustLogicalLineTop): Ditto.
+        * rendering/ExclusionShapeInsideInfo.h:
+        (WebCore::ExclusionShapeInsideInfo::lineOverlapsShapeBounds): Use consistent
+        coordinate system (border box) to test for whether a line overlaps a shape.
+        (WebCore::ExclusionShapeInsideInfo::logicalLineTop): Include the logical offset
+        from the border box.
+        (WebCore::ExclusionShapeInsideInfo::logicalLineBottom): Ditto.
+
 2013-02-07  Benjamin Poulain  <[email protected]>
 
         Upstream iOS isWebThread() and isUIThread()

Modified: trunk/Source/WebCore/rendering/ExclusionShapeInfo.cpp (142163 => 142164)


--- trunk/Source/WebCore/rendering/ExclusionShapeInfo.cpp	2013-02-07 20:35:09 UTC (rev 142163)
+++ trunk/Source/WebCore/rendering/ExclusionShapeInfo.cpp	2013-02-07 20:50:21 UTC (rev 142164)
@@ -49,7 +49,7 @@
 
     ASSERT(shape);
 
-    m_shape = ExclusionShape::createExclusionShape(shape, m_logicalWidth, m_logicalHeight, m_renderer->style()->writingMode());
+    m_shape = ExclusionShape::createExclusionShape(shape, m_shapeLogicalWidth, m_shapeLogicalHeight, m_renderer->style()->writingMode());
     ASSERT(m_shape);
     return m_shape.get();
 }

Modified: trunk/Source/WebCore/rendering/ExclusionShapeInfo.h (142163 => 142164)


--- trunk/Source/WebCore/rendering/ExclusionShapeInfo.h	2013-02-07 20:35:09 UTC (rev 142163)
+++ trunk/Source/WebCore/rendering/ExclusionShapeInfo.h	2013-02-07 20:50:21 UTC (rev 142164)
@@ -72,17 +72,22 @@
 
     void setShapeSize(LayoutUnit logicalWidth, LayoutUnit logicalHeight)
     {
-        if (m_logicalWidth == logicalWidth && m_logicalHeight == logicalHeight)
+        if (m_renderer->style()->boxSizing() == CONTENT_BOX) {
+            logicalWidth -= m_renderer->borderAndPaddingLogicalWidth();
+            logicalHeight -= m_renderer->borderAndPaddingLogicalHeight();
+        }
+
+        if (m_shapeLogicalWidth == logicalWidth && m_shapeLogicalHeight == logicalHeight)
             return;
         dirtyShapeSize();
-        m_logicalWidth = logicalWidth;
-        m_logicalHeight = logicalHeight;
+        m_shapeLogicalWidth = logicalWidth;
+        m_shapeLogicalHeight = logicalHeight;
     }
 
-    LayoutUnit shapeLogicalTop() const { return floatLogicalTopToLayoutUnit(computedShape()->shapeLogicalBoundingBox().y()); }
-    LayoutUnit shapeLogicalBottom() const { return floatLogicalBottomToLayoutUnit(computedShape()->shapeLogicalBoundingBox().maxY()); }
-    LayoutUnit shapeLogicalLeft() const { return computedShape()->shapeLogicalBoundingBox().x(); }
-    LayoutUnit shapeLogicalRight() const { return computedShape()->shapeLogicalBoundingBox().y(); }
+    LayoutUnit shapeLogicalTop() const { return floatLogicalTopToLayoutUnit(computedShape()->shapeLogicalBoundingBox().y()) + logicalTopOffset(); }
+    LayoutUnit shapeLogicalBottom() const { return floatLogicalBottomToLayoutUnit(computedShape()->shapeLogicalBoundingBox().maxY()) + logicalTopOffset(); }
+    LayoutUnit shapeLogicalLeft() const { return computedShape()->shapeLogicalBoundingBox().x() + logicalLeftOffset(); }
+    LayoutUnit shapeLogicalRight() const { return computedShape()->shapeLogicalBoundingBox().y() + logicalLeftOffset(); }
     LayoutUnit shapeLogicalWidth() const { return computedShape()->shapeLogicalBoundingBox().width(); }
     LayoutUnit shapeLogicalHeight() const { return computedShape()->shapeLogicalBoundingBox().height(); }
 
@@ -98,11 +103,14 @@
     LayoutUnit floatLogicalTopToLayoutUnit(float logicalTop) const { return LayoutUnit::fromFloatCeil(logicalTop); }
     LayoutUnit floatLogicalBottomToLayoutUnit(float logicalBottom) const { return LayoutUnit::fromFloatFloor(logicalBottom); }
 
+    LayoutUnit logicalTopOffset() const { return m_renderer->style()->boxSizing() == CONTENT_BOX ? m_renderer->borderBefore() + m_renderer->paddingBefore() : LayoutUnit(); }
+    LayoutUnit logicalLeftOffset() const { return m_renderer->style()->boxSizing() == CONTENT_BOX ? m_renderer->borderStart() + m_renderer->paddingStart() : LayoutUnit(); }
+
 private:
     mutable OwnPtr<ExclusionShape> m_shape;
 
-    LayoutUnit m_logicalWidth;
-    LayoutUnit m_logicalHeight;
+    LayoutUnit m_shapeLogicalWidth;
+    LayoutUnit m_shapeLogicalHeight;
     const RenderType* m_renderer;
 };
 }

Modified: trunk/Source/WebCore/rendering/ExclusionShapeInsideInfo.cpp (142163 => 142164)


--- trunk/Source/WebCore/rendering/ExclusionShapeInsideInfo.cpp	2013-02-07 20:35:09 UTC (rev 142163)
+++ trunk/Source/WebCore/rendering/ExclusionShapeInsideInfo.cpp	2013-02-07 20:50:21 UTC (rev 142164)
@@ -38,13 +38,18 @@
 bool ExclusionShapeInsideInfo::computeSegmentsForLine(LayoutUnit lineTop, LayoutUnit lineHeight)
 {
     ASSERT(lineHeight >= 0);
-    m_lineTop = lineTop;
+    m_shapeLineTop = lineTop - logicalTopOffset();
     m_lineHeight = lineHeight;
     m_segments.clear();
     m_segmentRanges.clear();
 
-    if (lineOverlapsShapeBounds()) {
-        computedShape()->getIncludedIntervals(lineTop, std::min(lineHeight, shapeLogicalBottom() - lineTop), m_segments);
+    if (lineOverlapsShapeBounds())
+        computedShape()->getIncludedIntervals(m_shapeLineTop, std::min(m_lineHeight, shapeLogicalBottom() - lineTop), m_segments);
+
+    LayoutUnit logicalLeftOffset = this->logicalLeftOffset();
+    for (size_t i = 0; i < m_segments.size(); i++) {
+        m_segments[i].logicalLeft += logicalLeftOffset;
+        m_segments[i].logicalRight += logicalLeftOffset;
     }
     return m_segments.size();
 }
@@ -52,14 +57,14 @@
 bool ExclusionShapeInsideInfo::adjustLogicalLineTop(float minSegmentWidth)
 {
     const ExclusionShape* shape = computedShape();
-    if (!shape || m_lineHeight <= 0 || m_lineTop > shapeLogicalBottom())
+    if (!shape || m_lineHeight <= 0 || logicalLineTop() > shapeLogicalBottom())
         return false;
 
     float floatNewLineTop;
-    if (shape->firstIncludedIntervalLogicalTop(m_lineTop, FloatSize(minSegmentWidth, m_lineHeight), floatNewLineTop)) {
+    if (shape->firstIncludedIntervalLogicalTop(m_shapeLineTop, FloatSize(minSegmentWidth, m_lineHeight), floatNewLineTop)) {
         LayoutUnit newLineTop = floatLogicalTopToLayoutUnit(floatNewLineTop);
-        if (newLineTop > m_lineTop) {
-            m_lineTop = newLineTop;
+        if (newLineTop > m_shapeLineTop) {
+            m_shapeLineTop = newLineTop;
             return true;
         }
     }

Modified: trunk/Source/WebCore/rendering/ExclusionShapeInsideInfo.h (142163 => 142164)


--- trunk/Source/WebCore/rendering/ExclusionShapeInsideInfo.h	2013-02-07 20:35:09 UTC (rev 142163)
+++ trunk/Source/WebCore/rendering/ExclusionShapeInsideInfo.h	2013-02-07 20:50:21 UTC (rev 142164)
@@ -63,7 +63,7 @@
         BasicShape* shape = (shapeValue && shapeValue->type() == ExclusionShapeValue::SHAPE) ? shapeValue->shape() : 0;
         return shape && (shape->type() == BasicShape::BASIC_SHAPE_RECTANGLE || shape->type() == BasicShape::BASIC_SHAPE_POLYGON);
     }
-    bool lineOverlapsShapeBounds() const { return m_lineTop < shapeLogicalBottom() && m_lineTop + m_lineHeight >= shapeLogicalTop(); }
+    bool lineOverlapsShapeBounds() const { return logicalLineTop() < shapeLogicalBottom() && logicalLineBottom() >= shapeLogicalTop(); }
 
     bool hasSegments() const
     {
@@ -85,12 +85,13 @@
     }
     bool computeSegmentsForLine(LayoutUnit lineTop, LayoutUnit lineHeight);
     bool adjustLogicalLineTop(float minSegmentWidth);
-    LayoutUnit logicalLineTop() const { return m_lineTop; }
+    LayoutUnit logicalLineTop() const { return m_shapeLineTop + logicalTopOffset(); }
+    LayoutUnit logicalLineBottom() const { return m_shapeLineTop + m_lineHeight + logicalTopOffset(); }
 
 private:
     ExclusionShapeInsideInfo(const RenderBlock* renderer) : ExclusionShapeInfo<RenderBlock, &RenderStyle::shapeInside>(renderer) { }
 
-    LayoutUnit m_lineTop;
+    LayoutUnit m_shapeLineTop;
     LayoutUnit m_lineHeight;
 
     SegmentList m_segments;
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to