Changeset 155002 in webkit


Ignore:
Timestamp:
Sep 3, 2013 3:14:51 PM (11 years ago)
Author:
betravis@adobe.com
Message:

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

Source/WebCore:

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.

LayoutTests:

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.
Location:
trunk
Files:
2 added
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r154998 r155002  
     12013-09-03  Bear Travis  <betravis@adobe.com>
     2
     3        [CSS Shapes] Shape's content gets extra left offset when left-border is positive on the content box
     4        https://bugs.webkit.org/show_bug.cgi?id=117573
     5
     6        Reviewed by David Hyatt.
     7
     8        Test that nested children with padding correctly apply an ancestor's shape-inside
     9        across different writing modes.
     10
     11        * fast/shapes/shape-inside/shape-inside-offset-block-children-expected.html: Added.
     12        * fast/shapes/shape-inside/shape-inside-offset-block-children.html: Added.
     13
    1142013-09-03  Antoine Quint  <graouts@apple.com>
    215
  • trunk/Source/WebCore/ChangeLog

    r154998 r155002  
     12013-09-03  Bear Travis  <betravis@adobe.com>
     2
     3        [CSS Shapes] Shape's content gets extra left offset when left-border is positive on the content box
     4        https://bugs.webkit.org/show_bug.cgi?id=117573
     5
     6        Reviewed by David Hyatt.
     7
     8        Nested blocks need to take into account their offset from the shape-inside container.
     9        The new code calculates the offset from the shape-inside container, then applies the
     10        offset to the computed segments. The line must be moved down by the offset's height,
     11        and each segment must be moved left by the offset's width.
     12
     13        Test: fast/shapes/shape-inside/shape-inside-offset-block-children.html
     14
     15        * rendering/RenderBlock.cpp:
     16        (WebCore::RenderBlock::relayoutShapeDescendantIfMoved): Relayout a block child if its
     17        new logical left would cause it to rest at a new position within a shape container.
     18        (WebCore::RenderBlock::logicalOffsetFromShapeAncestorContainer): Calculate the logical
     19        offset form a shape inside ancestor container.
     20        (WebCore::RenderBlock::layoutBlockChild): Call relayoutShapeDescendantIfMoved with the
     21        new position offset.
     22        * rendering/RenderBlock.h:
     23        * rendering/RenderBlockLineLayout.cpp:
     24        (WebCore::RenderBlock::updateShapeAndSegmentsForCurrentLine): Use layout offset, rather
     25        than just vertical offset.
     26        (WebCore::RenderBlock::updateShapeAndSegmentsForCurrentLineInFlowThread): Ditto.
     27        (WebCore::RenderBlock::layoutRunsAndFloatsInRange): Ditto.
     28        * rendering/shapes/ShapeInsideInfo.h:
     29        (WebCore::ShapeInsideInfo::computeSegmentsForLine): Shift segments logically left when
     30        there is an inline offset.
     31
    1322013-09-03  Antoine Quint  <graouts@apple.com>
    233
  • trunk/Source/WebCore/rendering/RenderBlock.cpp

    r154937 r155002  
    14351435
    14361436#if ENABLE(CSS_SHAPES)
     1437void RenderBlock::relayoutShapeDescendantIfMoved(RenderBlock* child, LayoutSize offset)
     1438{
     1439    LayoutUnit left = isHorizontalWritingMode() ? offset.width() : offset.height();
     1440    if (!left || !child || child->shapeInsideInfo() || !layoutShapeInsideInfo())
     1441        return;
     1442    // Propagate layout markers only up to the child, as we are still in the middle
     1443    // of a layout pass
     1444    child->setNormalChildNeedsLayout(true);
     1445    child->markShapeInsideDescendantsForLayout();
     1446    child->layoutIfNeeded();
     1447}
     1448
     1449LayoutSize RenderBlock::logicalOffsetFromShapeAncestorContainer(const RenderBlock* container) const
     1450{
     1451    const RenderBlock* currentBlock = this;
     1452    LayoutRect blockRect(currentBlock->borderBoxRect());
     1453    while (currentBlock && !currentBlock->isRenderFlowThread() && currentBlock != container) {
     1454        RenderBlock* containerBlock = currentBlock->containingBlock();
     1455        ASSERT(containerBlock);
     1456        if (!containerBlock)
     1457            return LayoutSize();
     1458
     1459        if (containerBlock->style()->writingMode() != currentBlock->style()->writingMode()) {
     1460            // We have to put the block rect in container coordinates
     1461            // and we have to take into account both the container and current block flipping modes
     1462            // Bug 118073: Flipping inline and block directions at the same time will not work,
     1463            // as one of the flipped dimensions will not yet have been set to its final size
     1464            if (containerBlock->style()->isFlippedBlocksWritingMode()) {
     1465                if (containerBlock->isHorizontalWritingMode())
     1466                    blockRect.setY(currentBlock->height() - blockRect.maxY());
     1467                else
     1468                    blockRect.setX(currentBlock->width() - blockRect.maxX());
     1469            }
     1470            currentBlock->flipForWritingMode(blockRect);
     1471        }
     1472
     1473        blockRect.moveBy(currentBlock->location());
     1474        currentBlock = containerBlock;
     1475    }
     1476
     1477    LayoutSize result = isHorizontalWritingMode() ? LayoutSize(blockRect.x(), blockRect.y()) : LayoutSize(blockRect.y(), blockRect.x());
     1478    return result;
     1479}
     1480
    14371481void RenderBlock::imageChanged(WrappedImagePtr image, const IntRect*)
    14381482{
     
    27302774    determineLogicalLeftPositionForChild(child, ApplyLayoutDelta);
    27312775
     2776    LayoutSize childOffset = child->location() - oldRect.location();
     2777#if ENABLE(CSS_SHAPES)
     2778    relayoutShapeDescendantIfMoved(childRenderBlock, childOffset);
     2779#endif
     2780
    27322781    // Update our height now that the child has been placed in the correct position.
    27332782    setLogicalHeight(logicalHeight() + logicalHeightForChild(child));
     
    27412790        maxFloatLogicalBottom = max(maxFloatLogicalBottom, addOverhangingFloats(toRenderBlock(child), !childNeededLayout));
    27422791
    2743     LayoutSize childOffset = child->location() - oldRect.location();
    27442792    if (childOffset.width() || childOffset.height()) {
    27452793        view().addLayoutDelta(childOffset);
  • trunk/Source/WebCore/rendering/RenderBlock.h

    r154937 r155002  
    619619    void computeShapeSize();
    620620    void updateShapeInsideInfoAfterStyleChange(const ShapeValue*, const ShapeValue* oldShape);
     621    void relayoutShapeDescendantIfMoved(RenderBlock* child, LayoutSize offset);
     622    LayoutSize logicalOffsetFromShapeAncestorContainer(const RenderBlock* container) const;
    621623#endif
    622624    virtual RenderObjectChildList* virtualChildren() { return children(); }
     
    11191121    void layoutRunsAndFloatsInRange(LineLayoutState&, InlineBidiResolver&, const InlineIterator& cleanLineStart, const BidiStatus& cleanLineBidiStatus, unsigned consecutiveHyphenatedLines);
    11201122#if ENABLE(CSS_SHAPES)
    1121     void updateShapeAndSegmentsForCurrentLine(ShapeInsideInfo*&, LayoutUnit&, LineLayoutState&);
     1123    void updateShapeAndSegmentsForCurrentLine(ShapeInsideInfo*&, const LayoutSize&, LineLayoutState&);
    11221124    void updateShapeAndSegmentsForCurrentLineInFlowThread(ShapeInsideInfo*&, LineLayoutState&);
    11231125    bool adjustLogicalLineTopAndLogicalHeightIfNeeded(ShapeInsideInfo*, LayoutUnit, LineLayoutState&, InlineBidiResolver&, FloatingObject*, InlineIterator&, WordMeasurements&);
  • trunk/Source/WebCore/rendering/RenderBlockLineLayout.cpp

    r154937 r155002  
    16791679}
    16801680
    1681 void RenderBlock::updateShapeAndSegmentsForCurrentLine(ShapeInsideInfo*& shapeInsideInfo, LayoutUnit& absoluteLogicalTop, LineLayoutState& layoutState)
     1681void RenderBlock::updateShapeAndSegmentsForCurrentLine(ShapeInsideInfo*& shapeInsideInfo, const LayoutSize& logicalOffsetFromShapeContainer, LineLayoutState& layoutState)
    16821682{
    16831683    if (layoutState.flowThread())
     
    16871687        return;
    16881688
    1689     LayoutUnit lineTop = logicalHeight() + absoluteLogicalTop;
     1689    LayoutUnit lineTop = logicalHeight() + logicalOffsetFromShapeContainer.height();
     1690    LayoutUnit lineLeft = logicalOffsetFromShapeContainer.width();
    16901691    LayoutUnit lineHeight = this->lineHeight(layoutState.lineInfo().isFirstLine(), isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes);
    16911692
    16921693    // FIXME: Bug 95361: It is possible for a line to grow beyond lineHeight, in which case these segments may be incorrect.
    1693     shapeInsideInfo->computeSegmentsForLine(lineTop, lineHeight);
     1694    shapeInsideInfo->computeSegmentsForLine(LayoutSize(lineLeft, lineTop), lineHeight);
    16941695
    16951696    pushShapeContentOverflowBelowTheContentBox(this, shapeInsideInfo, lineTop, lineHeight);
     
    17621763
    17631764    LayoutUnit lineTop = logicalLineTopInFlowThread - currentRegion->logicalTopForFlowThreadContent() + currentRegion->borderAndPaddingBefore();
    1764     shapeInsideInfo->computeSegmentsForLine(lineTop, lineHeight);
     1765
     1766    // FIXME: 118571 - Shape inside on a region does not yet take into account its padding for nested flow blocks
     1767    shapeInsideInfo->computeSegmentsForLine(LayoutSize(0, lineTop), lineHeight);
    17651768
    17661769    if (currentRegion->isLastRegion())
     
    18001803
    18011804#if ENABLE(CSS_SHAPES)
    1802     LayoutUnit absoluteLogicalTop;
     1805    LayoutSize logicalOffsetFromShapeContainer;
    18031806    ShapeInsideInfo* shapeInsideInfo = layoutShapeInsideInfo();
    18041807    if (shapeInsideInfo) {
     
    18071810            // FIXME Bug 100284: If subsequent LayoutStates are pushed, we will have to add
    18081811            // their offsets from the original shape-inside container.
    1809             absoluteLogicalTop = logicalTop();
     1812            logicalOffsetFromShapeContainer = logicalOffsetFromShapeAncestorContainer(shapeInsideInfo->owner());
    18101813        }
    18111814        // Begin layout at the logical top of our shape inside.
    1812         if (logicalHeight() + absoluteLogicalTop < shapeInsideInfo->shapeLogicalTop()) {
    1813             LayoutUnit logicalHeight = shapeInsideInfo->shapeLogicalTop() - absoluteLogicalTop;
     1815        if (logicalHeight() + logicalOffsetFromShapeContainer.height() < shapeInsideInfo->shapeLogicalTop()) {
     1816            LayoutUnit logicalHeight = shapeInsideInfo->shapeLogicalTop() - logicalOffsetFromShapeContainer.height();
    18141817            if (layoutState.flowThread())
    18151818                logicalHeight -= shapeInsideInfo->owner()->borderAndPaddingBefore();
     
    18391842
    18401843#if ENABLE(CSS_SHAPES)
    1841         updateShapeAndSegmentsForCurrentLine(shapeInsideInfo, absoluteLogicalTop, layoutState);
     1844        updateShapeAndSegmentsForCurrentLine(shapeInsideInfo, logicalOffsetFromShapeContainer, layoutState);
    18421845#endif
    18431846        WordMeasurements wordMeasurements;
     
    18551858
    18561859#if ENABLE(CSS_SHAPES)
    1857         if (adjustLogicalLineTopAndLogicalHeightIfNeeded(shapeInsideInfo, absoluteLogicalTop, layoutState, resolver, lastFloatFromPreviousLine, end, wordMeasurements))
     1860        if (adjustLogicalLineTopAndLogicalHeightIfNeeded(shapeInsideInfo, logicalOffsetFromShapeContainer.height(), layoutState, resolver, lastFloatFromPreviousLine, end, wordMeasurements))
    18581861            continue;
    18591862#endif
  • trunk/Source/WebCore/rendering/shapes/ShapeInsideInfo.h

    r151402 r155002  
    6969    static bool isEnabledFor(const RenderBlock* renderer);
    7070
     71    bool computeSegmentsForLine(LayoutSize lineOffset, LayoutUnit lineHeight)
     72    {
     73        m_segmentRanges.clear();
     74        bool result = ShapeInfo<RenderBlock, &RenderStyle::resolvedShapeInside, &Shape::getIncludedIntervals>::computeSegmentsForLine(lineOffset.height(), lineHeight);
     75        for (size_t i = 0; i < m_segments.size(); i++) {
     76            m_segments[i].logicalLeft -= lineOffset.width();
     77            m_segments[i].logicalRight -= lineOffset.width();
     78        }
     79        return result;
     80    }
     81
    7182    virtual bool computeSegmentsForLine(LayoutUnit lineTop, LayoutUnit lineHeight) OVERRIDE
    7283    {
Note: See TracChangeset for help on using the changeset viewer.