Changeset 156881 in webkit


Ignore:
Timestamp:
Oct 4, 2013, 1:49:21 AM (12 years ago)
Author:
abucur@adobe.com
Message:

[CSS Regions] Infinite loop when computing widows
https://bugs.webkit.org/show_bug.cgi?id=122215

Reviewed by David Hyatt.

Source/WebCore:

The patch ensures it's not possible to relayout a block indefinitely because of widows contraints. You can't
break a block more than once to account for widows. This can happen if, for example, some lines are moved
to the next container and there the content breaks in another container again without respecting the widows property.
This is in line with the idea of not leaving empty fragmentation containers during layout.

Test: fast/regions/regions-widows-stack-overflow.html

  • rendering/RenderBlockFlow.cpp:

(WebCore::RenderBlockFlow::adjustLinePositionForPagination):
(WebCore::RenderBlockFlow::setBreakAtLineToAvoidWidow):
(WebCore::RenderBlockFlow::setDidBreakAtLineToAvoidWidow):
(WebCore::RenderBlockFlow::clearDidBreakAtLineToAvoidWidow):
(WebCore::RenderBlockFlow::clearShouldBreakAtLineToAvoidWidow):

  • rendering/RenderBlockFlow.h:

(WebCore::RenderBlockFlow::RenderBlockFlowRareData::RenderBlockFlowRareData): Rename the m_shouldBreakAtLineToAvoidWidow
flag to m_didBreakAtLineToAvoidWidow.

(WebCore::RenderBlockFlow::shouldBreakAtLineToAvoidWidow): Use the line index to determine if it should break or not.
(WebCore::RenderBlockFlow::didBreakAtLineToAvoidWidow): Use to determine if a break already happened because of widows.

  • rendering/RenderBlockLineLayout.cpp:

(WebCore::RenderBlock::layoutRunsAndFloatsInRange):

LayoutTests:

Test there is no stack overflow when trying to break for widows that are caused by other widows.

  • fast/regions/regions-widows-stack-overflow-expected.html: Added.
  • fast/regions/regions-widows-stack-overflow.html: Added.
Location:
trunk
Files:
2 added
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r156869 r156881  
     12013-10-04  Andrei Bucur  <abucur@adobe.com>
     2
     3        [CSS Regions] Infinite loop when computing widows
     4        https://bugs.webkit.org/show_bug.cgi?id=122215
     5
     6        Reviewed by David Hyatt.
     7
     8        Test there is no stack overflow when trying to break for widows that are caused by other widows.
     9
     10        * fast/regions/regions-widows-stack-overflow-expected.html: Added.
     11        * fast/regions/regions-widows-stack-overflow.html: Added.
     12
    1132013-10-03  Christophe Dumez  <ch.dumez@sisa.samsung.com>
    214
  • trunk/Source/WebCore/ChangeLog

    r156879 r156881  
     12013-10-04  Andrei Bucur  <abucur@adobe.com>
     2
     3        [CSS Regions] Infinite loop when computing widows
     4        https://bugs.webkit.org/show_bug.cgi?id=122215
     5
     6        Reviewed by David Hyatt.
     7
     8        The patch ensures it's not possible to relayout a block indefinitely because of widows contraints. You can't
     9        break a block more than once to account for widows. This can happen if, for example, some lines are moved
     10        to the next container and there the content breaks in another container again without respecting the widows property.
     11        This is in line with the idea of not leaving empty fragmentation containers during layout.
     12
     13        Test: fast/regions/regions-widows-stack-overflow.html
     14
     15        * rendering/RenderBlockFlow.cpp:
     16        (WebCore::RenderBlockFlow::adjustLinePositionForPagination):
     17        (WebCore::RenderBlockFlow::setBreakAtLineToAvoidWidow):
     18        (WebCore::RenderBlockFlow::setDidBreakAtLineToAvoidWidow):
     19        (WebCore::RenderBlockFlow::clearDidBreakAtLineToAvoidWidow):
     20        (WebCore::RenderBlockFlow::clearShouldBreakAtLineToAvoidWidow):
     21
     22        * rendering/RenderBlockFlow.h:
     23        (WebCore::RenderBlockFlow::RenderBlockFlowRareData::RenderBlockFlowRareData): Rename the m_shouldBreakAtLineToAvoidWidow
     24        flag to m_didBreakAtLineToAvoidWidow.
     25
     26        (WebCore::RenderBlockFlow::shouldBreakAtLineToAvoidWidow): Use the line index to determine if it should break or not.
     27        (WebCore::RenderBlockFlow::didBreakAtLineToAvoidWidow): Use to determine if a break already happened because of widows.
     28
     29        * rendering/RenderBlockLineLayout.cpp:
     30        (WebCore::RenderBlock::layoutRunsAndFloatsInRange):
     31
    1322013-10-03  Anders Carlsson  <andersca@apple.com>
    233
  • trunk/Source/WebCore/rendering/RenderBlockFlow.cpp

    r156876 r156881  
    13901390    int lineIndex = lineCount(lineBox);
    13911391    if (remainingLogicalHeight < lineHeight || (shouldBreakAtLineToAvoidWidow() && lineBreakToAvoidWidow() == lineIndex)) {
    1392         if (shouldBreakAtLineToAvoidWidow() && lineBreakToAvoidWidow() == lineIndex)
     1392        if (shouldBreakAtLineToAvoidWidow() && lineBreakToAvoidWidow() == lineIndex) {
    13931393            clearShouldBreakAtLineToAvoidWidow();
     1394            setDidBreakAtLineToAvoidWidow();
     1395        }
    13941396        // If we have a non-uniform page height, then we have to shift further possibly.
    13951397        if (!hasUniformPageLogicalHeight && !pushToNextPageWithMinimumLogicalHeight(remainingLogicalHeight, logicalOffset, lineHeight))
     
    14161418void RenderBlockFlow::setBreakAtLineToAvoidWidow(int lineToBreak)
    14171419{
    1418     ASSERT(lineToBreak);
     1420    ASSERT(lineToBreak >= 0);
    14191421    if (!m_rareData)
    14201422        m_rareData = adoptPtr(new RenderBlockFlowRareData(this));
    1421     m_rareData->m_shouldBreakAtLineToAvoidWidow = true;
     1423
     1424    ASSERT(!m_rareData->m_didBreakAtLineToAvoidWidow);
    14221425    m_rareData->m_lineBreakToAvoidWidow = lineToBreak;
    14231426}
    14241427
     1428void RenderBlockFlow::setDidBreakAtLineToAvoidWidow()
     1429{
     1430    ASSERT(!shouldBreakAtLineToAvoidWidow());
     1431    if (!m_rareData)
     1432        return;
     1433
     1434    m_rareData->m_didBreakAtLineToAvoidWidow = true;
     1435}
     1436
     1437void RenderBlockFlow::clearDidBreakAtLineToAvoidWidow()
     1438{
     1439    if (!m_rareData)
     1440        return;
     1441
     1442    m_rareData->m_didBreakAtLineToAvoidWidow = false;
     1443}
     1444
    14251445void RenderBlockFlow::clearShouldBreakAtLineToAvoidWidow() const
    14261446{
     1447    ASSERT(shouldBreakAtLineToAvoidWidow());
    14271448    if (!m_rareData)
    14281449        return;
    1429     m_rareData->m_shouldBreakAtLineToAvoidWidow = false;
     1450
    14301451    m_rareData->m_lineBreakToAvoidWidow = -1;
    14311452}
  • trunk/Source/WebCore/rendering/RenderBlockFlow.h

    r156738 r156881  
    9393            , m_discardMarginBefore(false)
    9494            , m_discardMarginAfter(false)
    95             , m_shouldBreakAtLineToAvoidWidow(false)
     95            , m_didBreakAtLineToAvoidWidow(false)
    9696        {
    9797        }
     
    120120        bool m_discardMarginBefore : 1;
    121121        bool m_discardMarginAfter : 1;
    122         bool m_shouldBreakAtLineToAvoidWidow : 1;
     122        bool m_didBreakAtLineToAvoidWidow : 1;
    123123    };
    124124
     
    213213    void setCollapsedBottomMargin(const MarginInfo&);
    214214
    215     bool shouldBreakAtLineToAvoidWidow() const { return m_rareData && m_rareData->m_shouldBreakAtLineToAvoidWidow; }
     215    bool shouldBreakAtLineToAvoidWidow() const { return m_rareData && m_rareData->m_lineBreakToAvoidWidow >= 0; }
    216216    void clearShouldBreakAtLineToAvoidWidow() const;
    217217    int lineBreakToAvoidWidow() const { return m_rareData ? m_rareData->m_lineBreakToAvoidWidow : -1; }
    218218    void setBreakAtLineToAvoidWidow(int);
     219    void clearDidBreakAtLineToAvoidWidow();
     220    void setDidBreakAtLineToAvoidWidow();
     221    bool didBreakAtLineToAvoidWidow() const { return m_rareData && m_rareData->m_didBreakAtLineToAvoidWidow; }
    219222    bool relayoutToAvoidWidows(LayoutStateMaintainer&);
    220223
  • trunk/Source/WebCore/rendering/RenderBlockLineLayout.cpp

    r156876 r156881  
    16751675    }
    16761676
    1677     if (paginated && !style()->hasAutoWidows()) {
     1677    // In case we already adjusted the line positions during this layout to avoid widows
     1678    // then we need to ignore the possibility of having a new widows situation.
     1679    // Otherwise, we risk leaving empty containers which is against the block fragmentation principles.
     1680    // FIXME-BLOCKFLOW: Remove this type conversion once the owning function moves.
     1681    if (paginated && !style()->hasAutoWidows() && !toRenderBlockFlow(this)->didBreakAtLineToAvoidWidow()) {
    16781682        // Check the line boxes to make sure we didn't create unacceptable widows.
    16791683        // However, we'll prioritize orphans - so nothing we do here should create
     
    17321736        }
    17331737    }
     1738
     1739    // FIXME-BLOCKFLOW: Remove this type conversion once the owning function moves.
     1740    toRenderBlockFlow(this)->clearDidBreakAtLineToAvoidWidow();
    17341741}
    17351742
Note: See TracChangeset for help on using the changeset viewer.