- 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*);