Title: [136656] trunk
Revision
136656
Author
[email protected]
Date
2012-12-05 01:54:12 -0800 (Wed, 05 Dec 2012)

Log Message

Reduce the children repaints when moved multiple times during the layout
https://bugs.webkit.org/show_bug.cgi?id=103510

Reviewed by Darin Adler.

Source/WebCore:

Cache the children positions before the layout and move to the
final position after the layout.

Test: css3/flexbox/repaint-column-reverse.html

* rendering/RenderFlexibleBox.cpp:
(WebCore::RenderFlexibleBox::OrderIterator::OrderIterator): Do not
call first() on the consructor.
(WebCore::RenderFlexibleBox::layoutBlock): Use a Vector with the
children frame rects before the layout and call
repaintChildrenDuringLayoutIfMoved() to repaint the children that
have been moved.
(WebCore::RenderFlexibleBox::appendChildrenFrameRects): Return a
Vector with children frame rects.
(WebCore::RenderFlexibleBox::repaintChildrenDuringLayoutIfMoved):
Call repaintDuringLayoutIfMoved() for every children using the old
frame rects.
(WebCore::RenderFlexibleBox::setFlowAwareLocationForChild): Do not
call repaintDuringLayoutIfMoved().
(WebCore::RenderFlexibleBox::layoutFlexItems): Make sure the
passed iterator points to the first child.
* rendering/RenderFlexibleBox.h:

LayoutTests:

Add test to check that for flex items moved multiple times during the
layout, only the initial and final positions are repainted.

* css3/flexbox/repaint-column-reverse-expected.txt: Added.
* css3/flexbox/repaint-column-reverse.html: Added.
* platform/chromium-linux/css3/flexbox/repaint-column-reverse-expected.png: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (136655 => 136656)


--- trunk/LayoutTests/ChangeLog	2012-12-05 09:42:18 UTC (rev 136655)
+++ trunk/LayoutTests/ChangeLog	2012-12-05 09:54:12 UTC (rev 136656)
@@ -1,3 +1,17 @@
+2012-12-04  Carlos Garcia Campos  <[email protected]>
+
+        Reduce the children repaints when moved multiple times during the layout
+        https://bugs.webkit.org/show_bug.cgi?id=103510
+
+        Reviewed by Darin Adler.
+
+        Add test to check that for flex items moved multiple times during the
+        layout, only the initial and final positions are repainted.
+
+        * css3/flexbox/repaint-column-reverse-expected.txt: Added.
+        * css3/flexbox/repaint-column-reverse.html: Added.
+        * platform/chromium-linux/css3/flexbox/repaint-column-reverse-expected.png: Added.
+
 2012-12-05  Dominik Röttsches  <[email protected]>
 
         [EFL] Unreviewed gardening.

Added: trunk/LayoutTests/css3/flexbox/repaint-column-reverse-expected.txt (0 => 136656)


--- trunk/LayoutTests/css3/flexbox/repaint-column-reverse-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/css3/flexbox/repaint-column-reverse-expected.txt	2012-12-05 09:54:12 UTC (rev 136656)
@@ -0,0 +1 @@
+

Added: trunk/LayoutTests/css3/flexbox/repaint-column-reverse.html (0 => 136656)


--- trunk/LayoutTests/css3/flexbox/repaint-column-reverse.html	                        (rev 0)
+++ trunk/LayoutTests/css3/flexbox/repaint-column-reverse.html	2012-12-05 09:54:12 UTC (rev 136656)
@@ -0,0 +1,38 @@
+<!DOCTYPE html>
+<style>
+#flexbox {
+    display: -webkit-flex;
+    -webkit-flex-flow: column-reverse;
+    width: 200px;
+}
+.flex-item {
+    height: 30px;
+}
+</style>
+<script>
+function changeChildMargin()
+{
+    document.getElementById("blue").style.margin = "1px";
+    if (window.testRunner)
+        testRunner.notifyDone();
+}
+
+window._onload_ = function() {
+    if (window.testRunner) {
+        testRunner.dumpAsText(true);
+        testRunner.waitUntilDone();
+        testRunner.display();
+    } else {
+        document.body.appendChild(document.createTextNode(
+            "This test checks that for flex items that are moved multiple times during the layout "
+            + "only the initial and final positions are repainted. Only the blue flex item should be repainted "
+            + "after changing its position. If the other flex items are repainted, this test fails."));
+    }
+    setTimeout(changeChildMargin, 0);
+};
+</script>
+<div id="flexbox">
+  <div id="blue" class="flex-item" style="background-color: blue;"></div>
+  <div id="green" class="flex-item" style="background-color: green;"></div>
+  <div id="yellow" class="flex-item" style="background-color: yellow;"></div>
+</div>

Added: trunk/LayoutTests/platform/chromium-linux/css3/flexbox/repaint-column-reverse-expected.png


(Binary files differ)
Property changes on: trunk/LayoutTests/platform/chromium-linux/css3/flexbox/repaint-column-reverse-expected.png ___________________________________________________________________

Added: svn:mime-type

Modified: trunk/Source/WebCore/ChangeLog (136655 => 136656)


--- trunk/Source/WebCore/ChangeLog	2012-12-05 09:42:18 UTC (rev 136655)
+++ trunk/Source/WebCore/ChangeLog	2012-12-05 09:54:12 UTC (rev 136656)
@@ -1,3 +1,33 @@
+2012-12-04  Carlos Garcia Campos  <[email protected]>
+
+        Reduce the children repaints when moved multiple times during the layout
+        https://bugs.webkit.org/show_bug.cgi?id=103510
+
+        Reviewed by Darin Adler.
+
+        Cache the children positions before the layout and move to the
+        final position after the layout.
+
+        Test: css3/flexbox/repaint-column-reverse.html
+
+        * rendering/RenderFlexibleBox.cpp:
+        (WebCore::RenderFlexibleBox::OrderIterator::OrderIterator): Do not
+        call first() on the consructor.
+        (WebCore::RenderFlexibleBox::layoutBlock): Use a Vector with the
+        children frame rects before the layout and call
+        repaintChildrenDuringLayoutIfMoved() to repaint the children that
+        have been moved.
+        (WebCore::RenderFlexibleBox::appendChildrenFrameRects): Return a
+        Vector with children frame rects.
+        (WebCore::RenderFlexibleBox::repaintChildrenDuringLayoutIfMoved):
+        Call repaintDuringLayoutIfMoved() for every children using the old
+        frame rects.
+        (WebCore::RenderFlexibleBox::setFlowAwareLocationForChild): Do not
+        call repaintDuringLayoutIfMoved().
+        (WebCore::RenderFlexibleBox::layoutFlexItems): Make sure the
+        passed iterator points to the first child.
+        * rendering/RenderFlexibleBox.h:
+
 2012-12-05  Dan Carney  <[email protected]>
 
         [V8] toV8Fast for all classes with ScriptWrapper Holder objects

Modified: trunk/Source/WebCore/rendering/RenderFlexibleBox.cpp (136655 => 136656)


--- trunk/Source/WebCore/rendering/RenderFlexibleBox.cpp	2012-12-05 09:42:18 UTC (rev 136655)
+++ trunk/Source/WebCore/rendering/RenderFlexibleBox.cpp	2012-12-05 09:54:12 UTC (rev 136656)
@@ -58,7 +58,6 @@
     {
         copyToVector(orderValues, m_orderValues);
         std::sort(m_orderValues.begin(), m_orderValues.end());
-        first();
     }
 
     RenderBox* currentChild() { return m_currentChild; }
@@ -333,6 +332,9 @@
     OrderHashSet orderValues;
     computeMainAxisPreferredSizes(relayoutChildren, orderValues);
     m_orderIterator = adoptPtr(new OrderIterator(this, orderValues));
+
+    ChildFrameRects oldChildRects;
+    appendChildFrameRects(oldChildRects);
     layoutFlexItems(*m_orderIterator, lineContexts);
 
     LayoutUnit oldClientAfterEdge = clientLogicalBottom();
@@ -349,6 +351,7 @@
     computeRegionRangeForBlock();
     clearChildOverrideSizes();
 
+    repaintChildrenDuringLayoutIfMoved(oldChildRects);
     // FIXME: css3/flexbox/repaint-rtl-column.html seems to repaint more overflow than it needs to.
     computeOverflow(oldClientAfterEdge);
     statePusher.pop();
@@ -364,6 +367,35 @@
     setNeedsLayout(false);
 }
 
+void RenderFlexibleBox::appendChildFrameRects(ChildFrameRects& childFrameRects)
+{
+    ASSERT(m_orderIterator);
+
+    for (RenderBox* child = m_orderIterator->first(); child; child = m_orderIterator->next()) {
+        if (!child->isOutOfFlowPositioned())
+            childFrameRects.append(child->frameRect());
+    }
+}
+
+void RenderFlexibleBox::repaintChildrenDuringLayoutIfMoved(const ChildFrameRects& oldChildRects)
+{
+    ASSERT(m_orderIterator);
+
+    size_t childIndex = 0;
+    for (RenderBox* child = m_orderIterator->first(); child; child = m_orderIterator->next()) {
+        if (child->isOutOfFlowPositioned())
+            continue;
+
+        // If the child moved, we have to repaint it as well as any floating/positioned
+        // descendants. An exception is if we need a layout. In this case, we know we're going to
+        // repaint ourselves (and the child) anyway.
+        if (!selfNeedsLayout() && child->checkForRepaintDuringLayout())
+            child->repaintDuringLayoutIfMoved(oldChildRects[childIndex]);
+        ++childIndex;
+    }
+    ASSERT(childIndex == oldChildRects.size());
+}
+
 void RenderFlexibleBox::paintChildren(PaintInfo& paintInfo, const LayoutPoint& paintOffset, PaintInfo& paintInfoForChild, bool usePrintRect)
 {
     ASSERT(m_orderIterator);
@@ -664,21 +696,10 @@
 
 void RenderFlexibleBox::setFlowAwareLocationForChild(RenderBox* child, const LayoutPoint& location)
 {
-    LayoutRect oldFrameRect = child->frameRect();
-
     if (isHorizontalFlow())
         child->setLocation(location);
     else
         child->setLocation(location.transposedPoint());
-
-    // If the child moved, we have to repaint it as well as any floating/positioned
-    // descendants. An exception is if we need a layout. In this case, we know we're going to
-    // repaint ourselves (and the child) anyway.
-    // FIXME: In some cases, we might overpaint as we move a child multiple times. We could reduce
-    // overpainting by keeping track of the original position of a child and running this check on
-    // the final position.
-    if (!selfNeedsLayout() && child->checkForRepaintDuringLayout())
-        child->repaintDuringLayoutIfMoved(oldFrameRect);
 }
 
 LayoutUnit RenderFlexibleBox::mainAxisBorderAndPaddingExtentForChild(RenderBox* child) const
@@ -710,6 +731,7 @@
     double totalWeightedFlexShrink;
     LayoutUnit minMaxAppliedMainAxisExtent;
 
+    iterator.first();
     LayoutUnit crossAxisOffset = flowAwareBorderBefore() + flowAwarePaddingBefore();
     while (computeNextFlexLine(iterator, orderedChildren, preferredMainAxisExtent, totalFlexGrow, totalWeightedFlexShrink, minMaxAppliedMainAxisExtent)) {
         LayoutUnit availableFreeSpace = mainAxisContentExtent(preferredMainAxisExtent) - preferredMainAxisExtent;

Modified: trunk/Source/WebCore/rendering/RenderFlexibleBox.h (136655 => 136656)


--- trunk/Source/WebCore/rendering/RenderFlexibleBox.h	2012-12-05 09:42:18 UTC (rev 136655)
+++ trunk/Source/WebCore/rendering/RenderFlexibleBox.h	2012-12-05 09:54:12 UTC (rev 136656)
@@ -78,6 +78,9 @@
     struct LineContext;
     struct Violation;
 
+    // Use an inline capacity of 8, since flexbox containers usually have less than 8 children.
+    typedef Vector<LayoutRect, 8> ChildFrameRects;
+
     bool hasOrthogonalFlow(RenderBox* child) const;
     bool isColumnFlow() const;
     bool isLeftToRightFlow() const;
@@ -122,6 +125,8 @@
     bool updateAutoMarginsInCrossAxis(RenderBox* child, LayoutUnit availableAlignmentSpace);
     void repositionLogicalHeightDependentFlexItems(OrderIterator&, WTF::Vector<LineContext>&, LayoutUnit& oldClientAfterEdge);
     void clearChildOverrideSizes();
+    void appendChildFrameRects(ChildFrameRects&);
+    void repaintChildrenDuringLayoutIfMoved(const ChildFrameRects&);
 
     LayoutUnit availableAlignmentSpaceForChild(LayoutUnit lineCrossAxisExtent, RenderBox*);
     LayoutUnit marginBoxAscentForChild(RenderBox*);
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to