Changeset 86698 in webkit


Ignore:
Timestamp:
May 17, 2011 12:45:24 PM (13 years ago)
Author:
eric@webkit.org
Message:

2011-05-17 Eric Seidel <eric@webkit.org>

Reviewed by Ryosuke Niwa.

Add a LineLayoutState object to hold global state during line layout
https://bugs.webkit.org/show_bug.cgi?id=60113

Like LayoutState for layout(), LineLayoutState keeps track of global information
during an entire linebox tree layout pass (aka layoutInlineChildren).

For now it just holds isFullLayout and the logicalRepaintTop/Bottom.
It's possible we should hold the useRepaintBounds bool as well as
the startLine and endLine RootInlineBox pointers.

No change in behavior, thus no tests.

  • rendering/RenderBlock.cpp: (WebCore::RenderBlock::layoutBlock):
  • rendering/RenderBlock.h:
  • rendering/RenderBlockLineLayout.cpp: (WebCore::LineLayoutState::LineLayoutState): (WebCore::LineLayoutState::markForFullLayout): (WebCore::LineLayoutState::isFullLayout): (WebCore::LineLayoutState::setRepaintRange): (WebCore::LineLayoutState::updateRepaintRangeFromBox): (WebCore::LineLayoutState::startLine): (WebCore::LineLayoutState::endLine): (WebCore::deleteLineRange): (WebCore::RenderBlock::layoutRunsAndFloats): (WebCore::RenderBlock::layoutInlineChildren): (WebCore::RenderBlock::checkFloatsInCleanLine): (WebCore::RenderBlock::determineStartPosition): (WebCore::RenderBlock::determineEndPosition): (WebCore::RenderBlock::matchedEndLine):
Location:
trunk/Source/WebCore
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebCore/ChangeLog

    r86695 r86698  
     12011-05-17  Eric Seidel  <eric@webkit.org>
     2
     3        Reviewed by Ryosuke Niwa.
     4
     5        Add a LineLayoutState object to hold global state during line layout
     6        https://bugs.webkit.org/show_bug.cgi?id=60113
     7
     8        Like LayoutState for layout(), LineLayoutState keeps track of global information
     9        during an entire linebox tree layout pass (aka layoutInlineChildren).
     10
     11        For now it just holds isFullLayout and the logicalRepaintTop/Bottom.
     12        It's possible we should hold the useRepaintBounds bool as well as
     13        the startLine and endLine RootInlineBox pointers.
     14
     15        No change in behavior, thus no tests.
     16
     17        * rendering/RenderBlock.cpp:
     18        (WebCore::RenderBlock::layoutBlock):
     19        * rendering/RenderBlock.h:
     20        * rendering/RenderBlockLineLayout.cpp:
     21        (WebCore::LineLayoutState::LineLayoutState):
     22        (WebCore::LineLayoutState::markForFullLayout):
     23        (WebCore::LineLayoutState::isFullLayout):
     24        (WebCore::LineLayoutState::setRepaintRange):
     25        (WebCore::LineLayoutState::updateRepaintRangeFromBox):
     26        (WebCore::LineLayoutState::startLine):
     27        (WebCore::LineLayoutState::endLine):
     28        (WebCore::deleteLineRange):
     29        (WebCore::RenderBlock::layoutRunsAndFloats):
     30        (WebCore::RenderBlock::layoutInlineChildren):
     31        (WebCore::RenderBlock::checkFloatsInCleanLine):
     32        (WebCore::RenderBlock::determineStartPosition):
     33        (WebCore::RenderBlock::determineEndPosition):
     34        (WebCore::RenderBlock::matchedEndLine):
     35
    1362011-05-17  Andreas Kling  <kling@webkit.org>
    237
  • trunk/Source/WebCore/rendering/RenderBlock.cpp

    r86451 r86698  
    12831283    updateScrollInfoAfterLayout();
    12841284
     1285    // FIXME: This repaint logic should be moved into a separate helper function!
    12851286    // Repaint with our new bounds if they are different from our old bounds.
    12861287    bool didFullRepaint = repainter.repaintAfterLayout();
  • trunk/Source/WebCore/rendering/RenderBlock.h

    r86377 r86698  
    3838class LayoutStateMaintainer;
    3939class LazyLineBreakIterator;
     40class LineLayoutState;
    4041class LineWidth;
    4142class RenderInline;
     
    521522        Vector<RenderBox*> m_positionedObjects;
    522523    };
    523    
     524
    524525    void checkFloatsInCleanLine(RootInlineBox*, Vector<FloatWithRect>&, size_t& floatIndex, bool& encounteredNewFloat, bool& dirtiedByFloat);
    525     RootInlineBox* determineStartPosition(LineInfo&, bool& fullLayout, InlineBidiResolver&, Vector<FloatWithRect>& floats, unsigned& numCleanFloats,
    526                                           bool& useRepaintBounds, int& repaintTop, int& repaintBottom);
    527     RootInlineBox* determineEndPosition(RootInlineBox* startBox, Vector<FloatWithRect>& floats, size_t floatIndex, InlineIterator& cleanLineStart,
    528                                         BidiStatus& cleanLineBidiStatus, int& yPos);
    529     bool matchedEndLine(const InlineBidiResolver&, const InlineIterator& endLineStart, const BidiStatus& endLineStatus,
    530                         RootInlineBox*& endLine, int& endYPos, int& repaintBottom, int& repaintTop);
     526    RootInlineBox* determineStartPosition(LineLayoutState&, LineInfo&, InlineBidiResolver&, Vector<FloatWithRect>&, unsigned& numCleanFloats, bool& useRepaintBounds);
     527    RootInlineBox* determineEndPosition(RootInlineBox* startBox, Vector<FloatWithRect>&, size_t floatIndex, InlineIterator& cleanLineStart, BidiStatus& cleanLineBidiStatus, int& yPos);
     528    bool matchedEndLine(LineLayoutState&, const InlineBidiResolver&, const InlineIterator& endLineStart, const BidiStatus& endLineStatus, RootInlineBox*& endLine, int& endYPos);
    531529
    532530    RootInlineBox* constructLine(BidiRunList<BidiRun>&, const LineInfo&);
     
    732730    // Helper function for layoutInlineChildren()
    733731    RootInlineBox* createLineBoxesFromBidiRuns(BidiRunList<BidiRun>&, const InlineIterator& end, LineInfo&, VerticalPositionCache&, BidiRun* trailingSpaceRun);
    734     void layoutRunsAndFloats(bool fullLayout, bool hasInlineChild, Vector<FloatWithRect>&, int& repaintLogicalTop, int& repaintLogicalBottom);
     732    void layoutRunsAndFloats(LineLayoutState&, bool hasInlineChild, Vector<FloatWithRect>&);
    735733
    736734    // Pagination routines.
  • trunk/Source/WebCore/rendering/RenderBlockLineLayout.cpp

    r86628 r86698  
    817817}
    818818
    819 static void deleteLineRange(RenderArena* arena, RootInlineBox* startLine, int& repaintLogicalTop, int& repaintLogicalBottom, RootInlineBox* stopLine = 0)
     819// Like LayoutState for layout(), LineLayoutState keeps track of global information
     820// during an entire linebox tree layout pass (aka layoutInlineChildren).
     821class LineLayoutState {
     822public:
     823    LineLayoutState(bool fullLayout, int& repaintLogicalTop, int& repaintLogicalBottom)
     824        : m_isFullLayout(fullLayout)
     825        , m_repaintLogicalTop(repaintLogicalTop)
     826        , m_repaintLogicalBottom(repaintLogicalBottom)
     827    { }
     828
     829    void markForFullLayout() { m_isFullLayout = true; }
     830    bool isFullLayout() const { return m_isFullLayout; }
     831
     832    void setRepaintRange(int logicalHeight) { m_repaintLogicalTop = m_repaintLogicalBottom = logicalHeight; }
     833    void updateRepaintRangeFromBox(RootInlineBox* box, int paginationDelta = 0)
     834    {
     835        m_repaintLogicalTop = min(m_repaintLogicalTop, box->logicalTopVisualOverflow() + min(paginationDelta, 0));
     836        m_repaintLogicalBottom = max(m_repaintLogicalBottom, box->logicalBottomVisualOverflow() + max(paginationDelta, 0));
     837    }
     838
     839private:
     840    bool m_isFullLayout;
     841
     842    // FIXME: Should this be a range object instead of two ints?
     843    int& m_repaintLogicalTop;
     844    int& m_repaintLogicalBottom;
     845};
     846
     847static void deleteLineRange(LineLayoutState& layoutState, RenderArena* arena, RootInlineBox* startLine, RootInlineBox* stopLine = 0)
    820848{
    821849    RootInlineBox* boxToDelete = startLine;
    822850    while (boxToDelete && boxToDelete != stopLine) {
    823         repaintLogicalTop = min(repaintLogicalTop, boxToDelete->logicalTopVisualOverflow());
    824         repaintLogicalBottom = max(repaintLogicalBottom, boxToDelete->logicalBottomVisualOverflow());
     851        layoutState.updateRepaintRangeFromBox(boxToDelete);
    825852        // Note: deleteLineRange(renderArena(), firstRootBox()) is not identical to deleteLineBoxTree().
    826853        // deleteLineBoxTree uses nextLineBox() instead of nextRootBox() when traversing.
     
    831858}
    832859
    833 void RenderBlock::layoutRunsAndFloats(bool fullLayout, bool hasInlineChild, Vector<FloatWithRect>& floats, int& repaintLogicalTop, int& repaintLogicalBottom)
     860void RenderBlock::layoutRunsAndFloats(LineLayoutState& layoutState, bool hasInlineChild, Vector<FloatWithRect>& floats)
    834861{
    835862    // We want to skip ahead to the first dirty line
     
    837864    unsigned floatIndex;
    838865    LineInfo lineInfo;
     866    // FIXME: Should useRepaintBounds be on the LineLayoutState?
     867    // It appears to be used to track the case where we're only repainting a subset of our lines.
    839868    bool useRepaintBounds = false;
    840869
    841     RootInlineBox* startLine = determineStartPosition(lineInfo, fullLayout, resolver, floats, floatIndex,
    842                                                       useRepaintBounds, repaintLogicalTop, repaintLogicalBottom);
     870    RootInlineBox* startLine = determineStartPosition(layoutState, lineInfo, resolver, floats, floatIndex, useRepaintBounds);
    843871
    844872    // FIXME: This would make more sense outside of this function, but since
    845873    // determineStartPosition can change the fullLayout flag we have to do this here. Failure to call
    846874    // determineStartPosition first will break fast/repaint/line-flow-with-floats-9.html.
    847     if (fullLayout && hasInlineChild && !selfNeedsLayout()) {
     875    if (layoutState.isFullLayout() && hasInlineChild && !selfNeedsLayout()) {
    848876        setNeedsLayout(true, false);  // Mark ourselves as needing a full layout. This way we'll repaint like
    849877        // we're supposed to.
     
    867895    BidiStatus cleanLineBidiStatus;
    868896    int endLineLogicalTop = 0;
    869     RootInlineBox* endLine = (fullLayout || !startLine) ?
     897    RootInlineBox* endLine = (layoutState.isFullLayout() || !startLine) ?
    870898        0 : determineEndPosition(startLine, floats, floatIndex, cleanLineStart, cleanLineBidiStatus, endLineLogicalTop);
    871899
     
    873901        if (!useRepaintBounds) {
    874902            useRepaintBounds = true;
    875             repaintLogicalTop = logicalHeight();
    876             repaintLogicalBottom = logicalHeight();
    877         }
    878         deleteLineRange(renderArena(), startLine, repaintLogicalTop, repaintLogicalBottom);
     903            layoutState.setRepaintRange(logicalHeight());
     904        }
     905        deleteLineRange(layoutState, renderArena(), startLine);
    879906    }
    880907
    881908    InlineIterator end = resolver.position();
    882909
    883     if (!fullLayout && lastRootBox() && lastRootBox()->endsWithBreak()) {
     910    if (!layoutState.isFullLayout() && lastRootBox() && lastRootBox()->endsWithBreak()) {
    884911        // If the last line before the start line ends with a line break that clear floats,
    885912        // adjust the height accordingly.
     
    910937    while (!end.atEnd()) {
    911938        // FIXME: Is this check necessary before the first iteration or can it be moved to the end?
    912         if (checkForEndLineMatch && (endLineMatched = matchedEndLine(resolver, cleanLineStart, cleanLineBidiStatus, endLine, endLineLogicalTop, repaintLogicalBottom, repaintLogicalTop)))
     939        if (checkForEndLineMatch && (endLineMatched = matchedEndLine(layoutState, resolver, cleanLineStart, cleanLineBidiStatus, endLine, endLineLogicalTop)))
    913940            break;
    914941
     
    958985            if (lineBox) {
    959986                lineBox->setLineBreakInfo(end.m_obj, end.m_pos, resolver.status());
    960                 if (useRepaintBounds) {
    961                     repaintLogicalTop = min(repaintLogicalTop, lineBox->logicalTopVisualOverflow());
    962                     repaintLogicalBottom = max(repaintLogicalBottom, lineBox->logicalBottomVisualOverflow());
    963                 }
     987                if (useRepaintBounds)
     988                    layoutState.updateRepaintRangeFromBox(lineBox);
    964989
    965990                if (paginated) {
     
    969994                        int oldLineWidth = availableLogicalWidthForLine(oldLogicalHeight, lineInfo.isFirstLine());
    970995                        lineBox->adjustBlockDirectionPosition(adjustment);
    971                         if (useRepaintBounds) // This can only be a positive adjustment, so no need to update repaintTop.
    972                             repaintLogicalBottom = max(repaintLogicalBottom, lineBox->logicalBottomVisualOverflow());
     996                        if (useRepaintBounds)
     997                            layoutState.updateRepaintRangeFromBox(lineBox);
    973998
    974999                        if (availableLogicalWidthForLine(oldLogicalHeight + adjustment, lineInfo.isFirstLine()) != oldLineWidth) {
     
    10311056                }
    10321057                if (delta) {
    1033                     repaintLogicalTop = min(repaintLogicalTop, line->logicalTopVisualOverflow() + min(delta, 0));
    1034                     repaintLogicalBottom = max(repaintLogicalBottom, line->logicalBottomVisualOverflow() + max(delta, 0));
     1058                    layoutState.updateRepaintRangeFromBox(line, delta);
    10351059                    line->adjustBlockDirectionPosition(delta);
    10361060                }
     
    10491073        } else {
    10501074            // Delete all the remaining lines.
    1051             deleteLineRange(renderArena(), endLine, repaintLogicalTop, repaintLogicalBottom);
     1075            deleteLineRange(layoutState, renderArena(), endLine);
    10521076        }
    10531077    }
     
    11061130    // Figure out if we should clear out our line boxes.
    11071131    // FIXME: Handle resize eventually!
    1108     bool fullLayout = !firstLineBox() || selfNeedsLayout() || relayoutChildren;
    1109     if (fullLayout)
     1132    bool isFullLayout = !firstLineBox() || selfNeedsLayout() || relayoutChildren;
     1133    LineLayoutState layoutState(isFullLayout, repaintLogicalTop, repaintLogicalBottom);
     1134
     1135    if (isFullLayout)
    11101136        lineBoxes()->deleteLineBoxes(renderArena());
    11111137
     
    11451171                else if (o->isFloating())
    11461172                    floats.append(FloatWithRect(box));
    1147                 else if (fullLayout || o->needsLayout()) {
     1173                else if (layoutState.isFullLayout() || o->needsLayout()) {
    11481174                    // Replaced elements
    1149                     toRenderBox(o)->dirtyLineBoxes(fullLayout);
     1175                    toRenderBox(o)->dirtyLineBoxes(layoutState.isFullLayout());
    11501176                    o->layoutIfNeeded();
    11511177                }
     
    11531179                if (!o->isText())
    11541180                    toRenderInline(o)->updateAlwaysCreateLineBoxes();
    1155                 if (fullLayout || o->selfNeedsLayout())
    1156                     dirtyLineBoxesForRenderer(o, fullLayout);
     1181                if (layoutState.isFullLayout() || o->selfNeedsLayout())
     1182                    dirtyLineBoxesForRenderer(o, layoutState.isFullLayout());
    11571183                o->setNeedsLayout(false);
    11581184            }
     
    11601186        }
    11611187
    1162         layoutRunsAndFloats(fullLayout, hasInlineChild, floats, repaintLogicalTop, repaintLogicalBottom);
     1188        layoutRunsAndFloats(layoutState, hasInlineChild, floats);
    11631189    }
    11641190
     
    12011227            return;
    12021228        }
     1229
    12031230        if (floats[floatIndex].rect.size() != newSize) {
    12041231            int floatTop = isHorizontalWritingMode() ? floats[floatIndex].rect.y() : floats[floatIndex].rect.x();
     
    12151242}
    12161243
    1217 RootInlineBox* RenderBlock::determineStartPosition(LineInfo& lineInfo, bool& fullLayout, InlineBidiResolver& resolver, Vector<FloatWithRect>& floats,
    1218                                                    unsigned& numCleanFloats, bool& useRepaintBounds, int& repaintLogicalTop, int& repaintLogicalBottom)
     1244RootInlineBox* RenderBlock::determineStartPosition(LineLayoutState& layoutState, LineInfo& lineInfo, InlineBidiResolver& resolver, Vector<FloatWithRect>& floats,
     1245                                                   unsigned& numCleanFloats, bool& useRepaintBounds)
    12191246{
    12201247    RootInlineBox* curr = 0;
    12211248    RootInlineBox* last = 0;
    12221249
     1250    // FIXME: This entire float-checking block needs to be broken into a new function.
    12231251    bool dirtiedByFloat = false;
    1224     if (!fullLayout) {
     1252    if (!layoutState.isFullLayout()) {
    12251253        // Paginate all of the clean lines.
    12261254        bool paginated = view()->layoutState() && view()->layoutState()->isPaginated();
     
    12341262                    if (containsFloats() || !floats.isEmpty()) {
    12351263                        // FIXME: Do better eventually.  For now if we ever shift because of pagination and floats are present just go to a full layout.
    1236                         fullLayout = true;
     1264                        layoutState.markForFullLayout();
    12371265                        break;
    12381266                    }
     
    12411269                        useRepaintBounds = true;
    12421270
    1243                     repaintLogicalTop = min(repaintLogicalTop, curr->logicalTopVisualOverflow() + min(paginationDelta, 0));
    1244                     repaintLogicalBottom = max(repaintLogicalBottom, curr->logicalBottomVisualOverflow() + max(paginationDelta, 0));
     1271                    layoutState.updateRepaintRangeFromBox(curr, paginationDelta);
    12451272                    curr->adjustBlockDirectionPosition(paginationDelta);
    12461273                }
    12471274            }
    12481275
    1249             // If a new float has been inserted before this line or before its last known float,just do a full layout.
    1250             checkFloatsInCleanLine(curr, floats, floatIndex, fullLayout, dirtiedByFloat);
    1251             if (dirtiedByFloat || fullLayout)
     1276            // If a new float has been inserted before this line or before its last known float, just do a full layout.
     1277            bool encounteredNewFloat = false;
     1278            checkFloatsInCleanLine(curr, floats, floatIndex, encounteredNewFloat, dirtiedByFloat);
     1279            if (encounteredNewFloat)
     1280                layoutState.markForFullLayout();
     1281
     1282            if (dirtiedByFloat || layoutState.isFullLayout())
    12521283                break;
    12531284        }
    12541285        // Check if a new float has been inserted after the last known float.
    12551286        if (!curr && floatIndex < floats.size())
    1256             fullLayout = true;
    1257     }
    1258 
    1259     if (fullLayout) {
     1287            layoutState.markForFullLayout();
     1288    }
     1289
     1290    if (layoutState.isFullLayout()) {
    12601291        // FIXME: This should just call deleteLineBoxTree, but that causes
    12611292        // crashes for fast/repaint tests.
     
    13621393}
    13631394
    1364 bool RenderBlock::matchedEndLine(const InlineBidiResolver& resolver, const InlineIterator& endLineStart, const BidiStatus& endLineStatus, RootInlineBox*& endLine,
    1365                                  int& endLogicalTop, int& repaintLogicalBottom, int& repaintLogicalTop)
     1395bool RenderBlock::matchedEndLine(LineLayoutState& layoutState, const InlineBidiResolver& resolver, const InlineIterator& endLineStart, const BidiStatus& endLineStatus, RootInlineBox*& endLine, int& endLogicalTop)
    13661396{
    13671397    if (resolver.position() == endLineStart) {
     
    14291459
    14301460            // Now delete the lines that we failed to sync.
    1431             deleteLineRange(renderArena(), endLine, repaintLogicalTop, repaintLogicalBottom, result);
     1461            deleteLineRange(layoutState, renderArena(), endLine, result);
    14321462            endLine = result;
    14331463            return result;
Note: See TracChangeset for help on using the changeset viewer.