Changeset 69628 in webkit


Ignore:
Timestamp:
Oct 12, 2010 6:36:33 PM (13 years ago)
Author:
hyatt@apple.com
Message:

<rdar://problem/8488444> REGRESSION (r67771)
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.
Location:
trunk
Files:
4 added
11 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r69626 r69628  
     12010-10-12  David Hyatt  <hyatt@apple.com>
     2
     3        Reviewed by Dan Bernstein
     4
     5        <rdar://problem/8488444> REGRESSION (r67771)
     6        https://bugs.webkit.org/show_bug.cgi?id=47434
     7        Crash when printing in RenderBlock::markDescendantBlocksAndLinesForLayout
     8       
     9        Added printing/simultaneous-position-float-change.html
     10
     11        Remove the markDescendantBlocksAndLinesForLayout method since it can walk m_floatingObjects lists with deleted
     12        objects in them.  Make the mechanism for relayout when the page height changes the same as the one when pageY
     13        changes and just tie a concept of pageHeightChanged to the layout state.  If that is set, blocks will just
     14        automatically mark themselves as needing layout.
     15
     16        * platform/mac/printing/simultaneous-position-float-change-expected.checksum: Added.
     17        * platform/mac/printing/simultaneous-position-float-change-expected.png: Added.
     18        * platform/mac/printing/simultaneous-position-float-change-expected.txt: Added.
     19        * printing/simultaneous-position-float-change.html: Added.
     20
    1212010-09-30  Dumitru Daniliuc  <dumi@chromium.org>
    222
  • trunk/WebCore/ChangeLog

    r69625 r69628  
     12010-10-12 David Hyatt  <hyatt@apple.com>
     2
     3        Reviewed by Dan Bernstein
     4
     5        <rdar://problem/8488444> REGRESSION (r67771)
     6        https://bugs.webkit.org/show_bug.cgi?id=47434
     7        Crash when printing in RenderBlock::markDescendantBlocksAndLinesForLayout
     8       
     9        Added printing/simultaneous-position-float-change.html
     10
     11        Remove the markDescendantBlocksAndLinesForLayout method since it can walk m_floatingObjects lists with deleted
     12        objects in them.  Make the mechanism for relayout when the page height changes the same as the one when pageY
     13        changes and just tie a concept of pageHeightChanged to the layout state.  If that is set, blocks will just
     14        automatically mark themselves as needing layout.
     15
     16        * rendering/LayoutState.cpp:
     17        (WebCore::LayoutState::LayoutState):
     18        * rendering/LayoutState.h:
     19        (WebCore::LayoutState::LayoutState):
     20        (WebCore::LayoutState::pageHeight):
     21        (WebCore::LayoutState::pageHeightChanged):
     22        * rendering/RenderBlock.cpp:
     23        (WebCore::RenderBlock::layoutBlock):
     24        (WebCore::RenderBlock::layoutBlockChild):
     25        (WebCore::RenderBlock::layoutPositionedObjects):
     26        (WebCore::RenderBlock::markForPaginationRelayoutIfNeeded):
     27        (WebCore::RenderBlock::insertFloatingObject):
     28        (WebCore::RenderBlock::positionNewFloats):
     29        * rendering/RenderBlock.h:
     30        * rendering/RenderBox.cpp:
     31        * rendering/RenderBox.h:
     32        (WebCore::RenderBox::markForPaginationRelayoutIfNeeded):
     33        * rendering/RenderFlexibleBox.cpp:
     34        (WebCore::RenderFlexibleBox::layoutHorizontalBox):
     35        (WebCore::RenderFlexibleBox::layoutVerticalBox):
     36        * rendering/RenderView.cpp:
     37        (WebCore::RenderView::RenderView):
     38        (WebCore::RenderView::layout):
     39        * rendering/RenderView.h:
     40        (WebCore::RenderView::setPageHeight):
     41        (WebCore::RenderView::pushLayoutState):
     42        (WebCore::LayoutStateMaintainer::LayoutStateMaintainer):
     43        (WebCore::LayoutStateMaintainer::push):
     44
    1452010-10-12  Anders Carlsson  <andersca@apple.com>
    246
  • trunk/WebCore/rendering/LayoutState.cpp

    r67660 r69628  
    3535namespace WebCore {
    3636
    37 LayoutState::LayoutState(LayoutState* prev, RenderBox* renderer, const IntSize& offset, int pageHeight, ColumnInfo* columnInfo)
     37LayoutState::LayoutState(LayoutState* prev, RenderBox* renderer, const IntSize& offset, int pageHeight, bool pageHeightChanged, ColumnInfo* columnInfo)
    3838    : m_columnInfo(columnInfo)
    3939    , m_next(prev)
     
    8787        m_pageOffset = IntSize(m_layoutOffset.width() + renderer->borderLeft() + renderer->paddingLeft(),
    8888                               m_layoutOffset.height() + renderer->borderTop() + renderer->paddingTop());
     89        m_pageHeightChanged = pageHeightChanged;
    8990    } else {
    9091        // If we don't establish a new page height, then propagate the old page height and offset down.
    9192        m_pageHeight = m_next->m_pageHeight;
     93        m_pageHeightChanged = m_next->m_pageHeightChanged;
    9294        m_pageOffset = m_next->m_pageOffset;
    9395       
     
    108110    : m_clipped(false)
    109111    , m_pageHeight(0)
     112    , m_pageHeightChanged(false)
    110113    , m_columnInfo(0)
    111114    , m_next(0)
  • trunk/WebCore/rendering/LayoutState.h

    r67660 r69628  
    4343        : m_clipped(false)
    4444        , m_pageHeight(0)
     45        , m_pageHeightChanged(false)
    4546        , m_columnInfo(0)
    4647        , m_next(0)
     
    5152    }
    5253
    53     LayoutState(LayoutState*, RenderBox*, const IntSize& offset, int pageHeight, ColumnInfo*);
     54    LayoutState(LayoutState*, RenderBox*, const IntSize& offset, int pageHeight, bool pageHeightChanged, ColumnInfo*);
    5455    LayoutState(RenderObject*);
    5556
     
    6869    void addForcedColumnBreak(int childY);
    6970   
     71    bool pageHeight() const { return m_pageHeight; }
     72    bool pageHeightChanged() const { return m_pageHeightChanged; }
     73
    7074private:
    7175    // The normal operator new is disallowed.
     
    8286
    8387    int m_pageHeight; // The current page height for the pagination model that encloses us.
     88    bool m_pageHeightChanged; // If our page height has changed, this will force all blocks to relayout.
    8489    IntSize m_pageOffset; // The offset of the start of the first page in the nearest enclosing pagination model.
    8590    ColumnInfo* m_columnInfo; // If the enclosing pagination model is a column model, then this will store column information for easy retrieval/manipulation.
  • trunk/WebCore/rendering/RenderBlock.cpp

    r69319 r69628  
    11391139    setLogicalHeight(0);
    11401140    bool hasSpecifiedPageHeight = false;
     1141    bool pageHeightChanged = false;
    11411142    ColumnInfo* colInfo = columnInfo();
    11421143    if (hasColumns()) {
     
    11541155        if (colInfo->columnHeight() != pageHeight && m_everHadLayout) {
    11551156            colInfo->setColumnHeight(pageHeight);
    1156             markDescendantBlocksAndLinesForLayout(); // We need to dirty all descendant blocks and lines, since the column height is different now.
     1157            pageHeightChanged = true;
    11571158        }
    11581159       
     
    11611162    }
    11621163
    1163     LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()), hasColumns() || hasTransform() || hasReflection(), pageHeight, colInfo);
     1164    LayoutStateMaintainer statePusher(view(), this, IntSize(x(), y()), hasColumns() || hasTransform() || hasReflection(), pageHeight, pageHeightChanged, colInfo);
    11641165
    11651166    // We use four values, maxTopPos, maxTopNeg, maxBottomPos, and maxBottomNeg, to track
     
    18681869    }
    18691870
    1870     bool paginated = view()->layoutState()->isPaginated();
    1871     if (!child->needsLayout() && paginated && view()->layoutState()->m_pageHeight && childRenderBlock && view()->layoutState()->pageY(child->y()) != childRenderBlock->pageY())
    1872         childRenderBlock->markForPaginationRelayout();
     1871    if (!child->needsLayout())
     1872        child->markForPaginationRelayoutIfNeeded();
    18731873
    18741874    bool childHadLayout = child->m_everHadLayout;
     
    18871887    int logicalTopAfterClear = clearFloatsIfNeeded(child, marginInfo, oldPosMarginBefore, oldNegMarginBefore, logicalTopBeforeClear);
    18881888   
     1889    bool paginated = view()->layoutState()->isPaginated();
    18891890    if (paginated) {
    18901891        int oldTop = logicalTopAfterClear;
     
    19361937            if (!child->avoidsFloats() && childRenderBlock->containsFloats())
    19371938                childRenderBlock->markAllDescendantsWithFloatsForLayout();
    1938             if (paginated && !child->needsLayout() && view()->layoutState()->m_pageHeight && view()->layoutState()->pageY(child->y()) != childRenderBlock->pageY())
    1939                 childRenderBlock->markForPaginationRelayout();
     1939            if (!child->needsLayout())
     1940                child->markForPaginationRelayoutIfNeeded();
    19401941        }
    19411942
     
    20182019        if (hasColumns())
    20192020            view()->layoutState()->clearPaginationInformation(); // Positioned objects are not part of the column flow, so they don't paginate with the columns.
    2020 
    2021         bool paginated = view()->layoutState()->isPaginated();
    20222021
    20232022        RenderBox* r;
     
    20362035                r->setPreferredLogicalWidthsDirty(true, false);
    20372036           
    2038             if (!r->needsLayout() && paginated && view()->layoutState()->m_pageHeight) {
    2039                 RenderBlock* childRenderBlock = r->isRenderBlock() ? toRenderBlock(r) : 0;
    2040                 if (childRenderBlock && view()->layoutState()->pageY(childRenderBlock->y()) != childRenderBlock->pageY())
    2041                     childRenderBlock->markForPaginationRelayout();
    2042             }
     2037            if (!r->needsLayout())
     2038                r->markForPaginationRelayoutIfNeeded();
    20432039
    20442040            // 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
     
    20642060        }
    20652061    }
     2062}
     2063
     2064void RenderBlock::markForPaginationRelayoutIfNeeded()
     2065{
     2066    ASSERT(!needsLayout());
     2067    if (needsLayout())
     2068        return;
     2069
     2070    if (view()->layoutState()->pageHeightChanged() || (view()->layoutState()->pageHeight() && view()->layoutState()->pageY(y()) != pageY()))
     2071        setChildNeedsLayout(true, false);
    20662072}
    20672073
     
    29412947    // Our location is irrelevant if we're unsplittable or no pagination is in effect.
    29422948    // Just go ahead and lay out the float.
    2943     bool affectedByPagination = o->isRenderBlock() && view()->layoutState()->m_pageHeight;
     2949    bool isChildRenderBlock = o->isRenderBlock();
     2950    if (isChildRenderBlock && !o->needsLayout() && view()->layoutState()->pageHeightChanged())
     2951        o->setChildNeedsLayout(true, false);
     2952       
     2953    bool affectedByPagination = isChildRenderBlock && view()->layoutState()->m_pageHeight;
    29442954    if (!affectedByPagination || isWritingModeRoot()) // We are unsplittable if we're a block flow root.
    29452955        o->layoutIfNeeded();
     
    30753085            RenderBlock* childBlock = childBox->isRenderBlock() ? toRenderBlock(childBox) : 0;
    30763086
    3077             if (childBlock && view()->layoutState()->m_pageHeight && view()->layoutState()->pageY(childBox->y()) != childBlock->pageY())
    3078                 childBlock->markForPaginationRelayout();
     3087            if (!childBox->needsLayout())
     3088                childBox->markForPaginationRelayoutIfNeeded();;
    30793089            childBox->layoutIfNeeded();
    30803090
     
    38653875                childBlock->markAllDescendantsWithFloatsForLayout(floatToRemove, inLayout);
    38663876        }
    3867     }
    3868 }
    3869 
    3870 void RenderBlock::markDescendantBlocksAndLinesForLayout(bool inLayout)
    3871 {
    3872     if (!m_everHadLayout)
    3873         return;
    3874 
    3875     setChildNeedsLayout(true, !inLayout);
    3876 
    3877     // Iterate over our children and mark them as needed.
    3878     if (!childrenInline()) {
    3879         for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
    3880             if (child->isFloatingOrPositioned())
    3881                 continue;
    3882             child->markDescendantBlocksAndLinesForLayout(inLayout);
    3883         }
    3884     }
    3885    
    3886     // Walk our floating objects and mark them too.
    3887     if (m_floatingObjects) {
    3888         DeprecatedPtrListIterator<FloatingObject> it(*m_floatingObjects);
    3889         while (it.current()) {
    3890             if (it.current()->m_renderer->isRenderBlock())
    3891                 it.current()->m_renderer->markDescendantBlocksAndLinesForLayout(inLayout);
    3892             ++it;
    3893         }
    3894     }
    3895 
    3896     if (m_positionedObjects) {
    3897         // FIXME: Technically we don't have to mark the positioned objects if we're the block
    3898         // that established the columns, but we don't really have that information here.
    3899         Iterator end = m_positionedObjects->end();
    3900         for (Iterator it = m_positionedObjects->begin(); it != end; ++it)
    3901             (*it)->markDescendantBlocksAndLinesForLayout();
    39023877    }
    39033878}
  • trunk/WebCore/rendering/RenderBlock.h

    r69235 r69628  
    9191    void markAllDescendantsWithFloatsForLayout(RenderBox* floatToRemove = 0, bool inLayout = true);
    9292    void markPositionedObjectsForLayout();
    93     void markForPaginationRelayout()
    94     {
    95         if (isTable())
    96             markDescendantBlocksAndLinesForLayout();
    97         else
    98             setChildNeedsLayout(true, false);
    99     }
    100     virtual void markDescendantBlocksAndLinesForLayout(bool inLayout = true);
     93    virtual void markForPaginationRelayoutIfNeeded();
    10194   
    10295    bool containsFloats() { return m_floatingObjects && !m_floatingObjects->isEmpty(); }
  • trunk/WebCore/rendering/RenderBox.cpp

    r69476 r69628  
    31273127}
    31283128
    3129 void RenderBox::markDescendantBlocksAndLinesForLayout(bool inLayout)
    3130 {
    3131     if (!m_everHadLayout || isReplaced())
    3132         return;
    3133 
    3134     setChildNeedsLayout(true, !inLayout);
    3135 
    3136     // Iterate over our children and mark them as needed.
    3137     for (RenderBox* child = firstChildBox(); child; child = child->nextSiblingBox()) {
    3138         if (child->isFloatingOrPositioned())
    3139             continue;
    3140         child->markDescendantBlocksAndLinesForLayout(inLayout);
    3141     }
    3142 }
    3143 
    31443129} // namespace WebCore
  • trunk/WebCore/rendering/RenderBox.h

    r69235 r69628  
    363363    virtual bool avoidsFloats() const;
    364364
    365     virtual void markDescendantBlocksAndLinesForLayout(bool inLayout = true);
    366    
     365    virtual void markForPaginationRelayoutIfNeeded() { }
     366
    367367    bool isWritingModeRoot() const { return !parent() || parent()->style()->writingMode() != style()->writingMode(); }
    368368
  • trunk/WebCore/rendering/RenderFlexibleBox.cpp

    r68842 r69628  
    335335    gatherFlexChildrenInfo(iterator, relayoutChildren, highestFlexGroup, lowestFlexGroup, haveFlex);
    336336
    337     bool paginated = view()->layoutState()->isPaginated();
    338 
    339337    RenderBox* child;
    340338
     
    367365            child->computeBlockDirectionMargins(this);
    368366   
    369             if (!child->needsLayout() && paginated && view()->layoutState()->m_pageHeight) {
    370                 RenderBlock* childRenderBlock = child->isRenderBlock() ? toRenderBlock(child) : 0;
    371                 if (childRenderBlock && view()->layoutState()->pageY(child->y()) != childRenderBlock->pageY())
    372                     childRenderBlock->markForPaginationRelayout();
    373             }
     367            if (!child->needsLayout())
     368                child->markForPaginationRelayoutIfNeeded();
    374369
    375370            // Now do the layout.
     
    441436                child->setChildNeedsLayout(true, false);
    442437               
    443             if (!child->needsLayout() && paginated && view()->layoutState()->m_pageHeight) {
    444                 RenderBlock* childRenderBlock = child->isRenderBlock() ? toRenderBlock(child) : 0;
    445                 if (childRenderBlock && view()->layoutState()->pageY(child->y()) != childRenderBlock->pageY())
    446                     childRenderBlock->markForPaginationRelayout();
    447             }
     438            if (!child->needsLayout())
     439                child->markForPaginationRelayoutIfNeeded();
    448440
    449441            child->layoutIfNeeded();
     
    660652    gatherFlexChildrenInfo(iterator, relayoutChildren, highestFlexGroup, lowestFlexGroup, haveFlex);
    661653
    662     bool paginated = view()->layoutState()->isPaginated();
    663 
    664654    RenderBox* child;
    665655
     
    711701            setHeight(height() + child->marginTop());
    712702   
    713             if (!child->needsLayout() && paginated && view()->layoutState()->m_pageHeight) {
    714                 RenderBlock* childRenderBlock = child->isRenderBlock() ? toRenderBlock(child) : 0;
    715                 if (childRenderBlock && view()->layoutState()->pageY(child->y()) != childRenderBlock->pageY())
    716                     childRenderBlock->markForPaginationRelayout();
    717             }
     703            if (!child->needsLayout())
     704                child->markForPaginationRelayoutIfNeeded();
    718705
    719706            // Now do a layout.
  • trunk/WebCore/rendering/RenderView.cpp

    r68436 r69628  
    5151    , m_maximalOutlineSize(0)
    5252    , m_pageHeight(0)
     53    , m_pageHeightChanged(false)
    5354    , m_layoutState(0)
    5455    , m_layoutStateDisableCount(0)
     
    117118    state.m_clipped = false;
    118119    state.m_pageHeight = m_pageHeight;
     120    state.m_pageHeightChanged = m_pageHeightChanged;
     121    m_pageHeightChanged = false;
    119122    m_layoutState = &state;
    120123
  • trunk/WebCore/rendering/RenderView.h

    r69220 r69628  
    136136        if (m_pageHeight != height) {
    137137            m_pageHeight = height;
    138             markDescendantBlocksAndLinesForLayout();
     138            m_pageHeightChanged = true;
    139139        }
    140140    }
     
    176176
    177177    // These functions may only be accessed by LayoutStateMaintainer.
    178     bool pushLayoutState(RenderBox* renderer, const IntSize& offset, int pageHeight = 0, ColumnInfo* colInfo = 0)
     178    bool pushLayoutState(RenderBox* renderer, const IntSize& offset, int pageHeight = 0, bool pageHeightChanged = false, ColumnInfo* colInfo = 0)
    179179    {
    180180        // We push LayoutState even if layoutState is disabled because it stores layoutDelta too.
    181181        if (!doingFullRepaint() || renderer->hasColumns() || m_layoutState->isPaginated()) {
    182             m_layoutState = new (renderArena()) LayoutState(m_layoutState, renderer, offset, pageHeight, colInfo);
     182            m_layoutState = new (renderArena()) LayoutState(m_layoutState, renderer, offset, pageHeight, pageHeightChanged, colInfo);
    183183            return true;
    184184        }
     
    228228private:
    229229    unsigned m_pageHeight;
     230    bool m_pageHeightChanged;
    230231    LayoutState* m_layoutState;
    231232    unsigned m_layoutStateDisableCount;
     
    255256public:
    256257    // ctor to push now
    257     LayoutStateMaintainer(RenderView* view, RenderBox* root, IntSize offset, bool disableState = false, int pageHeight = 0, ColumnInfo* colInfo = 0)
     258    LayoutStateMaintainer(RenderView* view, RenderBox* root, IntSize offset, bool disableState = false, int pageHeight = 0, bool pageHeightChanged = false, ColumnInfo* colInfo = 0)
    258259        : m_view(view)
    259260        , m_disabled(disableState)
     
    262263        , m_didCreateLayoutState(false)
    263264    {
    264         push(root, offset, pageHeight, colInfo);
     265        push(root, offset, pageHeight, pageHeightChanged, colInfo);
    265266    }
    266267   
     
    280281    }
    281282
    282     void push(RenderBox* root, IntSize offset, int pageHeight = 0, ColumnInfo* colInfo = 0)
     283    void push(RenderBox* root, IntSize offset, int pageHeight = 0, bool pageHeightChanged = false, ColumnInfo* colInfo = 0)
    283284    {
    284285        ASSERT(!m_didStart);
    285286        // We push state even if disabled, because we still need to store layoutDelta
    286         m_didCreateLayoutState = m_view->pushLayoutState(root, offset, pageHeight, colInfo);
     287        m_didCreateLayoutState = m_view->pushLayoutState(root, offset, pageHeight, pageHeightChanged, colInfo);
    287288        if (m_disabled && m_didCreateLayoutState)
    288289            m_view->disableLayoutState();
Note: See TracChangeset for help on using the changeset viewer.