Title: [122244] trunk
Revision
122244
Author
[email protected]
Date
2012-07-10 12:14:25 -0700 (Tue, 10 Jul 2012)

Log Message

Source/WebCore: https://bugs.webkit.org/show_bug.cgi?id=90646
<rdar://problem/11648478> 3-pass pagination slows down pagination

Improve the logical top estimate function for margin collapsing to be more accurate. In particular
make the basic case of <body><p> or <body><h1> no longer be wrong. This estimate being incorrect
is not a big deal most of the time, but when paginating it is a very big deal, since you have to
relayout everything whenever your vertical placement is wrong.

Improving the estimation exposed a bug in an existing layout test. I had to clean up the buggy
code written for negative margin-related float detection and fix an invalid layout test to
actually be correct.

Reviewed by Simon Fraser.

* rendering/RenderBlock.cpp:
(WebCore::RenderBlock::collapseMargins):
(WebCore::RenderBlock::marginBeforeEstimateForChild):
(WebCore):
(WebCore::RenderBlock::estimateLogicalTopPosition):
(WebCore::RenderBlock::marginValuesForChild):
* rendering/RenderBlock.h:
(RenderBlock):
* rendering/RenderBox.cpp:
(WebCore::RenderBox::shrinkLogicalWidthToAvoidFloats):
(WebCore::RenderBox::computeLogicalWidthInRegionUsing):

LayoutTests: https://bugs.webkit.org/show_bug.cgi?id=90646

Fix invalid layout test exposed by my changes to logical top estimation.

Reviewed by Simon Fraser.

* fast/block/float/previous-sibling-float-002-expected.html:
* fast/block/float/previous-sibling-float-002.html:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (122243 => 122244)


--- trunk/LayoutTests/ChangeLog	2012-07-10 19:10:43 UTC (rev 122243)
+++ trunk/LayoutTests/ChangeLog	2012-07-10 19:14:25 UTC (rev 122244)
@@ -1,3 +1,14 @@
+2012-07-06  David Hyatt  <[email protected]>
+
+        https://bugs.webkit.org/show_bug.cgi?id=90646
+
+        Fix invalid layout test exposed by my changes to logical top estimation.
+
+        Reviewed by Simon Fraser.
+
+        * fast/block/float/previous-sibling-float-002-expected.html:
+        * fast/block/float/previous-sibling-float-002.html:
+
 2012-07-10  Rafael Weinstein  <[email protected]>
 
         Unreviewed gardening. tables/mozilla_expected_failures/other/empty_cells.html marked as flaky.

Modified: trunk/LayoutTests/fast/block/float/previous-sibling-float-002-expected.html (122243 => 122244)


--- trunk/LayoutTests/fast/block/float/previous-sibling-float-002-expected.html	2012-07-10 19:10:43 UTC (rev 122243)
+++ trunk/LayoutTests/fast/block/float/previous-sibling-float-002-expected.html	2012-07-10 19:14:25 UTC (rev 122244)
@@ -8,7 +8,7 @@
             {
                 background-color:green;
                 width: 400px;
-                height: 30px;
+                height: 40px;
             }
         </style>
     </head>

Modified: trunk/LayoutTests/fast/block/float/previous-sibling-float-002.html (122243 => 122244)


--- trunk/LayoutTests/fast/block/float/previous-sibling-float-002.html	2012-07-10 19:10:43 UTC (rev 122243)
+++ trunk/LayoutTests/fast/block/float/previous-sibling-float-002.html	2012-07-10 19:14:25 UTC (rev 122244)
@@ -8,6 +8,8 @@
             {
                 background-color:green;
                 width: 400px;
+                overflow: hidden;
+                height:40px
             }
             #div1
             {
@@ -16,7 +18,7 @@
             #float-right
             {
                 float: right; 
-                height: 20px; 
+                height: 40px; 
                 width: 400px; 
                 background-color: green;
             }

Modified: trunk/Source/WebCore/ChangeLog (122243 => 122244)


--- trunk/Source/WebCore/ChangeLog	2012-07-10 19:10:43 UTC (rev 122243)
+++ trunk/Source/WebCore/ChangeLog	2012-07-10 19:14:25 UTC (rev 122244)
@@ -1,3 +1,31 @@
+2012-07-06  David Hyatt  <[email protected]>
+
+        https://bugs.webkit.org/show_bug.cgi?id=90646
+        <rdar://problem/11648478> 3-pass pagination slows down pagination
+
+        Improve the logical top estimate function for margin collapsing to be more accurate. In particular
+        make the basic case of <body><p> or <body><h1> no longer be wrong. This estimate being incorrect
+        is not a big deal most of the time, but when paginating it is a very big deal, since you have to
+        relayout everything whenever your vertical placement is wrong.
+
+        Improving the estimation exposed a bug in an existing layout test. I had to clean up the buggy
+        code written for negative margin-related float detection and fix an invalid layout test to
+        actually be correct.
+
+        Reviewed by Simon Fraser.
+
+        * rendering/RenderBlock.cpp:
+        (WebCore::RenderBlock::collapseMargins):
+        (WebCore::RenderBlock::marginBeforeEstimateForChild):
+        (WebCore):
+        (WebCore::RenderBlock::estimateLogicalTopPosition):
+        (WebCore::RenderBlock::marginValuesForChild):
+        * rendering/RenderBlock.h:
+        (RenderBlock):
+        * rendering/RenderBox.cpp:
+        (WebCore::RenderBox::shrinkLogicalWidthToAvoidFloats):
+        (WebCore::RenderBox::computeLogicalWidthInRegionUsing):
+
 2012-07-10  Alexei Filippov  <[email protected]>
 
         Web Inspector: Count inspector memory used to traverse DOM in native memory snapshots.

Modified: trunk/Source/WebCore/rendering/RenderBlock.cpp (122243 => 122244)


--- trunk/Source/WebCore/rendering/RenderBlock.cpp	2012-07-10 19:10:43 UTC (rev 122243)
+++ trunk/Source/WebCore/rendering/RenderBlock.cpp	2012-07-10 19:14:25 UTC (rev 122244)
@@ -2033,7 +2033,7 @@
     RenderObject* prev = child->previousSibling();
     if (prev && prev->isBlockFlow() && !prev->isFloatingOrOutOfFlowPositioned()) {
         RenderBlock* block = toRenderBlock(prev);
-        if (block->containsFloats() && block->lowestFloatLogicalBottom() > logicalTop) 
+        if (block->containsFloats() && !block->avoidsFloats() && (block->logicalTop() + block->lowestFloatLogicalBottom()) > logicalTop) 
             addOverhangingFloats(block, false);
     }
 
@@ -2089,14 +2089,60 @@
     return yPos + heightIncrease;
 }
 
+void RenderBlock::marginBeforeEstimateForChild(RenderBox* child, LayoutUnit& positiveMarginBefore, LayoutUnit& negativeMarginBefore) const
+{
+    // FIXME: We could get even more quirks mode cases right if we dealt with quirk containers.
+    // FIXME: We should deal with the margin-collapse-* style extensions that prevent collapsing and that discard margins.
+    LayoutUnit beforeChildMargin = marginBeforeForChild(child);
+    positiveMarginBefore = max(positiveMarginBefore, beforeChildMargin);
+    negativeMarginBefore = max(negativeMarginBefore, -beforeChildMargin);
+
+    if (!child->isRenderBlock())
+        return;
+    
+    RenderBlock* childBlock = toRenderBlock(child);
+    if (childBlock->childrenInline() || childBlock->isWritingModeRoot())
+        return;
+
+    MarginInfo childMarginInfo(childBlock, childBlock->borderBefore() + childBlock->paddingBefore(), childBlock->borderAfter() + childBlock->paddingAfter());
+    if (!childMarginInfo.canCollapseMarginBeforeWithChildren())
+        return;
+
+    RenderBox* grandchildBox = childBlock->firstChildBox();
+    for ( ; grandchildBox; grandchildBox = grandchildBox->nextSiblingBox()) {
+        if (!grandchildBox->isFloatingOrOutOfFlowPositioned())
+            break;
+    }
+    
+    // Give up if there is clearance on the box, since it probably won't collapse into us.
+    if (!grandchildBox || grandchildBox->style()->clear() != CNONE)
+        return;
+
+    // Collapse the margin of the grandchild box with our own to produce an estimate.
+    childBlock->marginBeforeEstimateForChild(grandchildBox, positiveMarginBefore, negativeMarginBefore);
+}
+
 LayoutUnit RenderBlock::estimateLogicalTopPosition(RenderBox* child, const MarginInfo& marginInfo, LayoutUnit& estimateWithoutPagination)
 {
     // FIXME: We need to eliminate the estimation of vertical position, because when it's wrong we sometimes trigger a pathological
     // relayout if there are intruding floats.
     LayoutUnit logicalTopEstimate = logicalHeight();
     if (!marginInfo.canCollapseWithMarginBefore()) {
-        LayoutUnit childMarginBefore = child->selfNeedsLayout() ? marginBeforeForChild(child) : collapsedMarginBeforeForChild(child);
-        logicalTopEstimate += max(marginInfo.margin(), childMarginBefore);
+        LayoutUnit positiveMarginBefore = ZERO_LAYOUT_UNIT;
+        LayoutUnit negativeMarginBefore = ZERO_LAYOUT_UNIT;
+        if (child->selfNeedsLayout()) {
+            // Try to do a basic estimation of how the collapse is going to go.
+            marginBeforeEstimateForChild(child, positiveMarginBefore, negativeMarginBefore);
+        } else {
+            // Use the cached collapsed margin values from a previous layout. Most of the time they
+            // will be right.
+            MarginValues marginValues = marginValuesForChild(child);
+            positiveMarginBefore = max(positiveMarginBefore, marginValues.positiveMarginBefore());
+            negativeMarginBefore = max(negativeMarginBefore, marginValues.negativeMarginBefore());
+        }
+
+        // Collapse the result with our current margins.
+        logicalTopEstimate += max(marginInfo.positiveMargin(), positiveMarginBefore) - max(marginInfo.negativeMargin(), negativeMarginBefore);
     }
 
     // Adjust logicalTopEstimate down to the next page if the margins are so large that we don't fit on the current
@@ -7065,7 +7111,7 @@
     return marginAfterForChild(child);
 }
 
-RenderBlock::MarginValues RenderBlock::marginValuesForChild(RenderBox* child)
+RenderBlock::MarginValues RenderBlock::marginValuesForChild(RenderBox* child) const
 {
     LayoutUnit childBeforePositive = 0;
     LayoutUnit childBeforeNegative = 0;

Modified: trunk/Source/WebCore/rendering/RenderBlock.h (122243 => 122244)


--- trunk/Source/WebCore/rendering/RenderBlock.h	2012-07-10 19:10:43 UTC (rev 122243)
+++ trunk/Source/WebCore/rendering/RenderBlock.h	2012-07-10 19:14:25 UTC (rev 122244)
@@ -331,7 +331,7 @@
         LayoutUnit m_positiveMarginAfter;
         LayoutUnit m_negativeMarginAfter;
     };
-    MarginValues marginValuesForChild(RenderBox* child);
+    MarginValues marginValuesForChild(RenderBox* child) const;
 
     virtual void scrollbarsChanged(bool /*horizontalScrollbarChanged*/, bool /*verticalScrollbarChanged*/) { };
 
@@ -921,6 +921,7 @@
     LayoutUnit collapseMargins(RenderBox* child, MarginInfo&);
     LayoutUnit clearFloatsIfNeeded(RenderBox* child, MarginInfo&, LayoutUnit oldTopPosMargin, LayoutUnit oldTopNegMargin, LayoutUnit yPos);
     LayoutUnit estimateLogicalTopPosition(RenderBox* child, const MarginInfo&, LayoutUnit& estimateWithoutPagination);
+    void marginBeforeEstimateForChild(RenderBox* child, LayoutUnit& positiveMarginBefore, LayoutUnit& negativeMarginBefore) const;
     void determineLogicalLeftPositionForChild(RenderBox* child);
     void handleAfterSideOfBlock(LayoutUnit top, LayoutUnit bottom, MarginInfo&);
     void setCollapsedBottomMargin(const MarginInfo&);

Modified: trunk/Source/WebCore/rendering/RenderBox.cpp (122243 => 122244)


--- trunk/Source/WebCore/rendering/RenderBox.cpp	2012-07-10 19:10:43 UTC (rev 122243)
+++ trunk/Source/WebCore/rendering/RenderBox.cpp	2012-07-10 19:14:25 UTC (rev 122244)
@@ -1178,6 +1178,7 @@
     }
 
     LayoutUnit result = cb->availableLogicalWidthForLine(logicalTopPosition, false, containingBlockRegion, adjustedPageOffsetForContainingBlock) - childMarginStart - childMarginEnd;
+    result = max(result, minPreferredLogicalWidth()); // Don't shrink below our minimum preferred logical width.
 
     // We need to see if margins on either the start side or the end side can contain the floats in question. If they can,
     // then just using the line width is inaccurate. In the case where a float completely fits, we don't need to use the line
@@ -1750,7 +1751,7 @@
         // shrinkToAvoidFloats() is only true for width: auto so the below code works correctly for
         // width: fill-available since no case matches and it returns the logicalWidthResult from above.
         if (shrinkToAvoidFloats() && cb->containsFloats())
-            logicalWidthResult = shrinkLogicalWidthToAvoidFloats(marginStart, marginEnd, cb, region, offsetFromLogicalTopOfFirstPage);
+            logicalWidthResult = min(logicalWidthResult, shrinkLogicalWidthToAvoidFloats(marginStart, marginEnd, cb, region, offsetFromLogicalTopOfFirstPage));
 
         if (logicalWidth.type() == MinContent)
             logicalWidthResult = minPreferredLogicalWidth();
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to