Changeset 151570 in webkit


Ignore:
Timestamp:
Jun 13, 2013 2:09:43 PM (11 years ago)
Author:
zoltan@webkit.org
Message:

[CSS Shapes][CSS Regions] Respect bottom positioned shapes and content adjustment inside shapes
https://bugs.webkit.org/show_bug.cgi?id=117599

Reviewed by David Hyatt.

In r150478 I added support for multiple positioned shape-insides on regions, this patch covers the cases when a shape
is positioned to the bottom of the region or the region contains a shape which forces the content to be adjusted inside
the shape (e.g. we have a triangle shape and the first line needs to be started at the first position where it fits).
I introduced a new helper function to update the current shape and the current line segments in the flow thread cases. With
this new helper function all the logic which calculates the segments for shape-inside on regions is located in one function.

Source/WebCore:

Tests: fast/regions/shape-inside/shape-inside-on-regions-block-content-overflow-bottom-positioned-multiple-shapes.html

fast/regions/shape-inside/shape-inside-on-regions-block-content-polygon-with-adjustment.html
fast/regions/shape-inside/shape-inside-on-regions-inline-content-overflow-bottom-positioned-multiple-shapes.html
fast/regions/shape-inside/shape-inside-on-regions-inline-content-polygon-with-adjustment.html

  • rendering/RenderBlock.h: Add new helper's declaration
  • rendering/RenderBlockLineLayout.cpp:

(WebCore::LineLayoutState::LineLayoutState): Add a member to carry adjustment for flow thread cases.
(WebCore::LineLayoutState::adjustedLogicalLineTop): Add new member.
(WebCore::LineLayoutState::setAdjustedLogicalLineTop): Add new setter for the new member.
(WebCore::RenderBlock::updateShapeAndSegmentsForCurrentLine): Move flow thread case to its helper function.
(WebCore::RenderBlock::updateShapeAndSegmentsForCurrentLineInFlowThread): Added new helper for flow thread cases.
(WebCore::RenderBlock::adjustLogicalLineTopAndLogicalHeightIfNeeded): Save adjustment for flow thread cases.

LayoutTests:

  • fast/regions/shape-inside/shape-inside-on-regions-block-content-overflow-bottom-positioned-multiple-shapes-expected.html: Added.
  • fast/regions/shape-inside/shape-inside-on-regions-block-content-overflow-bottom-positioned-multiple-shapes.html: Added.
  • fast/regions/shape-inside/shape-inside-on-regions-block-content-polygon-with-adjustment-expected.html: Added.
  • fast/regions/shape-inside/shape-inside-on-regions-block-content-polygon-with-adjustment.html: Added.
  • fast/regions/shape-inside/shape-inside-on-regions-inline-content-overflow-bottom-positioned-multiple-shapes-expected.html: Added.
  • fast/regions/shape-inside/shape-inside-on-regions-inline-content-overflow-bottom-positioned-multiple-shapes.html: Added.
  • fast/regions/shape-inside/shape-inside-on-regions-inline-content-polygon-with-adjustment-expected.html: Added.
  • fast/regions/shape-inside/shape-inside-on-regions-inline-content-polygon-with-adjustment.html: Added.
Location:
trunk
Files:
8 added
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r151567 r151570  
     12013-06-13  Zoltan Horvath  <zoltan@webkit.org>
     2
     3        [CSS Shapes][CSS Regions] Respect bottom positioned shapes and content adjustment inside shapes
     4        https://bugs.webkit.org/show_bug.cgi?id=117599
     5
     6        Reviewed by David Hyatt.
     7
     8        In r150478 I added support for multiple positioned shape-insides on regions, this patch covers the cases when a shape
     9        is positioned to the bottom of the region or the region contains a shape which forces the content to be adjusted inside
     10        the shape (e.g. we have a triangle shape and the first line needs to be started at the first position where it fits).
     11        I introduced a new helper function to update the current shape and the current line segments in the flow thread cases. With
     12        this new helper function all the logic which calculates the segments for shape-inside on regions is located in one function.
     13
     14        * fast/regions/shape-inside/shape-inside-on-regions-block-content-overflow-bottom-positioned-multiple-shapes-expected.html: Added.
     15        * fast/regions/shape-inside/shape-inside-on-regions-block-content-overflow-bottom-positioned-multiple-shapes.html: Added.
     16        * fast/regions/shape-inside/shape-inside-on-regions-block-content-polygon-with-adjustment-expected.html: Added.
     17        * fast/regions/shape-inside/shape-inside-on-regions-block-content-polygon-with-adjustment.html: Added.
     18        * fast/regions/shape-inside/shape-inside-on-regions-inline-content-overflow-bottom-positioned-multiple-shapes-expected.html: Added.
     19        * fast/regions/shape-inside/shape-inside-on-regions-inline-content-overflow-bottom-positioned-multiple-shapes.html: Added.
     20        * fast/regions/shape-inside/shape-inside-on-regions-inline-content-polygon-with-adjustment-expected.html: Added.
     21        * fast/regions/shape-inside/shape-inside-on-regions-inline-content-polygon-with-adjustment.html: Added.
     22
    1232013-06-13  Mihai Tica  <mitica@adobe.com>
    224
  • trunk/Source/WebCore/ChangeLog

    r151566 r151570  
     12013-06-13  Zoltan Horvath  <zoltan@webkit.org>
     2
     3        [CSS Shapes][CSS Regions] Respect bottom positioned shapes and content adjustment inside shapes
     4        https://bugs.webkit.org/show_bug.cgi?id=117599
     5
     6        Reviewed by David Hyatt.
     7
     8        In r150478 I added support for multiple positioned shape-insides on regions, this patch covers the cases when a shape
     9        is positioned to the bottom of the region or the region contains a shape which forces the content to be adjusted inside
     10        the shape (e.g. we have a triangle shape and the first line needs to be started at the first position where it fits).
     11        I introduced a new helper function to update the current shape and the current line segments in the flow thread cases. With
     12        this new helper function all the logic which calculates the segments for shape-inside on regions is located in one function.
     13
     14        Tests: fast/regions/shape-inside/shape-inside-on-regions-block-content-overflow-bottom-positioned-multiple-shapes.html
     15               fast/regions/shape-inside/shape-inside-on-regions-block-content-polygon-with-adjustment.html
     16               fast/regions/shape-inside/shape-inside-on-regions-inline-content-overflow-bottom-positioned-multiple-shapes.html
     17               fast/regions/shape-inside/shape-inside-on-regions-inline-content-polygon-with-adjustment.html
     18
     19        * rendering/RenderBlock.h: Add new helper's declaration
     20        * rendering/RenderBlockLineLayout.cpp:
     21        (WebCore::LineLayoutState::LineLayoutState): Add a member to carry adjustment for flow thread cases.
     22        (WebCore::LineLayoutState::adjustedLogicalLineTop): Add new member.
     23        (WebCore::LineLayoutState::setAdjustedLogicalLineTop): Add new setter for the new member.
     24        (WebCore::RenderBlock::updateShapeAndSegmentsForCurrentLine): Move flow thread case to its helper function.
     25        (WebCore::RenderBlock::updateShapeAndSegmentsForCurrentLineInFlowThread): Added new helper for flow thread cases.
     26        (WebCore::RenderBlock::adjustLogicalLineTopAndLogicalHeightIfNeeded): Save adjustment for flow thread cases.
     27
    1282013-06-13  Mihai Tica  <mitica@adobe.com>
    229
  • trunk/Source/WebCore/rendering/RenderBlock.h

    r151545 r151570  
    10861086    void layoutRunsAndFloatsInRange(LineLayoutState&, InlineBidiResolver&, const InlineIterator& cleanLineStart, const BidiStatus& cleanLineBidiStatus, unsigned consecutiveHyphenatedLines);
    10871087#if ENABLE(CSS_SHAPES)
    1088     void updateShapeAndSegmentsForCurrentLine(ShapeInsideInfo*, LayoutUnit&, LineLayoutState&, bool&);
     1088    void updateShapeAndSegmentsForCurrentLine(ShapeInsideInfo*&, LayoutUnit&, LineLayoutState&, bool&);
     1089    void updateShapeAndSegmentsForCurrentLineInFlowThread(ShapeInsideInfo*&, LineLayoutState&, bool&);
    10891090    bool adjustLogicalLineTopAndLogicalHeightIfNeeded(ShapeInsideInfo*, LayoutUnit, LineLayoutState&, InlineBidiResolver&, FloatingObject*, InlineIterator&, WordMeasurements&);
    10901091#endif
  • trunk/Source/WebCore/rendering/RenderBlockLineLayout.cpp

    r151518 r151570  
    14591459        , m_repaintLogicalTop(repaintLogicalTop)
    14601460        , m_repaintLogicalBottom(repaintLogicalBottom)
     1461        , m_adjustedLogicalLineTop(0)
    14611462        , m_usesRepaintBounds(false)
    14621463        , m_flowThread(flowThread)
     
    15041505    void setFloatIndex(unsigned floatIndex) { m_floatIndex = floatIndex; }
    15051506   
     1507    LayoutUnit adjustedLogicalLineTop() const { return m_adjustedLogicalLineTop; }
     1508    void setAdjustedLogicalLineTop(LayoutUnit value) { m_adjustedLogicalLineTop = value; }
     1509
    15061510    RenderFlowThread* flowThread() const { return m_flowThread; }
    15071511    void setFlowThread(RenderFlowThread* thread) { m_flowThread = thread; }
     
    15221526    LayoutUnit& m_repaintLogicalTop;
    15231527    LayoutUnit& m_repaintLogicalBottom;
     1528
     1529    LayoutUnit m_adjustedLogicalLineTop;
    15241530
    15251531    bool m_usesRepaintBounds;
     
    16471653}
    16481654
    1649 void RenderBlock::updateShapeAndSegmentsForCurrentLine(ShapeInsideInfo* shapeInsideInfo, LayoutUnit& absoluteLogicalTop, LineLayoutState& layoutState, bool& lineOverflowsFromShapeInside)
    1650 {
    1651     LayoutUnit logicalHeight = this->logicalHeight();
    1652     RenderRegion* currentRegion = regionAtBlockOffset(logicalHeight);
    1653     if (currentRegion)
    1654         shapeInsideInfo = layoutShapeInsideInfo();
     1655void RenderBlock::updateShapeAndSegmentsForCurrentLine(ShapeInsideInfo*& shapeInsideInfo, LayoutUnit& absoluteLogicalTop, LineLayoutState& layoutState, bool& lineOverflowsFromShapeInside)
     1656{
     1657    if (layoutState.flowThread())
     1658        return updateShapeAndSegmentsForCurrentLineInFlowThread(shapeInsideInfo, layoutState, lineOverflowsFromShapeInside);
     1659
    16551660    if (!shapeInsideInfo)
    16561661        return;
    16571662
    1658     LayoutUnit lineTop = logicalHeight + absoluteLogicalTop;
    1659     LayoutUnit lineHeight = this->lineHeight(layoutState.lineInfo().isFirstLine(), isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes);
    1660 
    1661     if (layoutState.flowThread()) {
    1662         RenderRegion* nextRegion = regionAtBlockOffset(logicalHeight + lineHeight - LayoutUnit(1));
    1663         lineTop += shapeInsideInfo->owner()->borderAndPaddingBefore();
    1664         // Content in a flow thread is relative to the beginning of the thread, but the shape calculation should be relative to the current region.
    1665         if (currentRegion == nextRegion)
    1666             lineTop -= currentRegion->logicalTopForFlowThreadContent();
    1667     }
    1668 
     1663    LayoutUnit lineTop = logicalHeight() + absoluteLogicalTop;
    16691664    // FIXME: Bug 95361: It is possible for a line to grow beyond lineHeight, in which case these segments may be incorrect.
    1670     shapeInsideInfo->computeSegmentsForLine(lineTop, lineHeight);
     1665    shapeInsideInfo->computeSegmentsForLine(lineTop, lineHeight(layoutState.lineInfo().isFirstLine(), isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes));
    16711666
    16721667    // The overflow should be pushed below the content box
     
    16741669    if (!shapeInsideInfo->lineWithinShapeBounds() && !lineOverflowsFromShapeInside && shapeContainingBlockHeight) {
    16751670        lineOverflowsFromShapeInside = true;
    1676         LayoutUnit newLogicalHeight = shapeContainingBlockHeight;
    1677 
    1678         if (layoutState.flowThread()) {
    1679             // If block contents flown across multiple regions and the shape-inside was applied on the second region we can end up with negative lineTop
    1680             if (lineTop < 0)
    1681                 return;
    1682 
    1683             newLogicalHeight = logicalHeight + shapeContainingBlockHeight - lineTop - currentRegion->borderAndPaddingBefore();
    1684 
    1685             RenderRegion* nextRegion = regionAtBlockOffset(newLogicalHeight);
    1686             ShapeInsideInfo* nextShapeInfo = 0;
    1687             if (nextRegion)
    1688                 nextShapeInfo = nextRegion->shapeInsideInfo();
    1689 
    1690             // The overflow flows into another region with shape-inside
    1691             if (currentRegion != nextRegion && nextShapeInfo) {
    1692                 newLogicalHeight += nextShapeInfo->shapeLogicalTop() - nextRegion->borderAndPaddingBefore();
    1693 
    1694                 LayoutUnit offset = nextShapeInfo->shapeLogicalTop() - nextRegion->borderAndPaddingBefore();
    1695                 nextShapeInfo->computeSegmentsForLine(offset, lineHeight);
    1696 
    1697                 shapeInsideInfo = nextShapeInfo;
    1698                 lineOverflowsFromShapeInside = false;
    1699             }
    1700         }
     1671        setLogicalHeight(shapeContainingBlockHeight);
     1672    }
     1673}
     1674
     1675void RenderBlock::updateShapeAndSegmentsForCurrentLineInFlowThread(ShapeInsideInfo*& shapeInsideInfo, LineLayoutState& layoutState, bool& lineOverflowsFromShapeInside)
     1676{
     1677    ASSERT(layoutState.flowThread());
     1678
     1679    LayoutUnit lineHeight = this->lineHeight(layoutState.lineInfo().isFirstLine(), isHorizontalWritingMode() ? HorizontalLine : VerticalLine, PositionOfInteriorLineBoxes);
     1680
     1681    RenderRegion* currentRegion = regionAtBlockOffset(logicalHeight());
     1682    if (!currentRegion)
     1683        return;
     1684
     1685    shapeInsideInfo = currentRegion->shapeInsideInfo();
     1686
     1687    LayoutUnit logicalLineTopInFlowThread = logicalHeight() + offsetFromLogicalTopOfFirstPage();
     1688    LayoutUnit logicalLineBottomInFlowThread = logicalLineTopInFlowThread + lineHeight;
     1689    LayoutUnit logicalRegionTopInFlowThread = currentRegion->logicalTopForFlowThreadContent();
     1690    LayoutUnit logicalRegionBottomInFlowThread = logicalRegionTopInFlowThread + currentRegion->logicalHeight() - currentRegion->borderAndPaddingBefore() - currentRegion->borderAfter() - currentRegion->paddingAfter();
     1691
     1692    // We only want to deal regions with shapes, so we look up for the next region whether it has a shape
     1693    if (!shapeInsideInfo && !currentRegion->isLastRegion()) {
     1694        LayoutUnit deltaToNextRegion = logicalHeight() + logicalRegionBottomInFlowThread - logicalLineTopInFlowThread;
     1695        RenderRegion* lookupForNextRegion = regionAtBlockOffset(logicalHeight() + deltaToNextRegion);
     1696        if (!lookupForNextRegion->shapeInsideInfo())
     1697            return;
     1698    }
     1699
     1700    LayoutUnit shapeBottomInFlowThread = LayoutUnit::max();
     1701    if (shapeInsideInfo)
     1702        shapeBottomInFlowThread = shapeInsideInfo->shapeLogicalBottom() + currentRegion->logicalTopForFlowThreadContent();
     1703
     1704    // If the line is between two shapes/regions we position the line to the top of the next shape/region
     1705    RenderRegion* nextRegion = regionAtBlockOffset(logicalHeight() + lineHeight);
     1706    if ((currentRegion != nextRegion && (logicalLineBottomInFlowThread > logicalRegionBottomInFlowThread)) || (!currentRegion->isLastRegion() && shapeBottomInFlowThread < logicalLineBottomInFlowThread)) {
     1707        LayoutUnit deltaToNextRegion = logicalRegionBottomInFlowThread - logicalLineTopInFlowThread;
     1708        nextRegion = regionAtBlockOffset(logicalHeight() + deltaToNextRegion);
     1709
     1710        ASSERT(currentRegion != nextRegion);
     1711
     1712        shapeInsideInfo = nextRegion->shapeInsideInfo();
     1713        setLogicalHeight(logicalHeight() + deltaToNextRegion);
     1714
     1715        currentRegion = nextRegion;
     1716
     1717        logicalLineTopInFlowThread = logicalHeight() + offsetFromLogicalTopOfFirstPage();
     1718        logicalLineBottomInFlowThread = logicalLineTopInFlowThread + lineHeight;
     1719        logicalRegionTopInFlowThread = currentRegion->logicalTopForFlowThreadContent();
     1720        logicalRegionBottomInFlowThread = logicalRegionTopInFlowThread + currentRegion->logicalHeight() - currentRegion->borderAndPaddingBefore() - currentRegion->borderAfter() - currentRegion->paddingAfter();
     1721    }
     1722
     1723    if (!shapeInsideInfo)
     1724        return;
     1725
     1726    // We position the first line to the top of the shape in the region or to the previously adjusted position in the shape
     1727    if (logicalLineBottomInFlowThread <= (logicalRegionTopInFlowThread + lineHeight) || (logicalLineTopInFlowThread - logicalRegionTopInFlowThread) < (layoutState.adjustedLogicalLineTop() - currentRegion->borderAndPaddingBefore())) {
     1728        LayoutUnit shapeTopOffset = layoutState.adjustedLogicalLineTop();
     1729        if (!shapeTopOffset)
     1730            shapeTopOffset = shapeInsideInfo->shapeLogicalTop();
     1731
     1732        LayoutUnit shapePositionInFlowThread = currentRegion->logicalTopForFlowThreadContent() + shapeTopOffset;
     1733        LayoutUnit shapeTopLineTopDelta = shapePositionInFlowThread - logicalLineTopInFlowThread - currentRegion->borderAndPaddingBefore();
     1734
     1735        setLogicalHeight(logicalHeight() + shapeTopLineTopDelta);
     1736        logicalLineTopInFlowThread += shapeTopLineTopDelta;
     1737        layoutState.setAdjustedLogicalLineTop(0);
     1738    }
     1739
     1740    LayoutUnit lineTop = logicalLineTopInFlowThread - currentRegion->logicalTopForFlowThreadContent() + currentRegion->borderAndPaddingBefore();
     1741    shapeInsideInfo->computeSegmentsForLine(lineTop, lineHeight);
     1742
     1743    // Overflow from last shape on last region should be pushed below the content box
     1744    if (currentRegion->isLastRegion() && !lineOverflowsFromShapeInside && (lineTop + lineHeight) > shapeInsideInfo->shapeLogicalBottom()) {
     1745        lineOverflowsFromShapeInside = true;
     1746        LayoutUnit newLogicalHeight = this->logicalHeight() + (shapeInsideInfo->shapeContainingBlockHeight() - (lineTop + currentRegion->borderAfter() + currentRegion->paddingAfter()));
    17011747        setLogicalHeight(newLogicalHeight);
    17021748    }
     
    17101756
    17111757    LayoutUnit newLogicalHeight = adjustedLogicalLineTop - absoluteLogicalTop;
    1712     if (layoutState.flowThread())
     1758
     1759    if (layoutState.flowThread()) {
     1760        layoutState.setAdjustedLogicalLineTop(adjustedLogicalLineTop);
    17131761        newLogicalHeight = logicalHeight();
     1762    }
     1763
    17141764
    17151765    end = restartLayoutRunsAndFloatsInRange(logicalHeight(), newLogicalHeight, lastFloatFromPreviousLine, resolver, end);
Note: See TracChangeset for help on using the changeset viewer.