Diff
Modified: trunk/LayoutTests/ChangeLog (155001 => 155002)
--- trunk/LayoutTests/ChangeLog 2013-09-03 22:08:49 UTC (rev 155001)
+++ trunk/LayoutTests/ChangeLog 2013-09-03 22:14:51 UTC (rev 155002)
@@ -1,3 +1,16 @@
+2013-09-03 Bear Travis <betra...@adobe.com>
+
+ [CSS Shapes] Shape's content gets extra left offset when left-border is positive on the content box
+ https://bugs.webkit.org/show_bug.cgi?id=117573
+
+ Reviewed by David Hyatt.
+
+ Test that nested children with padding correctly apply an ancestor's shape-inside
+ across different writing modes.
+
+ * fast/shapes/shape-inside/shape-inside-offset-block-children-expected.html: Added.
+ * fast/shapes/shape-inside/shape-inside-offset-block-children.html: Added.
+
2013-09-03 Antoine Quint <grao...@apple.com>
Web Inspector: exceptions triggered from console evaluation do not pause the debugger
Added: trunk/LayoutTests/fast/shapes/shape-inside/shape-inside-offset-block-children-expected.html (0 => 155002)
--- trunk/LayoutTests/fast/shapes/shape-inside/shape-inside-offset-block-children-expected.html (rev 0)
+++ trunk/LayoutTests/fast/shapes/shape-inside/shape-inside-offset-block-children-expected.html 2013-09-03 22:14:51 UTC (rev 155002)
@@ -0,0 +1,33 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style id='stylesheet'>
+.shape-inside {
+ font: 50px/1 Ahem, sans-serif;
+ color: green;
+ float: left;
+}
+</style>
+<script src=''></script>
+<script>
+ ids = [
+ 'shape-inside',
+ 'shape-inside-rl',
+ 'shape-inside-lr',
+ 'shape-inside-tb-lr-tb',
+ 'shape-inside-lr-rl-lr'
+ ];
+ ids.forEach(function(id) {
+ drawExpectedRectangle(id, 'stylesheet', { width: 300, height: 300 }, { x: 100, y: 100, width: 100, height: 100 }, 'px', null);
+ });
+</script>
+</head>
+<body>
+<p>This test ensures that shape-inside takes into account padding on nested child blocks in different writing modes. You should see several green squares within a blue outline. The test requires the Ahem font.</p>
+<div id='shape-inside' class='shape-inside'>xxxx</div>
+<div id='shape-inside-rl' class='shape-inside'>xxxx</div>
+<div id='shape-inside-lr' class='shape-inside'>xxxx</div>
+<div id='shape-inside-tb-lr-tb' class='shape-inside'>xxxx</div>
+<div id='shape-inside-lr-rl-lr' class='shape-inside'>xxxx</div>
+</body>
+</html>
Added: trunk/LayoutTests/fast/shapes/shape-inside/shape-inside-offset-block-children.html (0 => 155002)
--- trunk/LayoutTests/fast/shapes/shape-inside/shape-inside-offset-block-children.html (rev 0)
+++ trunk/LayoutTests/fast/shapes/shape-inside/shape-inside-offset-block-children.html 2013-09-03 22:14:51 UTC (rev 155002)
@@ -0,0 +1,47 @@
+<!DOCTYPE html>
+<html>
+<head>
+<style id='stylesheet'>
+.shape-inside {
+ font: 50px/1 Ahem, sans-serif;
+ color: green;
+ float: left;
+}
+.horizontal.tb {
+ -webkit-writing-mode: horizontal-tb;
+}
+.vertical.rl {
+ -webkit-writing-mode: vertical-rl;
+}
+.vertical.lr {
+ -webkit-writing-mode: vertical-lr;
+}
+.shape-inside * {
+ padding: 5px 10px 15px 20px;
+}
+</style>
+<script src=''></script>
+<script>
+window._onload_ = function() {
+ ids = [
+ 'shape-inside',
+ 'shape-inside-rl',
+ 'shape-inside-lr',
+ 'shape-inside-tb-lr-tb',
+ 'shape-inside-lr-rl-lr'
+ ];
+ ids.forEach(function(id) {
+ drawTextRectangle(id, 'stylesheet', { width: 300, height: 300 }, { x: 100, y: 100, width: 100, height: 100 }, 'px', null);
+ });
+}
+</script>
+</head>
+<body>
+<p>This test ensures that shape-inside takes into account padding on nested child blocks in different writing modes. You should see several green squares within a blue outline. The test requires the Ahem font.</p>
+<div id='shape-inside' class='shape-inside'><div><div>xxxx</div></div></div>
+<div id='shape-inside-rl' class='shape-inside vertical lr'><div><div>xxxx</div></div></div>
+<div id='shape-inside-lr' class='shape-inside vertical rl'><div><div>xxxx</div></div></div>
+<div id='shape-inside-tb-lr-tb' class='shape-inside'><div class='vertical lr'><div class='horizontal tb'>xxxx</div></div></div>
+<div id='shape-inside-lr-rl-lr' class='shape-inside vertical rl'><div class='vertical lr'><div class='vertical rl'>xxxx</div></div></div>
+</body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (155001 => 155002)
--- trunk/Source/WebCore/ChangeLog 2013-09-03 22:08:49 UTC (rev 155001)
+++ trunk/Source/WebCore/ChangeLog 2013-09-03 22:14:51 UTC (rev 155002)
@@ -1,3 +1,34 @@
+2013-09-03 Bear Travis <betra...@adobe.com>
+
+ [CSS Shapes] Shape's content gets extra left offset when left-border is positive on the content box
+ https://bugs.webkit.org/show_bug.cgi?id=117573
+
+ Reviewed by David Hyatt.
+
+ Nested blocks need to take into account their offset from the shape-inside container.
+ The new code calculates the offset from the shape-inside container, then applies the
+ offset to the computed segments. The line must be moved down by the offset's height,
+ and each segment must be moved left by the offset's width.
+
+ Test: fast/shapes/shape-inside/shape-inside-offset-block-children.html
+
+ * rendering/RenderBlock.cpp:
+ (WebCore::RenderBlock::relayoutShapeDescendantIfMoved): Relayout a block child if its
+ new logical left would cause it to rest at a new position within a shape container.
+ (WebCore::RenderBlock::logicalOffsetFromShapeAncestorContainer): Calculate the logical
+ offset form a shape inside ancestor container.
+ (WebCore::RenderBlock::layoutBlockChild): Call relayoutShapeDescendantIfMoved with the
+ new position offset.
+ * rendering/RenderBlock.h:
+ * rendering/RenderBlockLineLayout.cpp:
+ (WebCore::RenderBlock::updateShapeAndSegmentsForCurrentLine): Use layout offset, rather
+ than just vertical offset.
+ (WebCore::RenderBlock::updateShapeAndSegmentsForCurrentLineInFlowThread): Ditto.
+ (WebCore::RenderBlock::layoutRunsAndFloatsInRange): Ditto.
+ * rendering/shapes/ShapeInsideInfo.h:
+ (WebCore::ShapeInsideInfo::computeSegmentsForLine): Shift segments logically left when
+ there is an inline offset.
+
2013-09-03 Antoine Quint <grao...@apple.com>
Web Inspector: exceptions triggered from console evaluation do not pause the debugger
Modified: trunk/Source/WebCore/rendering/RenderBlock.cpp (155001 => 155002)
--- trunk/Source/WebCore/rendering/RenderBlock.cpp 2013-09-03 22:08:49 UTC (rev 155001)
+++ trunk/Source/WebCore/rendering/RenderBlock.cpp 2013-09-03 22:14:51 UTC (rev 155002)
@@ -1434,6 +1434,50 @@
}
#if ENABLE(CSS_SHAPES)
+void RenderBlock::relayoutShapeDescendantIfMoved(RenderBlock* child, LayoutSize offset)
+{
+ LayoutUnit left = isHorizontalWritingMode() ? offset.width() : offset.height();
+ if (!left || !child || child->shapeInsideInfo() || !layoutShapeInsideInfo())
+ return;
+ // Propagate layout markers only up to the child, as we are still in the middle
+ // of a layout pass
+ child->setNormalChildNeedsLayout(true);
+ child->markShapeInsideDescendantsForLayout();
+ child->layoutIfNeeded();
+}
+
+LayoutSize RenderBlock::logicalOffsetFromShapeAncestorContainer(const RenderBlock* container) const
+{
+ const RenderBlock* currentBlock = this;
+ LayoutRect blockRect(currentBlock->borderBoxRect());
+ while (currentBlock && !currentBlock->isRenderFlowThread() && currentBlock != container) {
+ RenderBlock* containerBlock = currentBlock->containingBlock();
+ ASSERT(containerBlock);
+ if (!containerBlock)
+ return LayoutSize();
+
+ if (containerBlock->style()->writingMode() != currentBlock->style()->writingMode()) {
+ // We have to put the block rect in container coordinates
+ // and we have to take into account both the container and current block flipping modes
+ // Bug 118073: Flipping inline and block directions at the same time will not work,
+ // as one of the flipped dimensions will not yet have been set to its final size
+ if (containerBlock->style()->isFlippedBlocksWritingMode()) {
+ if (containerBlock->isHorizontalWritingMode())
+ blockRect.setY(currentBlock->height() - blockRect.maxY());
+ else
+ blockRect.setX(currentBlock->width() - blockRect.maxX());
+ }
+ currentBlock->flipForWritingMode(blockRect);
+ }
+
+ blockRect.moveBy(currentBlock->location());
+ currentBlock = containerBlock;
+ }
+
+ LayoutSize result = isHorizontalWritingMode() ? LayoutSize(blockRect.x(), blockRect.y()) : LayoutSize(blockRect.y(), blockRect.x());
+ return result;
+}
+
void RenderBlock::imageChanged(WrappedImagePtr image, const IntRect*)
{
RenderBox::imageChanged(image);
@@ -2729,6 +2773,11 @@
// Now place the child in the correct left position
determineLogicalLeftPositionForChild(child, ApplyLayoutDelta);
+ LayoutSize childOffset = child->location() - oldRect.location();
+#if ENABLE(CSS_SHAPES)
+ relayoutShapeDescendantIfMoved(childRenderBlock, childOffset);
+#endif
+
// Update our height now that the child has been placed in the correct position.
setLogicalHeight(logicalHeight() + logicalHeightForChild(child));
if (mustSeparateMarginAfterForChild(child)) {
@@ -2740,7 +2789,6 @@
if (childRenderBlock && childRenderBlock->containsFloats())
maxFloatLogicalBottom = max(maxFloatLogicalBottom, addOverhangingFloats(toRenderBlock(child), !childNeededLayout));
- LayoutSize childOffset = child->location() - oldRect.location();
if (childOffset.width() || childOffset.height()) {
view().addLayoutDelta(childOffset);
Modified: trunk/Source/WebCore/rendering/RenderBlock.h (155001 => 155002)
--- trunk/Source/WebCore/rendering/RenderBlock.h 2013-09-03 22:08:49 UTC (rev 155001)
+++ trunk/Source/WebCore/rendering/RenderBlock.h 2013-09-03 22:14:51 UTC (rev 155002)
@@ -618,6 +618,8 @@
#if ENABLE(CSS_SHAPES)
void computeShapeSize();
void updateShapeInsideInfoAfterStyleChange(const ShapeValue*, const ShapeValue* oldShape);
+ void relayoutShapeDescendantIfMoved(RenderBlock* child, LayoutSize offset);
+ LayoutSize logicalOffsetFromShapeAncestorContainer(const RenderBlock* container) const;
#endif
virtual RenderObjectChildList* virtualChildren() { return children(); }
virtual const RenderObjectChildList* virtualChildren() const { return children(); }
@@ -1118,7 +1120,7 @@
void layoutRunsAndFloats(LineLayoutState&, bool hasInlineChild);
void layoutRunsAndFloatsInRange(LineLayoutState&, InlineBidiResolver&, const InlineIterator& cleanLineStart, const BidiStatus& cleanLineBidiStatus, unsigned consecutiveHyphenatedLines);
#if ENABLE(CSS_SHAPES)
- void updateShapeAndSegmentsForCurrentLine(ShapeInsideInfo*&, LayoutUnit&, LineLayoutState&);
+ void updateShapeAndSegmentsForCurrentLine(ShapeInsideInfo*&, const LayoutSize&, LineLayoutState&);
void updateShapeAndSegmentsForCurrentLineInFlowThread(ShapeInsideInfo*&, LineLayoutState&);
bool adjustLogicalLineTopAndLogicalHeightIfNeeded(ShapeInsideInfo*, LayoutUnit, LineLayoutState&, InlineBidiResolver&, FloatingObject*, InlineIterator&, WordMeasurements&);
#endif
Modified: trunk/Source/WebCore/rendering/RenderBlockLineLayout.cpp (155001 => 155002)
--- trunk/Source/WebCore/rendering/RenderBlockLineLayout.cpp 2013-09-03 22:08:49 UTC (rev 155001)
+++ trunk/Source/WebCore/rendering/RenderBlockLineLayout.cpp 2013-09-03 22:14:51 UTC (rev 155002)
@@ -1678,7 +1678,7 @@
block->setLogicalHeight(newLogicalHeight);
}
-void RenderBlock::updateShapeAndSegmentsForCurrentLine(ShapeInsideInfo*& shapeInsideInfo, LayoutUnit& absoluteLogicalTop, LineLayoutState& layoutState)
+void RenderBlock::updateShapeAndSegmentsForCurrentLine(ShapeInsideInfo*& shapeInsideInfo, const LayoutSize& logicalOffsetFromShapeContainer, LineLayoutState& layoutState)
{
if (layoutState.flowThread())
return updateShapeAndSegmentsForCurrentLineInFlowThread(shapeInsideInfo, layoutState);
@@ -1686,11 +1686,12 @@
if (!shapeInsideInfo)
return;
- LayoutUnit lineTop = logicalHeight() + absoluteLogicalTop;
+ LayoutUnit lineTop = logicalHeight() + logicalOffsetFromShapeContainer.height();
+ LayoutUnit lineLeft = logicalOffsetFromShapeContainer.width();
LayoutUnit lineHeight = this->lineHeight(layoutState.lineInfo().isFirstLine(), isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes);
// FIXME: Bug 95361: It is possible for a line to grow beyond lineHeight, in which case these segments may be incorrect.
- shapeInsideInfo->computeSegmentsForLine(lineTop, lineHeight);
+ shapeInsideInfo->computeSegmentsForLine(LayoutSize(lineLeft, lineTop), lineHeight);
pushShapeContentOverflowBelowTheContentBox(this, shapeInsideInfo, lineTop, lineHeight);
}
@@ -1761,8 +1762,10 @@
}
LayoutUnit lineTop = logicalLineTopInFlowThread - currentRegion->logicalTopForFlowThreadContent() + currentRegion->borderAndPaddingBefore();
- shapeInsideInfo->computeSegmentsForLine(lineTop, lineHeight);
+ // FIXME: 118571 - Shape inside on a region does not yet take into account its padding for nested flow blocks
+ shapeInsideInfo->computeSegmentsForLine(LayoutSize(0, lineTop), lineHeight);
+
if (currentRegion->isLastRegion())
pushShapeContentOverflowBelowTheContentBox(this, shapeInsideInfo, lineTop, lineHeight);
}
@@ -1799,18 +1802,18 @@
LineBreaker lineBreaker(this);
#if ENABLE(CSS_SHAPES)
- LayoutUnit absoluteLogicalTop;
+ LayoutSize logicalOffsetFromShapeContainer;
ShapeInsideInfo* shapeInsideInfo = layoutShapeInsideInfo();
if (shapeInsideInfo) {
ASSERT(shapeInsideInfo->owner() == this || allowsShapeInsideInfoSharing());
if (shapeInsideInfo != this->shapeInsideInfo()) {
// FIXME Bug 100284: If subsequent LayoutStates are pushed, we will have to add
// their offsets from the original shape-inside container.
- absoluteLogicalTop = logicalTop();
+ logicalOffsetFromShapeContainer = logicalOffsetFromShapeAncestorContainer(shapeInsideInfo->owner());
}
// Begin layout at the logical top of our shape inside.
- if (logicalHeight() + absoluteLogicalTop < shapeInsideInfo->shapeLogicalTop()) {
- LayoutUnit logicalHeight = shapeInsideInfo->shapeLogicalTop() - absoluteLogicalTop;
+ if (logicalHeight() + logicalOffsetFromShapeContainer.height() < shapeInsideInfo->shapeLogicalTop()) {
+ LayoutUnit logicalHeight = shapeInsideInfo->shapeLogicalTop() - logicalOffsetFromShapeContainer.height();
if (layoutState.flowThread())
logicalHeight -= shapeInsideInfo->owner()->borderAndPaddingBefore();
setLogicalHeight(logicalHeight);
@@ -1838,7 +1841,7 @@
FloatingObject* lastFloatFromPreviousLine = (containsFloats()) ? m_floatingObjects->set().last() : 0;
#if ENABLE(CSS_SHAPES)
- updateShapeAndSegmentsForCurrentLine(shapeInsideInfo, absoluteLogicalTop, layoutState);
+ updateShapeAndSegmentsForCurrentLine(shapeInsideInfo, logicalOffsetFromShapeContainer, layoutState);
#endif
WordMeasurements wordMeasurements;
end = lineBreaker.nextLineBreak(resolver, layoutState.lineInfo(), renderTextInfo, lastFloatFromPreviousLine, consecutiveHyphenatedLines, wordMeasurements);
@@ -1854,7 +1857,7 @@
}
#if ENABLE(CSS_SHAPES)
- if (adjustLogicalLineTopAndLogicalHeightIfNeeded(shapeInsideInfo, absoluteLogicalTop, layoutState, resolver, lastFloatFromPreviousLine, end, wordMeasurements))
+ if (adjustLogicalLineTopAndLogicalHeightIfNeeded(shapeInsideInfo, logicalOffsetFromShapeContainer.height(), layoutState, resolver, lastFloatFromPreviousLine, end, wordMeasurements))
continue;
#endif
ASSERT(end != resolver.position());
Modified: trunk/Source/WebCore/rendering/shapes/ShapeInsideInfo.h (155001 => 155002)
--- trunk/Source/WebCore/rendering/shapes/ShapeInsideInfo.h 2013-09-03 22:08:49 UTC (rev 155001)
+++ trunk/Source/WebCore/rendering/shapes/ShapeInsideInfo.h 2013-09-03 22:14:51 UTC (rev 155002)
@@ -68,6 +68,17 @@
static bool isEnabledFor(const RenderBlock* renderer);
+ bool computeSegmentsForLine(LayoutSize lineOffset, LayoutUnit lineHeight)
+ {
+ m_segmentRanges.clear();
+ bool result = ShapeInfo<RenderBlock, &RenderStyle::resolvedShapeInside, &Shape::getIncludedIntervals>::computeSegmentsForLine(lineOffset.height(), lineHeight);
+ for (size_t i = 0; i < m_segments.size(); i++) {
+ m_segments[i].logicalLeft -= lineOffset.width();
+ m_segments[i].logicalRight -= lineOffset.width();
+ }
+ return result;
+ }
+
virtual bool computeSegmentsForLine(LayoutUnit lineTop, LayoutUnit lineHeight) OVERRIDE
{
m_segmentRanges.clear();