Title: [86698] trunk/Source/WebCore
Revision
86698
Author
[email protected]
Date
2011-05-17 12:45:24 -0700 (Tue, 17 May 2011)

Log Message

2011-05-17  Eric Seidel  <[email protected]>

        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):

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (86697 => 86698)


--- trunk/Source/WebCore/ChangeLog	2011-05-17 19:35:37 UTC (rev 86697)
+++ trunk/Source/WebCore/ChangeLog	2011-05-17 19:45:24 UTC (rev 86698)
@@ -1,3 +1,38 @@
+2011-05-17  Eric Seidel  <[email protected]>
+
+        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):
+
 2011-05-17  Andreas Kling  <[email protected]>
 
         Reviewed by Kenneth Rohde Christiansen.

Modified: trunk/Source/WebCore/rendering/RenderBlock.cpp (86697 => 86698)


--- trunk/Source/WebCore/rendering/RenderBlock.cpp	2011-05-17 19:35:37 UTC (rev 86697)
+++ trunk/Source/WebCore/rendering/RenderBlock.cpp	2011-05-17 19:45:24 UTC (rev 86698)
@@ -1282,6 +1282,7 @@
     // we overflow or not.
     updateScrollInfoAfterLayout();
 
+    // FIXME: This repaint logic should be moved into a separate helper function!
     // Repaint with our new bounds if they are different from our old bounds.
     bool didFullRepaint = repainter.repaintAfterLayout();
     if (!didFullRepaint && repaintLogicalTop != repaintLogicalBottom && (style()->visibility() == VISIBLE || enclosingLayer()->hasVisibleContent())) {

Modified: trunk/Source/WebCore/rendering/RenderBlock.h (86697 => 86698)


--- trunk/Source/WebCore/rendering/RenderBlock.h	2011-05-17 19:35:37 UTC (rev 86697)
+++ trunk/Source/WebCore/rendering/RenderBlock.h	2011-05-17 19:45:24 UTC (rev 86698)
@@ -37,6 +37,7 @@
 class InlineIterator;
 class LayoutStateMaintainer;
 class LazyLineBreakIterator;
+class LineLayoutState;
 class LineWidth;
 class RenderInline;
 class RenderText;
@@ -520,14 +521,11 @@
         EClear m_clear;
         Vector<RenderBox*> m_positionedObjects;
     };
-    
+
     void checkFloatsInCleanLine(RootInlineBox*, Vector<FloatWithRect>&, size_t& floatIndex, bool& encounteredNewFloat, bool& dirtiedByFloat);
-    RootInlineBox* determineStartPosition(LineInfo&, bool& fullLayout, InlineBidiResolver&, Vector<FloatWithRect>& floats, unsigned& numCleanFloats,
-                                          bool& useRepaintBounds, int& repaintTop, int& repaintBottom);
-    RootInlineBox* determineEndPosition(RootInlineBox* startBox, Vector<FloatWithRect>& floats, size_t floatIndex, InlineIterator& cleanLineStart,
-                                        BidiStatus& cleanLineBidiStatus, int& yPos);
-    bool matchedEndLine(const InlineBidiResolver&, const InlineIterator& endLineStart, const BidiStatus& endLineStatus,
-                        RootInlineBox*& endLine, int& endYPos, int& repaintBottom, int& repaintTop);
+    RootInlineBox* determineStartPosition(LineLayoutState&, LineInfo&, InlineBidiResolver&, Vector<FloatWithRect>&, unsigned& numCleanFloats, bool& useRepaintBounds);
+    RootInlineBox* determineEndPosition(RootInlineBox* startBox, Vector<FloatWithRect>&, size_t floatIndex, InlineIterator& cleanLineStart, BidiStatus& cleanLineBidiStatus, int& yPos);
+    bool matchedEndLine(LineLayoutState&, const InlineBidiResolver&, const InlineIterator& endLineStart, const BidiStatus& endLineStatus, RootInlineBox*& endLine, int& endYPos);
 
     RootInlineBox* constructLine(BidiRunList<BidiRun>&, const LineInfo&);
     InlineFlowBox* createLineBoxes(RenderObject*, const LineInfo&, InlineBox* childBox);
@@ -731,7 +729,7 @@
 
     // Helper function for layoutInlineChildren()
     RootInlineBox* createLineBoxesFromBidiRuns(BidiRunList<BidiRun>&, const InlineIterator& end, LineInfo&, VerticalPositionCache&, BidiRun* trailingSpaceRun);
-    void layoutRunsAndFloats(bool fullLayout, bool hasInlineChild, Vector<FloatWithRect>&, int& repaintLogicalTop, int& repaintLogicalBottom);
+    void layoutRunsAndFloats(LineLayoutState&, bool hasInlineChild, Vector<FloatWithRect>&);
 
     // Pagination routines.
     int nextPageLogicalTop(int logicalOffset) const; // Returns the top of the next page following logicalOffset.

Modified: trunk/Source/WebCore/rendering/RenderBlockLineLayout.cpp (86697 => 86698)


--- trunk/Source/WebCore/rendering/RenderBlockLineLayout.cpp	2011-05-17 19:35:37 UTC (rev 86697)
+++ trunk/Source/WebCore/rendering/RenderBlockLineLayout.cpp	2011-05-17 19:45:24 UTC (rev 86698)
@@ -816,12 +816,39 @@
     return lineBox;
 }
 
-static void deleteLineRange(RenderArena* arena, RootInlineBox* startLine, int& repaintLogicalTop, int& repaintLogicalBottom, RootInlineBox* stopLine = 0)
+// Like LayoutState for layout(), LineLayoutState keeps track of global information
+// during an entire linebox tree layout pass (aka layoutInlineChildren).
+class LineLayoutState {
+public:
+    LineLayoutState(bool fullLayout, int& repaintLogicalTop, int& repaintLogicalBottom)
+        : m_isFullLayout(fullLayout)
+        , m_repaintLogicalTop(repaintLogicalTop)
+        , m_repaintLogicalBottom(repaintLogicalBottom)
+    { }
+
+    void markForFullLayout() { m_isFullLayout = true; }
+    bool isFullLayout() const { return m_isFullLayout; }
+
+    void setRepaintRange(int logicalHeight) { m_repaintLogicalTop = m_repaintLogicalBottom = logicalHeight; }
+    void updateRepaintRangeFromBox(RootInlineBox* box, int paginationDelta = 0)
+    {
+        m_repaintLogicalTop = min(m_repaintLogicalTop, box->logicalTopVisualOverflow() + min(paginationDelta, 0));
+        m_repaintLogicalBottom = max(m_repaintLogicalBottom, box->logicalBottomVisualOverflow() + max(paginationDelta, 0));
+    }
+
+private:
+    bool m_isFullLayout;
+
+    // FIXME: Should this be a range object instead of two ints?
+    int& m_repaintLogicalTop;
+    int& m_repaintLogicalBottom;
+};
+
+static void deleteLineRange(LineLayoutState& layoutState, RenderArena* arena, RootInlineBox* startLine, RootInlineBox* stopLine = 0)
 {
     RootInlineBox* boxToDelete = startLine;
     while (boxToDelete && boxToDelete != stopLine) {
-        repaintLogicalTop = min(repaintLogicalTop, boxToDelete->logicalTopVisualOverflow());
-        repaintLogicalBottom = max(repaintLogicalBottom, boxToDelete->logicalBottomVisualOverflow());
+        layoutState.updateRepaintRangeFromBox(boxToDelete);
         // Note: deleteLineRange(renderArena(), firstRootBox()) is not identical to deleteLineBoxTree().
         // deleteLineBoxTree uses nextLineBox() instead of nextRootBox() when traversing.
         RootInlineBox* next = boxToDelete->nextRootBox();
@@ -830,21 +857,22 @@
     }
 }
 
-void RenderBlock::layoutRunsAndFloats(bool fullLayout, bool hasInlineChild, Vector<FloatWithRect>& floats, int& repaintLogicalTop, int& repaintLogicalBottom)
+void RenderBlock::layoutRunsAndFloats(LineLayoutState& layoutState, bool hasInlineChild, Vector<FloatWithRect>& floats)
 {
     // We want to skip ahead to the first dirty line
     InlineBidiResolver resolver;
     unsigned floatIndex;
     LineInfo lineInfo;
+    // FIXME: Should useRepaintBounds be on the LineLayoutState?
+    // It appears to be used to track the case where we're only repainting a subset of our lines.
     bool useRepaintBounds = false;
 
-    RootInlineBox* startLine = determineStartPosition(lineInfo, fullLayout, resolver, floats, floatIndex,
-                                                      useRepaintBounds, repaintLogicalTop, repaintLogicalBottom);
+    RootInlineBox* startLine = determineStartPosition(layoutState, lineInfo, resolver, floats, floatIndex, useRepaintBounds);
 
     // FIXME: This would make more sense outside of this function, but since
     // determineStartPosition can change the fullLayout flag we have to do this here. Failure to call
     // determineStartPosition first will break fast/repaint/line-flow-with-floats-9.html.
-    if (fullLayout && hasInlineChild && !selfNeedsLayout()) {
+    if (layoutState.isFullLayout() && hasInlineChild && !selfNeedsLayout()) {
         setNeedsLayout(true, false);  // Mark ourselves as needing a full layout. This way we'll repaint like
         // we're supposed to.
         RenderView* v = view();
@@ -866,21 +894,20 @@
     InlineIterator cleanLineStart;
     BidiStatus cleanLineBidiStatus;
     int endLineLogicalTop = 0;
-    RootInlineBox* endLine = (fullLayout || !startLine) ?
+    RootInlineBox* endLine = (layoutState.isFullLayout() || !startLine) ?
         0 : determineEndPosition(startLine, floats, floatIndex, cleanLineStart, cleanLineBidiStatus, endLineLogicalTop);
 
     if (startLine) {
         if (!useRepaintBounds) {
             useRepaintBounds = true;
-            repaintLogicalTop = logicalHeight();
-            repaintLogicalBottom = logicalHeight();
+            layoutState.setRepaintRange(logicalHeight());
         }
-        deleteLineRange(renderArena(), startLine, repaintLogicalTop, repaintLogicalBottom);
+        deleteLineRange(layoutState, renderArena(), startLine);
     }
 
     InlineIterator end = resolver.position();
 
-    if (!fullLayout && lastRootBox() && lastRootBox()->endsWithBreak()) {
+    if (!layoutState.isFullLayout() && lastRootBox() && lastRootBox()->endsWithBreak()) {
         // If the last line before the start line ends with a line break that clear floats,
         // adjust the height accordingly.
         // A line break can be either the first or the last object on a line, depending on its direction.
@@ -909,7 +936,7 @@
 
     while (!end.atEnd()) {
         // FIXME: Is this check necessary before the first iteration or can it be moved to the end?
-        if (checkForEndLineMatch && (endLineMatched = matchedEndLine(resolver, cleanLineStart, cleanLineBidiStatus, endLine, endLineLogicalTop, repaintLogicalBottom, repaintLogicalTop)))
+        if (checkForEndLineMatch && (endLineMatched = matchedEndLine(layoutState, resolver, cleanLineStart, cleanLineBidiStatus, endLine, endLineLogicalTop)))
             break;
 
         lineMidpointState.reset();
@@ -957,10 +984,8 @@
 
             if (lineBox) {
                 lineBox->setLineBreakInfo(end.m_obj, end.m_pos, resolver.status());
-                if (useRepaintBounds) {
-                    repaintLogicalTop = min(repaintLogicalTop, lineBox->logicalTopVisualOverflow());
-                    repaintLogicalBottom = max(repaintLogicalBottom, lineBox->logicalBottomVisualOverflow());
-                }
+                if (useRepaintBounds)
+                    layoutState.updateRepaintRangeFromBox(lineBox);
 
                 if (paginated) {
                     int adjustment = 0;
@@ -968,8 +993,8 @@
                     if (adjustment) {
                         int oldLineWidth = availableLogicalWidthForLine(oldLogicalHeight, lineInfo.isFirstLine());
                         lineBox->adjustBlockDirectionPosition(adjustment);
-                        if (useRepaintBounds) // This can only be a positive adjustment, so no need to update repaintTop.
-                            repaintLogicalBottom = max(repaintLogicalBottom, lineBox->logicalBottomVisualOverflow());
+                        if (useRepaintBounds)
+                            layoutState.updateRepaintRangeFromBox(lineBox);
 
                         if (availableLogicalWidthForLine(oldLogicalHeight + adjustment, lineInfo.isFirstLine()) != oldLineWidth) {
                             // We have to delete this line, remove all floats that got added, and let line layout re-run.
@@ -1030,8 +1055,7 @@
                     adjustLinePositionForPagination(line, delta);
                 }
                 if (delta) {
-                    repaintLogicalTop = min(repaintLogicalTop, line->logicalTopVisualOverflow() + min(delta, 0));
-                    repaintLogicalBottom = max(repaintLogicalBottom, line->logicalBottomVisualOverflow() + max(delta, 0));
+                    layoutState.updateRepaintRangeFromBox(line, delta);
                     line->adjustBlockDirectionPosition(delta);
                 }
                 if (Vector<RenderBox*>* cleanLineFloats = line->floatsPtr()) {
@@ -1048,7 +1072,7 @@
             setLogicalHeight(lastRootBox()->blockLogicalHeight());
         } else {
             // Delete all the remaining lines.
-            deleteLineRange(renderArena(), endLine, repaintLogicalTop, repaintLogicalBottom);
+            deleteLineRange(layoutState, renderArena(), endLine);
         }
     }
     if (m_floatingObjects && (checkForFloatsFromLastLine || positionNewFloats()) && lastRootBox()) {
@@ -1105,8 +1129,10 @@
 
     // Figure out if we should clear out our line boxes.
     // FIXME: Handle resize eventually!
-    bool fullLayout = !firstLineBox() || selfNeedsLayout() || relayoutChildren;
-    if (fullLayout)
+    bool isFullLayout = !firstLineBox() || selfNeedsLayout() || relayoutChildren;
+    LineLayoutState layoutState(isFullLayout, repaintLogicalTop, repaintLogicalBottom);
+
+    if (isFullLayout)
         lineBoxes()->deleteLineBoxes(renderArena());
 
     // Text truncation only kicks in if your overflow isn't visible and your text-overflow-mode isn't
@@ -1144,22 +1170,22 @@
                     o->containingBlock()->insertPositionedObject(box);
                 else if (o->isFloating())
                     floats.append(FloatWithRect(box));
-                else if (fullLayout || o->needsLayout()) {
+                else if (layoutState.isFullLayout() || o->needsLayout()) {
                     // Replaced elements
-                    toRenderBox(o)->dirtyLineBoxes(fullLayout);
+                    toRenderBox(o)->dirtyLineBoxes(layoutState.isFullLayout());
                     o->layoutIfNeeded();
                 }
             } else if (o->isText() || (o->isRenderInline() && !endOfInline)) {
                 if (!o->isText())
                     toRenderInline(o)->updateAlwaysCreateLineBoxes();
-                if (fullLayout || o->selfNeedsLayout())
-                    dirtyLineBoxesForRenderer(o, fullLayout);
+                if (layoutState.isFullLayout() || o->selfNeedsLayout())
+                    dirtyLineBoxesForRenderer(o, layoutState.isFullLayout());
                 o->setNeedsLayout(false);
             }
             o = bidiNext(this, o, 0, false, &endOfInline);
         }
 
-        layoutRunsAndFloats(fullLayout, hasInlineChild, floats, repaintLogicalTop, repaintLogicalBottom);
+        layoutRunsAndFloats(layoutState, hasInlineChild, floats);
     }
 
     // Expand the last line to accommodate Ruby and emphasis marks.
@@ -1200,6 +1226,7 @@
             encounteredNewFloat = true;
             return;
         }
+
         if (floats[floatIndex].rect.size() != newSize) {
             int floatTop = isHorizontalWritingMode() ? floats[floatIndex].rect.y() : floats[floatIndex].rect.x();
             int floatHeight = isHorizontalWritingMode() ? max(floats[floatIndex].rect.height(), newSize.height())
@@ -1214,14 +1241,15 @@
     }
 }
 
-RootInlineBox* RenderBlock::determineStartPosition(LineInfo& lineInfo, bool& fullLayout, InlineBidiResolver& resolver, Vector<FloatWithRect>& floats,
-                                                   unsigned& numCleanFloats, bool& useRepaintBounds, int& repaintLogicalTop, int& repaintLogicalBottom)
+RootInlineBox* RenderBlock::determineStartPosition(LineLayoutState& layoutState, LineInfo& lineInfo, InlineBidiResolver& resolver, Vector<FloatWithRect>& floats,
+                                                   unsigned& numCleanFloats, bool& useRepaintBounds)
 {
     RootInlineBox* curr = 0;
     RootInlineBox* last = 0;
 
+    // FIXME: This entire float-checking block needs to be broken into a new function.
     bool dirtiedByFloat = false;
-    if (!fullLayout) {
+    if (!layoutState.isFullLayout()) {
         // Paginate all of the clean lines.
         bool paginated = view()->layoutState() && view()->layoutState()->isPaginated();
         int paginationDelta = 0;
@@ -1233,30 +1261,33 @@
                 if (paginationDelta) {
                     if (containsFloats() || !floats.isEmpty()) {
                         // FIXME: Do better eventually.  For now if we ever shift because of pagination and floats are present just go to a full layout.
-                        fullLayout = true;
+                        layoutState.markForFullLayout();
                         break;
                     }
 
                     if (!useRepaintBounds)
                         useRepaintBounds = true;
 
-                    repaintLogicalTop = min(repaintLogicalTop, curr->logicalTopVisualOverflow() + min(paginationDelta, 0));
-                    repaintLogicalBottom = max(repaintLogicalBottom, curr->logicalBottomVisualOverflow() + max(paginationDelta, 0));
+                    layoutState.updateRepaintRangeFromBox(curr, paginationDelta);
                     curr->adjustBlockDirectionPosition(paginationDelta);
                 }
             }
 
-            // If a new float has been inserted before this line or before its last known float,just do a full layout.
-            checkFloatsInCleanLine(curr, floats, floatIndex, fullLayout, dirtiedByFloat);
-            if (dirtiedByFloat || fullLayout)
+            // If a new float has been inserted before this line or before its last known float, just do a full layout.
+            bool encounteredNewFloat = false;
+            checkFloatsInCleanLine(curr, floats, floatIndex, encounteredNewFloat, dirtiedByFloat);
+            if (encounteredNewFloat)
+                layoutState.markForFullLayout();
+
+            if (dirtiedByFloat || layoutState.isFullLayout())
                 break;
         }
         // Check if a new float has been inserted after the last known float.
         if (!curr && floatIndex < floats.size())
-            fullLayout = true;
+            layoutState.markForFullLayout();
     }
 
-    if (fullLayout) {
+    if (layoutState.isFullLayout()) {
         // FIXME: This should just call deleteLineBoxTree, but that causes
         // crashes for fast/repaint tests.
         RenderArena* arena = renderArena();
@@ -1361,8 +1392,7 @@
     return last;
 }
 
-bool RenderBlock::matchedEndLine(const InlineBidiResolver& resolver, const InlineIterator& endLineStart, const BidiStatus& endLineStatus, RootInlineBox*& endLine,
-                                 int& endLogicalTop, int& repaintLogicalBottom, int& repaintLogicalTop)
+bool RenderBlock::matchedEndLine(LineLayoutState& layoutState, const InlineBidiResolver& resolver, const InlineIterator& endLineStart, const BidiStatus& endLineStatus, RootInlineBox*& endLine, int& endLogicalTop)
 {
     if (resolver.position() == endLineStart) {
         if (resolver.status() != endLineStatus)
@@ -1428,7 +1458,7 @@
             }
 
             // Now delete the lines that we failed to sync.
-            deleteLineRange(renderArena(), endLine, repaintLogicalTop, repaintLogicalBottom, result);
+            deleteLineRange(layoutState, renderArena(), endLine, result);
             endLine = result;
             return result;
         }
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo.cgi/webkit-changes

Reply via email to