Changeset 137200 in webkit


Ignore:
Timestamp:
Dec 10, 2012 1:22:44 PM (11 years ago)
Author:
dino@apple.com
Message:

Support for CSS widows and orphans
https://bugs.webkit.org/show_bug.cgi?id=9410

Reviewed by Darin Adler.

Source/WebCore:

The CSS 'widow' and 'orphan' properties were supported by the parser and
style system, but were not actually doing anything in layout. Now they do!

In order to not break existing content, I unfortunately had to go against
the specification and change our default value from 2 to auto. A value of
auto means that widows and orphans will not cause any page/column breaks.

Supporting orphans was a small change. During line layout, if we realise
we need to move to a new page in a situation that would create an orphan,
move the entire block to the new page. There was already code to do this.

Support for widows was trickier. When we finish laying out a block, count
the number of hanging lines. If we've created a widow, and there are enough
available lines on the previous page, then steal some and remember the line
to break at. Trigger a relayout. Then notice the line that was marked for
breaking and avoid the widow. This means some blocks go through layout
twice, but as long as the widow value is small it shouldn't be a huge penalty.

Tests: fast/multicol/widows-and-orphans.html (new test)

printing/page-break-orphans.html
printing/page-break-orphans-and-widows.html
printing/page-break-widows.html

  • css/CSSComputedStyleDeclaration.cpp:

(WebCore::CSSComputedStyleDeclaration::getPropertyCSSValue): Return CSSValueAuto for widows and orphans if necessary.

  • css/CSSParser.cpp:

(WebCore::CSSParser::parseValue): Support "auto" in widow and orphan property parsing.

  • css/StyleBuilder.cpp:

(WebCore::StyleBuilder::StyleBuilder): Change property handler to something that supports auto.

  • page/animation/CSSPropertyAnimation.cpp:

(WebCore::CSSPropertyAnimation::ensurePropertyMap): Add widows and orphans to the animation map.

  • rendering/RenderBlock.cpp:

(WebCore::RenderBlock::layoutBlockChild): Detect if we've caused a widow-fixing break, and request relayout evaluation.
(WebCore::RenderBlock::markForPaginationRelayoutIfNeeded): Test for a widow-fixing line.
(WebCore::RenderBlock::setBreakAtLineToAvoidWidow): New function to remember where we should break on next layout.
(WebCore::RenderBlock::adjustLinePositionForPagination): Move the entire block to a new page if this would create an orphan.

  • rendering/RenderBlock.h:

(WebCore::RenderBlock::shouldBreakAtLineToAvoidWidow): New function to indicate if we are remembering a widow.
(WebCore::RenderBlock::clearShouldBreakAtLineToAvoidWidow): Reset the line breaks.
(WebCore::RenderBlock::lineBreakToAvoidWidow):
(WebCore::RenderBlock::RenderBlockRareData::RenderBlockRareData): Add a flag for indicating if we are remembering a line, and the actual line itself.

  • rendering/RenderBlockLineLayout.cpp:

(WebCore::RenderBlock::layoutRunsAndFloatsInRange): The code to detect and fix widows. Explained above.

  • rendering/style/RenderStyle.h: New methods for indicating if widows and orphans are non-default values.
  • rendering/style/StyleRareInheritedData.cpp: Ditto.
  • rendering/style/StyleRareInheritedData.h: Ditto.

LayoutTests:

A new, slightly more comprehensive, test for widows and orphans. We also
now pass the existing widows and orphans tests from printing. And
since the default value of the properties changed, update the
computed style test as well.

  • fast/css/getComputedStyle/computed-style-expected.txt: New auto value.
  • fast/css/getComputedStyle/computed-style-without-renderer-expected.txt: New auto value.
  • fast/multicol/widows-and-orphans-expected.txt: Added.
  • fast/multicol/widows-and-orphans.html: Added.
  • printing/page-break-orphans-and-widows-expected.txt:
  • printing/page-break-orphans-expected.txt:
  • printing/page-break-widows-expected.txt:
  • svg/css/getComputedStyle-basic-expected.txt: New auto value.
Location:
trunk
Files:
2 added
18 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r137191 r137200  
     12012-12-10  Dean Jackson  <dino@apple.com>
     2
     3        Support for CSS widows and orphans
     4        https://bugs.webkit.org/show_bug.cgi?id=9410
     5
     6        Reviewed by Darin Adler.
     7
     8        A new, slightly more comprehensive, test for widows and orphans. We also
     9        now pass the existing widows and orphans tests from printing. And
     10        since the default value of the properties changed, update the
     11        computed style test as well.
     12
     13        * fast/css/getComputedStyle/computed-style-expected.txt: New auto value.
     14        * fast/css/getComputedStyle/computed-style-without-renderer-expected.txt: New auto value.
     15        * fast/multicol/widows-and-orphans-expected.txt: Added.
     16        * fast/multicol/widows-and-orphans.html: Added.
     17        * printing/page-break-orphans-and-widows-expected.txt:
     18        * printing/page-break-orphans-expected.txt:
     19        * printing/page-break-widows-expected.txt:
     20        * svg/css/getComputedStyle-basic-expected.txt: New auto value.
     21
    1222012-12-10  Christophe Dumez  <christophe.dumez@intel.com>
    223
  • trunk/LayoutTests/fast/css/getComputedStyle/computed-style-expected.txt

    r136080 r137200  
    6464min-width: 0px;
    6565opacity: 1;
    66 orphans: 2;
     66orphans: auto;
    6767outline-color: rgb(0, 0, 0);
    6868outline-style: none;
     
    9696visibility: visible;
    9797white-space: normal;
    98 widows: 2;
     98widows: auto;
    9999width: 784px;
    100100word-break: normal;
  • trunk/LayoutTests/fast/css/getComputedStyle/computed-style-without-renderer-expected.txt

    r136080 r137200  
    6363min-width: 0px
    6464opacity: 1
    65 orphans: 2
     65orphans: auto
    6666outline-color: rgb(0, 0, 0)
    6767outline-style: none
     
    9595visibility: visible
    9696white-space: normal
    97 widows: 2
     97widows: auto
    9898width: 50%
    9999word-break: normal
  • trunk/LayoutTests/printing/page-break-orphans-and-widows-expected.txt

    r61502 r137200  
    99PASS: page number of "page1-3" is 1
    1010PASS: page number of "page2" is 2
    11 FAIL: expected page number of "page3" is 3. Was 2
     11PASS: page number of "page3" is 3
    1212PASS: page number of "page4" is 4
    1313FAIL: expected page number of "page5" is 5. Was 4
  • trunk/LayoutTests/printing/page-break-orphans-expected.txt

    r61502 r137200  
    88PASS: page number of "page1-2" is 1
    99PASS: page number of "page3" is 3
    10 FAIL: expected page number of "page4" is 4. Was 3
     10PASS: page number of "page4" is 4
    1111PASS: page number of "page5-1" is 5
    1212PASS: page number of "page5-2" is 5
     13All tests passed
    1314
    1415PASS successfullyParsed is true
  • trunk/LayoutTests/printing/page-break-widows-expected.txt

    r61502 r137200  
    1212PASS: page number of "page3-2" is 3
    1313PASS: page number of "page4" is 4
    14 FAIL: expected page number of "page5" is 5. Was 4
     14PASS: page number of "page5" is 5
     15All tests passed
    1516
    1617PASS successfullyParsed is true
  • trunk/LayoutTests/svg/css/getComputedStyle-basic-expected.txt

    r136080 r137200  
    125125rect: style.getPropertyValue(opacity) : 1
    126126rect: style.getPropertyCSSValue(opacity) : [object CSSPrimitiveValue]
    127 rect: style.getPropertyValue(orphans) : 2
     127rect: style.getPropertyValue(orphans) : auto
    128128rect: style.getPropertyCSSValue(orphans) : [object CSSPrimitiveValue]
    129129rect: style.getPropertyValue(outline-color) : rgb(0, 0, 0)
     
    189189rect: style.getPropertyValue(white-space) : normal
    190190rect: style.getPropertyCSSValue(white-space) : [object CSSPrimitiveValue]
    191 rect: style.getPropertyValue(widows) : 2
     191rect: style.getPropertyValue(widows) : auto
    192192rect: style.getPropertyCSSValue(widows) : [object CSSPrimitiveValue]
    193193rect: style.getPropertyValue(width) : auto
     
    625625g: style.getPropertyValue(opacity) : 1
    626626g: style.getPropertyCSSValue(opacity) : [object CSSPrimitiveValue]
    627 g: style.getPropertyValue(orphans) : 2
     627g: style.getPropertyValue(orphans) : auto
    628628g: style.getPropertyCSSValue(orphans) : [object CSSPrimitiveValue]
    629629g: style.getPropertyValue(outline-color) : rgb(0, 0, 0)
     
    689689g: style.getPropertyValue(white-space) : normal
    690690g: style.getPropertyCSSValue(white-space) : [object CSSPrimitiveValue]
    691 g: style.getPropertyValue(widows) : 2
     691g: style.getPropertyValue(widows) : auto
    692692g: style.getPropertyCSSValue(widows) : [object CSSPrimitiveValue]
    693693g: style.getPropertyValue(width) : auto
  • trunk/Source/WebCore/ChangeLog

    r137198 r137200  
     12012-12-10  Dean Jackson  <dino@apple.com>
     2
     3        Support for CSS widows and orphans
     4        https://bugs.webkit.org/show_bug.cgi?id=9410
     5
     6        Reviewed by Darin Adler.
     7
     8        The CSS 'widow' and 'orphan' properties were supported by the parser and
     9        style system, but were not actually doing anything in layout. Now they do!
     10
     11        In order to not break existing content, I unfortunately had to go against
     12        the specification and change our default value from 2 to auto. A value of
     13        auto means that widows and orphans will not cause any page/column breaks.
     14
     15        Supporting orphans was a small change. During line layout, if we realise
     16        we need to move to a new page in a situation that would create an orphan,
     17        move the entire block to the new page. There was already code to do this.
     18
     19        Support for widows was trickier. When we finish laying out a block, count
     20        the number of hanging lines. If we've created a widow, and there are enough
     21        available lines on the previous page, then steal some and remember the line
     22        to break at. Trigger a relayout. Then notice the line that was marked for
     23        breaking and avoid the widow. This means some blocks go through layout
     24        twice, but as long as the widow value is small it shouldn't be a huge penalty.
     25
     26        Tests: fast/multicol/widows-and-orphans.html (new test)
     27               printing/page-break-orphans.html
     28               printing/page-break-orphans-and-widows.html
     29               printing/page-break-widows.html
     30
     31        * css/CSSComputedStyleDeclaration.cpp:
     32        (WebCore::CSSComputedStyleDeclaration::getPropertyCSSValue): Return CSSValueAuto for widows and orphans if necessary.
     33        * css/CSSParser.cpp:
     34        (WebCore::CSSParser::parseValue): Support "auto" in widow and orphan property parsing.
     35        * css/StyleBuilder.cpp:
     36        (WebCore::StyleBuilder::StyleBuilder): Change property handler to something that supports auto.
     37        * page/animation/CSSPropertyAnimation.cpp:
     38        (WebCore::CSSPropertyAnimation::ensurePropertyMap): Add widows and orphans to the animation map.
     39        * rendering/RenderBlock.cpp:
     40        (WebCore::RenderBlock::layoutBlockChild): Detect if we've caused a widow-fixing break, and request relayout evaluation.
     41        (WebCore::RenderBlock::markForPaginationRelayoutIfNeeded): Test for a widow-fixing line.
     42        (WebCore::RenderBlock::setBreakAtLineToAvoidWidow): New function to remember where we should break on next layout.
     43        (WebCore::RenderBlock::adjustLinePositionForPagination): Move the entire block to a new page if this would create an orphan.
     44        * rendering/RenderBlock.h:
     45        (WebCore::RenderBlock::shouldBreakAtLineToAvoidWidow): New function to indicate if we are remembering a widow.
     46        (WebCore::RenderBlock::clearShouldBreakAtLineToAvoidWidow): Reset the line breaks.
     47        (WebCore::RenderBlock::lineBreakToAvoidWidow):
     48        (WebCore::RenderBlock::RenderBlockRareData::RenderBlockRareData): Add a flag for indicating if we are remembering a line, and the actual line itself.
     49        * rendering/RenderBlockLineLayout.cpp:
     50        (WebCore::RenderBlock::layoutRunsAndFloatsInRange): The code to detect and fix widows. Explained above.
     51        * rendering/style/RenderStyle.h: New methods for indicating if widows and orphans are non-default values.
     52        * rendering/style/StyleRareInheritedData.cpp: Ditto.
     53        * rendering/style/StyleRareInheritedData.h: Ditto.
     54
    1552012-12-10  Zan Dobersek  <zandobersek@gmail.com>
    256
  • trunk/Source/WebCore/css/CSSComputedStyleDeclaration.cpp

    r137007 r137200  
    20012001            return cssValuePool().createValue(style->opacity(), CSSPrimitiveValue::CSS_NUMBER);
    20022002        case CSSPropertyOrphans:
     2003            if (style->hasAutoOrphans())
     2004                return cssValuePool().createIdentifierValue(CSSValueAuto);
    20032005            return cssValuePool().createValue(style->orphans(), CSSPrimitiveValue::CSS_NUMBER);
    20042006        case CSSPropertyOutlineColor:
     
    21492151            return cssValuePool().createValue(style->whiteSpace());
    21502152        case CSSPropertyWidows:
     2153            if (style->hasAutoWidows())
     2154                return cssValuePool().createIdentifierValue(CSSValueAuto);
    21512155            return cssValuePool().createValue(style->widows(), CSSPrimitiveValue::CSS_NUMBER);
    21522156        case CSSPropertyWidth:
  • trunk/Source/WebCore/css/CSSParser.cpp

    r137166 r137200  
    21542154        }
    21552155        /* nobreak */
    2156     case CSSPropertyOrphans:              // <integer> | inherit
    2157     case CSSPropertyWidows:               // <integer> | inherit
    2158         // ### not supported later on
    2159         validPrimitive = (!id && validUnit(value, FInteger, CSSQuirksMode));
     2156    case CSSPropertyOrphans: // <integer> | inherit | auto (We've added support for auto for backwards compatibility)
     2157    case CSSPropertyWidows: // <integer> | inherit | auto (Ditto)
     2158        if (id == CSSValueAuto)
     2159            validPrimitive = true;
     2160        else
     2161            validPrimitive = (!id && validUnit(value, FInteger, CSSQuirksMode));
    21602162        break;
    21612163
  • trunk/Source/WebCore/css/StyleBuilder.cpp

    r136919 r137200  
    18961896    setPropertyHandler(CSSPropertyMinWidth, ApplyPropertyLength<&RenderStyle::minWidth, &RenderStyle::setMinWidth, &RenderStyle::initialMinSize, AutoEnabled, LegacyIntrinsicEnabled, IntrinsicEnabled>::createHandler());
    18971897    setPropertyHandler(CSSPropertyOpacity, ApplyPropertyDefault<float, &RenderStyle::opacity, float, &RenderStyle::setOpacity, float, &RenderStyle::initialOpacity>::createHandler());
    1898     setPropertyHandler(CSSPropertyOrphans, ApplyPropertyDefault<short, &RenderStyle::orphans, short, &RenderStyle::setOrphans, short, &RenderStyle::initialOrphans>::createHandler());
     1898    setPropertyHandler(CSSPropertyOrphans, ApplyPropertyAuto<short, &RenderStyle::orphans, &RenderStyle::setOrphans, &RenderStyle::hasAutoOrphans, &RenderStyle::setHasAutoOrphans>::createHandler());
    18991899    setPropertyHandler(CSSPropertyOutline, ApplyPropertyExpanding<SuppressValue, CSSPropertyOutlineWidth, CSSPropertyOutlineColor, CSSPropertyOutlineStyle>::createHandler());
    19001900    setPropertyHandler(CSSPropertyOutlineColor, ApplyPropertyColor<NoInheritFromParent, &RenderStyle::outlineColor, &RenderStyle::setOutlineColor, &RenderStyle::setVisitedLinkOutlineColor, &RenderStyle::color>::createHandler());
     
    20822082#endif
    20832083    setPropertyHandler(CSSPropertyWhiteSpace, ApplyPropertyDefault<EWhiteSpace, &RenderStyle::whiteSpace, EWhiteSpace, &RenderStyle::setWhiteSpace, EWhiteSpace, &RenderStyle::initialWhiteSpace>::createHandler());
    2084     setPropertyHandler(CSSPropertyWidows, ApplyPropertyDefault<short, &RenderStyle::widows, short, &RenderStyle::setWidows, short, &RenderStyle::initialWidows>::createHandler());
     2084    setPropertyHandler(CSSPropertyWidows, ApplyPropertyAuto<short, &RenderStyle::widows, &RenderStyle::setWidows, &RenderStyle::hasAutoWidows, &RenderStyle::setHasAutoWidows>::createHandler());
    20852085    setPropertyHandler(CSSPropertyWidth, ApplyPropertyLength<&RenderStyle::width, &RenderStyle::setWidth, &RenderStyle::initialSize, AutoEnabled, LegacyIntrinsicEnabled, IntrinsicEnabled, NoneDisabled, UndefinedDisabled>::createHandler());
    20862086    setPropertyHandler(CSSPropertyWordBreak, ApplyPropertyDefault<EWordBreak, &RenderStyle::wordBreak, EWordBreak, &RenderStyle::setWordBreak, EWordBreak, &RenderStyle::initialWordBreak>::createHandler());
  • trunk/Source/WebCore/page/animation/CSSPropertyAnimation.cpp

    r135314 r137200  
    11311131    gPropertyWrappers->append(new PropertyWrapper<short>(CSSPropertyWebkitBorderVerticalSpacing, &RenderStyle::verticalBorderSpacing, &RenderStyle::setVerticalBorderSpacing));
    11321132    gPropertyWrappers->append(new PropertyWrapper<int>(CSSPropertyZIndex, &RenderStyle::zIndex, &RenderStyle::setZIndex));
     1133    gPropertyWrappers->append(new PropertyWrapper<short>(CSSPropertyOrphans, &RenderStyle::orphans, &RenderStyle::setOrphans));
     1134    gPropertyWrappers->append(new PropertyWrapper<short>(CSSPropertyWidows, &RenderStyle::widows, &RenderStyle::setWidows));
    11331135    gPropertyWrappers->append(new PropertyWrapper<Length>(CSSPropertyLineHeight, &RenderStyle::specifiedLineHeight, &RenderStyle::setLineHeight));
    11341136    gPropertyWrappers->append(new PropertyWrapper<int>(CSSPropertyOutlineOffset, &RenderStyle::outlineOffset, &RenderStyle::setOutlineOffset));
  • trunk/Source/WebCore/rendering/RenderBlock.cpp

    r137108 r137200  
    25182518    // clearFloatsIfNeeded can also mark the child as needing a layout even though we didn't move. This happens
    25192519    // when collapseMargins dynamically adds overhanging floats because of a child with negative margins.
    2520     if (logicalTopAfterClear != logicalTopEstimate || child->needsLayout()) {
     2520    if (logicalTopAfterClear != logicalTopEstimate || child->needsLayout() || (paginated && childRenderBlock && childRenderBlock->shouldBreakAtLineToAvoidWidow())) {
    25212521        if (child->shrinkToAvoidFloats()) {
    25222522            // The child's width depends on the line width.
     
    27252725        return;
    27262726
    2727     if (view()->layoutState()->pageLogicalHeightChanged() || (view()->layoutState()->pageLogicalHeight() && view()->layoutState()->pageLogicalOffset(this, logicalTop()) != pageLogicalOffset()))
     2727    if (view()->layoutState()->pageLogicalHeightChanged() || (view()->layoutState()->pageLogicalHeight() && view()->layoutState()->pageLogicalOffset(this, logicalTop()) != pageLogicalOffset()) || shouldBreakAtLineToAvoidWidow())
    27282728        setChildNeedsLayout(true, MarkOnlyThis);
    27292729}
     
    67756775    }
    67766776    m_rareData->m_pageLogicalOffset = logicalOffset;
     6777}
     6778
     6779void RenderBlock::setBreakAtLineToAvoidWidow(RootInlineBox* lineToBreak)
     6780{
     6781    ASSERT(lineToBreak);
     6782    if (!m_rareData)
     6783        m_rareData = adoptPtr(new RenderBlockRareData(this));
     6784    m_rareData->m_shouldBreakAtLineToAvoidWidow = true;
     6785    m_rareData->m_lineBreakToAvoidWidow = lineToBreak;
     6786}
     6787
     6788void RenderBlock::clearShouldBreakAtLineToAvoidWidow() const
     6789{
     6790    if (!m_rareData)
     6791        return;
     6792    m_rareData->m_shouldBreakAtLineToAvoidWidow = false;
     6793    m_rareData->m_lineBreakToAvoidWidow = 0;
    67776794}
    67786795
     
    71607177        return;
    71617178    LayoutUnit remainingLogicalHeight = pageRemainingLogicalHeightForOffset(logicalOffset, ExcludePageBoundary);
    7162     if (remainingLogicalHeight < lineHeight) {
     7179
     7180    if (remainingLogicalHeight < lineHeight || (shouldBreakAtLineToAvoidWidow() && lineBreakToAvoidWidow() == lineBox)) {
     7181        if (shouldBreakAtLineToAvoidWidow() && lineBreakToAvoidWidow() == lineBox)
     7182            clearShouldBreakAtLineToAvoidWidow();
    71637183        // If we have a non-uniform page height, then we have to shift further possibly.
    71647184        if (!hasUniformPageLogicalHeight && !pushToNextPageWithMinimumLogicalHeight(remainingLogicalHeight, logicalOffset, lineHeight))
     
    71707190        LayoutUnit totalLogicalHeight = lineHeight + max<LayoutUnit>(0, logicalOffset);
    71717191        LayoutUnit pageLogicalHeightAtNewOffset = hasUniformPageLogicalHeight ? pageLogicalHeight : pageLogicalHeightForOffset(logicalOffset + remainingLogicalHeight);
    7172         if (lineBox == firstRootBox() && totalLogicalHeight < pageLogicalHeightAtNewOffset && !isOutOfFlowPositioned() && !isTableCell())
     7192        if (((lineBox == firstRootBox() && totalLogicalHeight < pageLogicalHeightAtNewOffset) || (!style()->hasAutoOrphans() && style()->orphans() >= lineCount()))
     7193            && !isOutOfFlowPositioned() && !isTableCell())
    71737194            setPaginationStrut(remainingLogicalHeight + max<LayoutUnit>(0, logicalOffset));
    71747195        else {
  • trunk/Source/WebCore/rendering/RenderBlock.h

    r137135 r137200  
    307307    LayoutUnit paginationStrut() const { return m_rareData ? m_rareData->m_paginationStrut : LayoutUnit(); }
    308308    void setPaginationStrut(LayoutUnit);
    309    
     309
     310    bool shouldBreakAtLineToAvoidWidow() const { return m_rareData && m_rareData->m_shouldBreakAtLineToAvoidWidow; }
     311    void clearShouldBreakAtLineToAvoidWidow() const;
     312    RootInlineBox* lineBreakToAvoidWidow() const { return m_rareData ? m_rareData->m_lineBreakToAvoidWidow : 0; }
     313    void setBreakAtLineToAvoidWidow(RootInlineBox*);
     314
    310315    // The page logical offset is the object's offset from the top of the page in the page progression
    311316    // direction (so an x-offset in vertical text and a y-offset for horizontal text).
     
    11501155            , m_pageLogicalOffset(0)
    11511156            , m_lineGridBox(0)
     1157            , m_shouldBreakAtLineToAvoidWidow(false)
     1158            , m_lineBreakToAvoidWidow(0)
    11521159        {
    11531160        }
     
    11761183       
    11771184        RootInlineBox* m_lineGridBox;
     1185
     1186        bool m_shouldBreakAtLineToAvoidWidow;
     1187        RootInlineBox* m_lineBreakToAvoidWidow;
    11781188     };
    11791189
  • trunk/Source/WebCore/rendering/RenderBlockLineLayout.cpp

    r136967 r137200  
    16421642        lineMidpointState.reset();
    16431643        resolver.setPosition(end, numberOfIsolateAncestors(end));
     1644    }
     1645
     1646    if (paginated && !style()->hasAutoWidows()) {
     1647        // Check the line boxes to make sure we didn't create unacceptable widows.
     1648        // However, we'll prioritize orphans - so nothing we do here should create
     1649        // a new orphan.
     1650
     1651        RootInlineBox* lineBox = lastRootBox();
     1652
     1653        // Count from the end of the block backwards, to see how many hanging
     1654        // lines we have.
     1655        RootInlineBox* firstLineInBlock = firstRootBox();
     1656        int numLinesHanging = 1;
     1657        while (lineBox && lineBox != firstLineInBlock && !lineBox->isFirstAfterPageBreak()) {
     1658            ++numLinesHanging;
     1659            lineBox = lineBox->prevRootBox();
     1660        }
     1661
     1662        // If there were no breaks in the block, we didn't create any widows.
     1663        if (!lineBox->isFirstAfterPageBreak() || lineBox == firstLineInBlock)
     1664            return;
     1665
     1666        if (numLinesHanging < style()->widows()) {
     1667            // We have detected a widow. Now we need to work out how many
     1668            // lines there are on the previous page, and how many we need
     1669            // to steal.
     1670            int numLinesNeeded = style()->widows() - numLinesHanging;
     1671            RootInlineBox* currentFirstLineOfNewPage = lineBox;
     1672
     1673            // Count the number of lines in the previous page.
     1674            lineBox = lineBox->prevRootBox();
     1675            int numLinesInPreviousPage = 1;
     1676            while (lineBox && lineBox != firstLineInBlock && !lineBox->isFirstAfterPageBreak()) {
     1677                ++numLinesInPreviousPage;
     1678                lineBox = lineBox->prevRootBox();
     1679            }
     1680
     1681            // If there was an explicit value for orphans, respect that. If not, we still
     1682            // shouldn't create a situation where we make an orphan bigger than the initial value.
     1683            // This means that setting widows implies we also care about orphans, but given
     1684            // the specification says the initial orphan value is non-zero, this is ok. The
     1685            // author is always free to set orphans explicitly as well.
     1686            int orphans = style()->hasAutoOrphans() ? style()->initialOrphans() : style()->orphans();
     1687            int numLinesAvailable = numLinesInPreviousPage - orphans;
     1688            if (numLinesAvailable <= 0)
     1689                return;
     1690
     1691            int numLinesToTake = min(numLinesAvailable, numLinesNeeded);
     1692            // Wind back from our first widowed line.
     1693            lineBox = currentFirstLineOfNewPage;
     1694            for (int i = 0; i < numLinesToTake; ++i)
     1695                lineBox = lineBox->prevRootBox();
     1696
     1697            // We now want to break at this line. Remember for next layout and trigger relayout.
     1698            setBreakAtLineToAvoidWidow(lineBox);
     1699            markLinesDirtyInBlockRange(lastRootBox()->lineBottomWithLeading(), lineBox->lineBottomWithLeading(), lineBox);
     1700        }
    16441701    }
    16451702}
  • trunk/Source/WebCore/rendering/style/RenderStyle.h

    r136640 r137200  
    707707    short widows() const { return rareInheritedData->widows; }
    708708    short orphans() const { return rareInheritedData->orphans; }
     709    bool hasAutoWidows() const { return rareInheritedData->m_hasAutoWidows; }
     710    bool hasAutoOrphans() const { return rareInheritedData->m_hasAutoOrphans; }
    709711    EPageBreak pageBreakInside() const { return static_cast<EPageBreak>(noninherited_flags._page_break_inside); }
    710712    EPageBreak pageBreakBefore() const { return static_cast<EPageBreak>(noninherited_flags._page_break_before); }
     
    11991201    void setZIndex(int v) { SET_VAR(m_box, m_hasAutoZIndex, false); SET_VAR(m_box, m_zIndex, v) }
    12001202
    1201     void setWidows(short w) { SET_VAR(rareInheritedData, widows, w); }
    1202     void setOrphans(short o) { SET_VAR(rareInheritedData, orphans, o); }
     1203    void setHasAutoWidows() { SET_VAR(rareInheritedData, m_hasAutoWidows, true); SET_VAR(rareInheritedData, widows, initialWidows()) }
     1204    void setWidows(short w) { SET_VAR(rareInheritedData, m_hasAutoWidows, false); SET_VAR(rareInheritedData, widows, w); }
     1205
     1206    void setHasAutoOrphans() { SET_VAR(rareInheritedData, m_hasAutoOrphans, true); SET_VAR(rareInheritedData, orphans, initialOrphans()) }
     1207    void setOrphans(short o) { SET_VAR(rareInheritedData, m_hasAutoOrphans, false); SET_VAR(rareInheritedData, orphans, o); }
     1208
    12031209    // For valid values of page-break-inside see http://www.w3.org/TR/CSS21/page.html#page-break-props
    12041210    void setPageBreakInside(EPageBreak b) { ASSERT(b == PBAUTO || b == PBAVOID); noninherited_flags._page_break_inside = b; }
  • trunk/Source/WebCore/rendering/style/StyleRareInheritedData.cpp

    r136640 r137200  
    7171    , widows(RenderStyle::initialWidows())
    7272    , orphans(RenderStyle::initialOrphans())
     73    , m_hasAutoWidows(true)
     74    , m_hasAutoOrphans(true)
    7375    , textSecurity(RenderStyle::initialTextSecurity())
    7476    , userModify(READ_ONLY)
     
    138140    , widows(o.widows)
    139141    , orphans(o.orphans)
     142    , m_hasAutoWidows(o.m_hasAutoWidows)
     143    , m_hasAutoOrphans(o.m_hasAutoOrphans)
    140144    , textSecurity(o.textSecurity)
    141145    , userModify(o.userModify)
     
    223227        && widows == o.widows
    224228        && orphans == o.orphans
     229        && m_hasAutoWidows == o.m_hasAutoWidows
     230        && m_hasAutoOrphans == o.m_hasAutoOrphans
    225231        && textSecurity == o.textSecurity
    226232        && userModify == o.userModify
  • trunk/Source/WebCore/rendering/style/StyleRareInheritedData.h

    r136640 r137200  
    8383    short widows;
    8484    short orphans;
     85    unsigned m_hasAutoWidows : 1;
     86    unsigned m_hasAutoOrphans : 1;
    8587   
    8688    unsigned textSecurity : 2; // ETextSecurity
Note: See TracChangeset for help on using the changeset viewer.