<rdar://problem/8488444> REGRESSION (r67771)
authorhyatt@apple.com <hyatt@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 13 Oct 2010 01:36:33 +0000 (01:36 +0000)
committerhyatt@apple.com <hyatt@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 13 Oct 2010 01:36:33 +0000 (01:36 +0000)
https://bugs.webkit.org/show_bug.cgi?id=47434
Crash when printing in RenderBlock::markDescendantBlocksAndLinesForLayout

Reviewed by Dan Bernstein

Added printing/simultaneous-position-float-change.html

Remove the markDescendantBlocksAndLinesForLayout method since it can walk m_floatingObjects lists with deleted
objects in them.  Make the mechanism for relayout when the page height changes the same as the one when pageY
changes and just tie a concept of pageHeightChanged to the layout state.  If that is set, blocks will just
automatically mark themselves as needing layout.

WebCore:

* rendering/LayoutState.cpp:
(WebCore::LayoutState::LayoutState):
* rendering/LayoutState.h:
(WebCore::LayoutState::LayoutState):
(WebCore::LayoutState::pageHeight):
(WebCore::LayoutState::pageHeightChanged):
* rendering/RenderBlock.cpp:
(WebCore::RenderBlock::layoutBlock):
(WebCore::RenderBlock::layoutBlockChild):
(WebCore::RenderBlock::layoutPositionedObjects):
(WebCore::RenderBlock::markForPaginationRelayoutIfNeeded):
(WebCore::RenderBlock::insertFloatingObject):
(WebCore::RenderBlock::positionNewFloats):
* rendering/RenderBlock.h:
* rendering/RenderBox.cpp:
* rendering/RenderBox.h:
(WebCore::RenderBox::markForPaginationRelayoutIfNeeded):
* rendering/RenderFlexibleBox.cpp:
(WebCore::RenderFlexibleBox::layoutHorizontalBox):
(WebCore::RenderFlexibleBox::layoutVerticalBox):
* rendering/RenderView.cpp:
(WebCore::RenderView::RenderView):
(WebCore::RenderView::layout):
* rendering/RenderView.h:
(WebCore::RenderView::setPageHeight):
(WebCore::RenderView::pushLayoutState):
(WebCore::LayoutStateMaintainer::LayoutStateMaintainer):
(WebCore::LayoutStateMaintainer::push):

LayoutTests:

* platform/mac/printing/simultaneous-position-float-change-expected.checksum: Added.
* platform/mac/printing/simultaneous-position-float-change-expected.png: Added.
* platform/mac/printing/simultaneous-position-float-change-expected.txt: Added.
* printing/simultaneous-position-float-change.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@69628 268f45cc-cd09-0410-ab3c-d52691b4dbfc

15 files changed:
LayoutTests/ChangeLog
LayoutTests/platform/mac/printing/simultaneous-position-float-change-expected.checksum [new file with mode: 0644]
LayoutTests/platform/mac/printing/simultaneous-position-float-change-expected.png [new file with mode: 0644]
LayoutTests/platform/mac/printing/simultaneous-position-float-change-expected.txt [new file with mode: 0644]
LayoutTests/printing/simultaneous-position-float-change.html [new file with mode: 0644]
WebCore/ChangeLog
WebCore/rendering/LayoutState.cpp
WebCore/rendering/LayoutState.h
WebCore/rendering/RenderBlock.cpp
WebCore/rendering/RenderBlock.h
WebCore/rendering/RenderBox.cpp
WebCore/rendering/RenderBox.h
WebCore/rendering/RenderFlexibleBox.cpp
WebCore/rendering/RenderView.cpp
WebCore/rendering/RenderView.h

index 46260c8..c897b48 100644 (file)
@@ -1,3 +1,23 @@
+2010-10-12  David Hyatt  <hyatt@apple.com>
+
+        Reviewed by Dan Bernstein
+
+        <rdar://problem/8488444> REGRESSION (r67771)
+        https://bugs.webkit.org/show_bug.cgi?id=47434
+        Crash when printing in RenderBlock::markDescendantBlocksAndLinesForLayout
+        
+        Added printing/simultaneous-position-float-change.html
+
+        Remove the markDescendantBlocksAndLinesForLayout method since it can walk m_floatingObjects lists with deleted
+        objects in them.  Make the mechanism for relayout when the page height changes the same as the one when pageY
+        changes and just tie a concept of pageHeightChanged to the layout state.  If that is set, blocks will just
+        automatically mark themselves as needing layout.
+
+        * platform/mac/printing/simultaneous-position-float-change-expected.checksum: Added.
+        * platform/mac/printing/simultaneous-position-float-change-expected.png: Added.
+        * platform/mac/printing/simultaneous-position-float-change-expected.txt: Added.
+        * printing/simultaneous-position-float-change.html: Added.
+
 2010-09-30  Dumitru Daniliuc  <dumi@chromium.org>
 
         Reviewed by David Levin.
diff --git a/LayoutTests/platform/mac/printing/simultaneous-position-float-change-expected.checksum b/LayoutTests/platform/mac/printing/simultaneous-position-float-change-expected.checksum
new file mode 100644 (file)
index 0000000..d69a371
--- /dev/null
@@ -0,0 +1 @@
+853de00567d121bea0b7bece66a5d61c
\ No newline at end of file
diff --git a/LayoutTests/platform/mac/printing/simultaneous-position-float-change-expected.png b/LayoutTests/platform/mac/printing/simultaneous-position-float-change-expected.png
new file mode 100644 (file)
index 0000000..3892168
Binary files /dev/null and b/LayoutTests/platform/mac/printing/simultaneous-position-float-change-expected.png differ
diff --git a/LayoutTests/platform/mac/printing/simultaneous-position-float-change-expected.txt b/LayoutTests/platform/mac/printing/simultaneous-position-float-change-expected.txt
new file mode 100644 (file)
index 0000000..c4f3052
--- /dev/null
@@ -0,0 +1,5 @@
+layer at (0,0) size 1000x8
+  RenderView at (0,0) size 1000x8
+layer at (0,0) size 1000x8
+  RenderBlock {HTML} at (0,0) size 1000x8
+    RenderBody {BODY} at (8,8) size 984x0
diff --git a/LayoutTests/printing/simultaneous-position-float-change.html b/LayoutTests/printing/simultaneous-position-float-change.html
new file mode 100644 (file)
index 0000000..8bcefb6
--- /dev/null
@@ -0,0 +1,22 @@
+<html>
+<head>
+    <style media="print">
+        div { position: absolute; }
+        span {display: none; }
+    </style>
+</head>
+<body>
+    <div> 
+        <span style="float: right;"> 
+            0
+        </span>
+    </div>
+    <script>
+document.body.offsetWidth;
+if (window.layoutTestController)
+    layoutTestController.setPrinting();
+document.body.offsetWidth;
+</script>
+
+</body>
+</html>
index 55f4ee8..d07167c 100644 (file)
@@ -1,3 +1,47 @@
+2010-10-12 David Hyatt  <hyatt@apple.com>
+
+        Reviewed by Dan Bernstein
+
+        <rdar://problem/8488444> REGRESSION (r67771)
+        https://bugs.webkit.org/show_bug.cgi?id=47434
+        Crash when printing in RenderBlock::markDescendantBlocksAndLinesForLayout
+        
+        Added printing/simultaneous-position-float-change.html
+
+        Remove the markDescendantBlocksAndLinesForLayout method since it can walk m_floatingObjects lists with deleted
+        objects in them.  Make the mechanism for relayout when the page height changes the same as the one when pageY
+        changes and just tie a concept of pageHeightChanged to the layout state.  If that is set, blocks will just
+        automatically mark themselves as needing layout.
+
+        * rendering/LayoutState.cpp:
+        (WebCore::LayoutState::LayoutState):
+        * rendering/LayoutState.h:
+        (WebCore::LayoutState::LayoutState):
+        (WebCore::LayoutState::pageHeight):
+        (WebCore::LayoutState::pageHeightChanged):
+        * rendering/RenderBlock.cpp:
+        (WebCore::RenderBlock::layoutBlock):
+        (WebCore::RenderBlock::layoutBlockChild):
+        (WebCore::RenderBlock::layoutPositionedObjects):
+        (WebCore::RenderBlock::markForPaginationRelayoutIfNeeded):
+        (WebCore::RenderBlock::insertFloatingObject):
+        (WebCore::RenderBlock::positionNewFloats):
+        * rendering/RenderBlock.h:
+        * rendering/RenderBox.cpp:
+        * rendering/RenderBox.h:
+        (WebCore::RenderBox::markForPaginationRelayoutIfNeeded):
+        * rendering/RenderFlexibleBox.cpp:
+        (WebCore::RenderFlexibleBox::layoutHorizontalBox):
+        (WebCore::RenderFlexibleBox::layoutVerticalBox):
+        * rendering/RenderView.cpp:
+        (WebCore::RenderView::RenderView):
+        (WebCore::RenderView::layout):
+        * rendering/RenderView.h:
+        (WebCore::RenderView::setPageHeight):
+        (WebCore::RenderView::pushLayoutState):
+        (WebCore::LayoutStateMaintainer::LayoutStateMaintainer):
+        (WebCore::LayoutStateMaintainer::push):
+
 2010-10-12  Anders Carlsson  <andersca@apple.com>
 
         Reviewed by Dan Bernstein.
index 0d81b15..3eea51f 100644 (file)
@@ -34,7 +34,7 @@
 
 namespace WebCore {
 
-LayoutState::LayoutState(LayoutState* prev, RenderBox* renderer, const IntSize& offset, int pageHeight, ColumnInfo* columnInfo)
+LayoutState::LayoutState(LayoutState* prev, RenderBox* renderer, const IntSize& offset, int pageHeight, bool pageHeightChanged, ColumnInfo* columnInfo)
     : m_columnInfo(columnInfo)
     , m_next(prev)
 #ifndef NDEBUG
@@ -86,9 +86,11 @@ LayoutState::LayoutState(LayoutState* prev, RenderBox* renderer, const IntSize&
         m_pageHeight = pageHeight;
         m_pageOffset = IntSize(m_layoutOffset.width() + renderer->borderLeft() + renderer->paddingLeft(),
                                m_layoutOffset.height() + renderer->borderTop() + renderer->paddingTop());
+        m_pageHeightChanged = pageHeightChanged;
     } else {
         // If we don't establish a new page height, then propagate the old page height and offset down.
         m_pageHeight = m_next->m_pageHeight;
+        m_pageHeightChanged = m_next->m_pageHeightChanged;
         m_pageOffset = m_next->m_pageOffset;
         
         // Disable pagination for objects we don't support.  For now this includes overflow:scroll/auto and inline blocks.
@@ -107,6 +109,7 @@ LayoutState::LayoutState(LayoutState* prev, RenderBox* renderer, const IntSize&
 LayoutState::LayoutState(RenderObject* root)
     : m_clipped(false)
     , m_pageHeight(0)
+    , m_pageHeightChanged(false)
     , m_columnInfo(0)
     , m_next(0)
 #ifndef NDEBUG
index ca4cbfb..cca3e42 100644 (file)
@@ -42,6 +42,7 @@ public:
     LayoutState()
         : m_clipped(false)
         , m_pageHeight(0)
+        , m_pageHeightChanged(false)
         , m_columnInfo(0)
         , m_next(0)
 #ifndef NDEBUG
@@ -50,7 +51,7 @@ public:
     {
     }
 
-    LayoutState(LayoutState*, RenderBox*, const IntSize& offset, int pageHeight, ColumnInfo*);
+    LayoutState(LayoutState*, RenderBox*, const IntSize& offset, int pageHeight, bool pageHeightChanged, ColumnInfo*);
     LayoutState(RenderObject*);
 
     void destroy(RenderArena*);
@@ -67,6 +68,9 @@ public:
     int pageY(int childY) const;
     void addForcedColumnBreak(int childY);
     
+    bool pageHeight() const { return m_pageHeight; }
+    bool pageHeightChanged() const { return m_pageHeightChanged; }
+
 private:
     // The normal operator new is disallowed.
     void* operator new(size_t) throw();
@@ -81,6 +85,7 @@ public:
                            // This is a total delta accumulated from the root.
 
     int m_pageHeight; // The current page height for the pagination model that encloses us.
+    bool m_pageHeightChanged; // If our page height has changed, this will force all blocks to relayout.
     IntSize m_pageOffset; // The offset of the start of the first page in the nearest enclosing pagination model.
     ColumnInfo* m_columnInfo; // If the enclosing pagination model is a column model, then this will store column information for easy retrieval/manipulation.
 
index 6eff96e..ced46f3 100644 (file)
@@ -1138,6 +1138,7 @@ void RenderBlock::layoutBlock(bool relayoutChildren, int pageHeight)
     int previousHeight = logicalHeight();
     setLogicalHeight(0);
     bool hasSpecifiedPageHeight = false;
+    bool pageHeightChanged = false;
     ColumnInfo* colInfo = columnInfo();
     if (hasColumns()) {
         if (!pageHeight) {
@@ -1153,14 +1154,14 @@ void RenderBlock::layoutBlock(bool relayoutChildren, int pageHeight)
         }
         if (colInfo->columnHeight() != pageHeight && m_everHadLayout) {
             colInfo->setColumnHeight(pageHeight);
-            markDescendantBlocksAndLinesForLayout(); // We need to dirty all descendant blocks and lines, since the column height is different now.
+            pageHeightChanged = true;
         }
         
         if (!hasSpecifiedPageHeight && !pageHeight)
             colInfo->clearForcedBreaks();
     }
 
-    LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()), hasColumns() || hasTransform() || hasReflection(), pageHeight, colInfo);
+    LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()), hasColumns() || hasTransform() || hasReflection(), pageHeight, pageHeightChanged, colInfo);
 
     // We use four values, maxTopPos, maxTopNeg, maxBottomPos, and maxBottomNeg, to track
     // our current maximal positive and negative margins.  These values are used when we
@@ -1867,9 +1868,8 @@ void RenderBlock::layoutBlockChild(RenderBox* child, MarginInfo& marginInfo, int
             previousFloatLogicalBottom = max(previousFloatLogicalBottom, oldLogicalTop + childRenderBlock->lowestFloatLogicalBottom());
     }
 
-    bool paginated = view()->layoutState()->isPaginated();
-    if (!child->needsLayout() && paginated && view()->layoutState()->m_pageHeight && childRenderBlock && view()->layoutState()->pageY(child->y()) != childRenderBlock->pageY())
-        childRenderBlock->markForPaginationRelayout();
+    if (!child->needsLayout())
+        child->markForPaginationRelayoutIfNeeded();
 
     bool childHadLayout = child->m_everHadLayout;
     bool childNeededLayout = child->needsLayout();
@@ -1886,6 +1886,7 @@ void RenderBlock::layoutBlockChild(RenderBox* child, MarginInfo& marginInfo, int
     // Now check for clear.
     int logicalTopAfterClear = clearFloatsIfNeeded(child, marginInfo, oldPosMarginBefore, oldNegMarginBefore, logicalTopBeforeClear);
     
+    bool paginated = view()->layoutState()->isPaginated();
     if (paginated) {
         int oldTop = logicalTopAfterClear;
         
@@ -1935,8 +1936,8 @@ void RenderBlock::layoutBlockChild(RenderBox* child, MarginInfo& marginInfo, int
         if (childRenderBlock) {
             if (!child->avoidsFloats() && childRenderBlock->containsFloats())
                 childRenderBlock->markAllDescendantsWithFloatsForLayout();
-            if (paginated && !child->needsLayout() && view()->layoutState()->m_pageHeight && view()->layoutState()->pageY(child->y()) != childRenderBlock->pageY())
-                childRenderBlock->markForPaginationRelayout();
+            if (!child->needsLayout())
+                child->markForPaginationRelayoutIfNeeded();
         }
 
         // Our guess was wrong. Make the child lay itself out again.
@@ -2018,8 +2019,6 @@ void RenderBlock::layoutPositionedObjects(bool relayoutChildren)
         if (hasColumns())
             view()->layoutState()->clearPaginationInformation(); // Positioned objects are not part of the column flow, so they don't paginate with the columns.
 
-        bool paginated = view()->layoutState()->isPaginated();
-
         RenderBox* r;
         Iterator end = m_positionedObjects->end();
         for (Iterator it = m_positionedObjects->begin(); it != end; ++it) {
@@ -2035,11 +2034,8 @@ void RenderBlock::layoutPositionedObjects(bool relayoutChildren)
             //if (relayoutChildren && (r->style()->paddingLeft().isPercent() || r->style()->paddingRight().isPercent()))
                 r->setPreferredLogicalWidthsDirty(true, false);
             
-            if (!r->needsLayout() && paginated && view()->layoutState()->m_pageHeight) {
-                RenderBlock* childRenderBlock = r->isRenderBlock() ? toRenderBlock(r) : 0;
-                if (childRenderBlock && view()->layoutState()->pageY(childRenderBlock->y()) != childRenderBlock->pageY())
-                    childRenderBlock->markForPaginationRelayout();
-            }
+            if (!r->needsLayout())
+                r->markForPaginationRelayoutIfNeeded();
 
             // We don't have to do a full layout.  We just have to update our position. Try that first. If we have shrink-to-fit width
             // and we hit the available width constraint, the layoutIfNeeded() will catch it and do a full layout.
@@ -2065,6 +2061,16 @@ void RenderBlock::markPositionedObjectsForLayout()
     }
 }
 
+void RenderBlock::markForPaginationRelayoutIfNeeded()
+{
+    ASSERT(!needsLayout());
+    if (needsLayout())
+        return;
+
+    if (view()->layoutState()->pageHeightChanged() || (view()->layoutState()->pageHeight() && view()->layoutState()->pageY(y()) != pageY()))
+        setChildNeedsLayout(true, false);
+}
+
 void RenderBlock::repaintOverhangingFloats(bool paintAllDescendants)
 {
     // Repaint any overhanging floats (if we know we're the one to paint them).
@@ -2940,7 +2946,11 @@ RenderBlock::FloatingObject* RenderBlock::insertFloatingObject(RenderBox* o)
     
     // Our location is irrelevant if we're unsplittable or no pagination is in effect.
     // Just go ahead and lay out the float.
-    bool affectedByPagination = o->isRenderBlock() && view()->layoutState()->m_pageHeight;
+    bool isChildRenderBlock = o->isRenderBlock();
+    if (isChildRenderBlock && !o->needsLayout() && view()->layoutState()->pageHeightChanged())
+        o->setChildNeedsLayout(true, false);
+        
+    bool affectedByPagination = isChildRenderBlock && view()->layoutState()->m_pageHeight;
     if (!affectedByPagination || isWritingModeRoot()) // We are unsplittable if we're a block flow root.
         o->layoutIfNeeded();
     else {
@@ -3074,8 +3084,8 @@ bool RenderBlock::positionNewFloats()
         if (view()->layoutState()->isPaginated()) {
             RenderBlock* childBlock = childBox->isRenderBlock() ? toRenderBlock(childBox) : 0;
 
-            if (childBlock && view()->layoutState()->m_pageHeight && view()->layoutState()->pageY(childBox->y()) != childBlock->pageY())
-                childBlock->markForPaginationRelayout();
+            if (!childBox->needsLayout())
+                childBox->markForPaginationRelayoutIfNeeded();;
             childBox->layoutIfNeeded();
 
             // If we are unsplittable and don't fit, then we need to move down.
@@ -3867,41 +3877,6 @@ void RenderBlock::markAllDescendantsWithFloatsForLayout(RenderBox* floatToRemove
     }
 }
 
-void RenderBlock::markDescendantBlocksAndLinesForLayout(bool inLayout)
-{
-    if (!m_everHadLayout)
-        return;
-
-    setChildNeedsLayout(true, !inLayout);
-
-    // Iterate over our children and mark them as needed.
-    if (!childrenInline()) {
-        for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
-            if (child->isFloatingOrPositioned())
-                continue;
-            child->markDescendantBlocksAndLinesForLayout(inLayout);
-        }
-    }
-    
-    // Walk our floating objects and mark them too.
-    if (m_floatingObjects) {
-        DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
-        while (it.current()) {
-            if (it.current()->m_renderer->isRenderBlock())
-                it.current()->m_renderer->markDescendantBlocksAndLinesForLayout(inLayout);
-            ++it;
-        }
-    }
-
-    if (m_positionedObjects) {
-        // FIXME: Technically we don't have to mark the positioned objects if we're the block
-        // that established the columns, but we don't really have that information here.
-        Iterator end = m_positionedObjects->end();
-        for (Iterator it = m_positionedObjects->begin(); it != end; ++it)
-            (*it)->markDescendantBlocksAndLinesForLayout();
-    }
-}
-
 int RenderBlock::getClearDelta(RenderBox* child, int yPos)
 {
     // There is no need to compute clearance if we have no floats.
index 9d5346b..61c889c 100644 (file)
@@ -90,14 +90,7 @@ public:
 
     void markAllDescendantsWithFloatsForLayout(RenderBox* floatToRemove = 0, bool inLayout = true);
     void markPositionedObjectsForLayout();
-    void markForPaginationRelayout()
-    { 
-        if (isTable())
-            markDescendantBlocksAndLinesForLayout();
-        else
-            setChildNeedsLayout(true, false);
-    }
-    virtual void markDescendantBlocksAndLinesForLayout(bool inLayout = true);
+    virtual void markForPaginationRelayoutIfNeeded();
     
     bool containsFloats() { return m_floatingObjects && !m_floatingObjects->isEmpty(); }
     bool containsFloat(RenderObject*);
index 989ef4e..9de592f 100644 (file)
@@ -3126,19 +3126,4 @@ void RenderBox::clearLayoutOverflow()
     m_overflow->resetLayoutOverflow(borderBoxRect());
 }
 
-void RenderBox::markDescendantBlocksAndLinesForLayout(bool inLayout)
-{
-    if (!m_everHadLayout || isReplaced())
-        return;
-
-    setChildNeedsLayout(true, !inLayout);
-
-    // Iterate over our children and mark them as needed.
-    for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
-        if (child->isFloatingOrPositioned())
-            continue;
-        child->markDescendantBlocksAndLinesForLayout(inLayout);
-    }
-}
-
 } // namespace WebCore
index 6051475..2260ac9 100644 (file)
@@ -362,8 +362,8 @@ public:
     bool shrinkToAvoidFloats() const;
     virtual bool avoidsFloats() const;
 
-    virtual void markDescendantBlocksAndLinesForLayout(bool inLayout = true);
-    
+    virtual void markForPaginationRelayoutIfNeeded() { }
+
     bool isWritingModeRoot() const { return !parent() || parent()->style()->writingMode() != style()->writingMode(); }
 
 protected:
index 843b971..de6ef40 100644 (file)
@@ -334,8 +334,6 @@ void RenderFlexibleBox::layoutHorizontalBox(bool relayoutChildren)
     bool haveFlex = false;
     gatherFlexChildrenInfo(iterator, relayoutChildren, highestFlexGroup, lowestFlexGroup, haveFlex);
 
-    bool paginated = view()->layoutState()->isPaginated();
-
     RenderBox* child;
 
     RenderBlock::startDelayUpdateScrollInfo();
@@ -366,11 +364,8 @@ void RenderFlexibleBox::layoutHorizontalBox(bool relayoutChildren)
             // Compute the child's vertical margins.
             child->computeBlockDirectionMargins(this);
     
-            if (!child->needsLayout() && paginated && view()->layoutState()->m_pageHeight) {
-                RenderBlock* childRenderBlock = child->isRenderBlock() ? toRenderBlock(child) : 0;
-                if (childRenderBlock && view()->layoutState()->pageY(child->y()) != childRenderBlock->pageY())
-                    childRenderBlock->markForPaginationRelayout();
-            }
+            if (!child->needsLayout())
+                child->markForPaginationRelayoutIfNeeded();
 
             // Now do the layout.
             child->layoutIfNeeded();
@@ -440,11 +435,8 @@ void RenderFlexibleBox::layoutHorizontalBox(bool relayoutChildren)
             if (oldChildHeight != child->height())
                 child->setChildNeedsLayout(true, false);
                 
-            if (!child->needsLayout() && paginated && view()->layoutState()->m_pageHeight) {
-                RenderBlock* childRenderBlock = child->isRenderBlock() ? toRenderBlock(child) : 0;
-                if (childRenderBlock && view()->layoutState()->pageY(child->y()) != childRenderBlock->pageY())
-                    childRenderBlock->markForPaginationRelayout();
-            }
+            if (!child->needsLayout())
+                child->markForPaginationRelayoutIfNeeded();
 
             child->layoutIfNeeded();
     
@@ -659,8 +651,6 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren)
     bool haveFlex = false;
     gatherFlexChildrenInfo(iterator, relayoutChildren, highestFlexGroup, lowestFlexGroup, haveFlex);
 
-    bool paginated = view()->layoutState()->isPaginated();
-
     RenderBox* child;
 
     // We confine the line clamp ugliness to vertical flexible boxes (thus keeping it out of
@@ -710,11 +700,8 @@ void RenderFlexibleBox::layoutVerticalBox(bool relayoutChildren)
             // Add in the child's marginTop to our height.
             setHeight(height() + child->marginTop());
     
-            if (!child->needsLayout() && paginated && view()->layoutState()->m_pageHeight) {
-                RenderBlock* childRenderBlock = child->isRenderBlock() ? toRenderBlock(child) : 0;
-                if (childRenderBlock && view()->layoutState()->pageY(child->y()) != childRenderBlock->pageY())
-                    childRenderBlock->markForPaginationRelayout();
-            }
+            if (!child->needsLayout())
+                child->markForPaginationRelayoutIfNeeded();
 
             // Now do a layout.
             child->layoutIfNeeded();
index 4da680c..d11ea6e 100644 (file)
@@ -50,6 +50,7 @@ RenderView::RenderView(Node* node, FrameView* view)
     , m_selectionEndPos(-1)
     , m_maximalOutlineSize(0)
     , m_pageHeight(0)
+    , m_pageHeightChanged(false)
     , m_layoutState(0)
     , m_layoutStateDisableCount(0)
 {
@@ -116,6 +117,8 @@ void RenderView::layout()
     // FIXME: May be better to push a clip and avoid issuing offscreen repaints.
     state.m_clipped = false;
     state.m_pageHeight = m_pageHeight;
+    state.m_pageHeightChanged = m_pageHeightChanged;
+    m_pageHeightChanged = false;
     m_layoutState = &state;
 
     if (needsLayout())
index 81d91f6..d3d7a08 100644 (file)
@@ -135,7 +135,7 @@ public:
     {
         if (m_pageHeight != height) {
             m_pageHeight = height;
-            markDescendantBlocksAndLinesForLayout();
+            m_pageHeightChanged = true;
         }
     }
 
@@ -175,11 +175,11 @@ private:
     int docWidth() const;
 
     // These functions may only be accessed by LayoutStateMaintainer.
-    bool pushLayoutState(RenderBox* renderer, const IntSize& offset, int pageHeight = 0, ColumnInfo* colInfo = 0)
+    bool pushLayoutState(RenderBox* renderer, const IntSize& offset, int pageHeight = 0, bool pageHeightChanged = false, ColumnInfo* colInfo = 0)
     {
         // We push LayoutState even if layoutState is disabled because it stores layoutDelta too.
         if (!doingFullRepaint() || renderer->hasColumns() || m_layoutState->isPaginated()) {
-            m_layoutState = new (renderArena()) LayoutState(m_layoutState, renderer, offset, pageHeight, colInfo);
+            m_layoutState = new (renderArena()) LayoutState(m_layoutState, renderer, offset, pageHeight, pageHeightChanged, colInfo);
             return true;
         }
         return false;
@@ -227,6 +227,7 @@ protected:
     
 private:
     unsigned m_pageHeight;
+    bool m_pageHeightChanged;
     LayoutState* m_layoutState;
     unsigned m_layoutStateDisableCount;
 #if USE(ACCELERATED_COMPOSITING)
@@ -254,14 +255,14 @@ void toRenderView(const RenderView*);
 class LayoutStateMaintainer : public Noncopyable {
 public:
     // ctor to push now
-    LayoutStateMaintainer(RenderView* view, RenderBox* root, IntSize offset, bool disableState = false, int pageHeight = 0, ColumnInfo* colInfo = 0)
+    LayoutStateMaintainer(RenderView* view, RenderBox* root, IntSize offset, bool disableState = false, int pageHeight = 0, bool pageHeightChanged = false, ColumnInfo* colInfo = 0)
         : m_view(view)
         , m_disabled(disableState)
         , m_didStart(false)
         , m_didEnd(false)
         , m_didCreateLayoutState(false)
     {
-        push(root, offset, pageHeight, colInfo);
+        push(root, offset, pageHeight, pageHeightChanged, colInfo);
     }
     
     // ctor to maybe push later
@@ -279,11 +280,11 @@ public:
         ASSERT(m_didStart == m_didEnd);   // if this fires, it means that someone did a push(), but forgot to pop().
     }
 
-    void push(RenderBox* root, IntSize offset, int pageHeight = 0, ColumnInfo* colInfo = 0)
+    void push(RenderBox* root, IntSize offset, int pageHeight = 0, bool pageHeightChanged = false, ColumnInfo* colInfo = 0)
     {
         ASSERT(!m_didStart);
         // We push state even if disabled, because we still need to store layoutDelta
-        m_didCreateLayoutState = m_view->pushLayoutState(root, offset, pageHeight, colInfo);
+        m_didCreateLayoutState = m_view->pushLayoutState(root, offset, pageHeight, pageHeightChanged, colInfo);
         if (m_disabled && m_didCreateLayoutState)
             m_view->disableLayoutState();
         m_didStart = true;