- Revision
- 136324
- Author
- t...@chromium.org
- Date
- 2012-12-02 02:39:51 -0800 (Sun, 02 Dec 2012)
Log Message
Avoid a second layout of flex items in layoutAndPlaceChildren()
https://bugs.webkit.org/show_bug.cgi?id=102352
Reviewed by Ojan Vafai.
Source/WebCore:
Avoid doing a second layout if we're going to get the same size as before.
This prevents us from doing an exponential number of layouts in some
common cases.
Test: css3/flexbox/stretch-after-sibling-size-change.html
* html/shadow/SliderThumbElement.cpp:
(WebCore::RenderSliderContainer::layout): Force a layout of the track, which positions the thumb.
* rendering/RenderFlexibleBox.cpp:
(WebCore::RenderFlexibleBox::needToStretchChild): Determine if a child is going to stretch.
(WebCore::RenderFlexibleBox::resetAutoMarginsAndLogicalTopInCrossAxis): Makes sure we're in a consistent state before
we apply auto margins.
(WebCore::RenderFlexibleBox::layoutAndPlaceChildren):
* rendering/RenderFlexibleBox.h: Add needToStretchChild.
LayoutTests:
Add a test case to make sure we relayout when a sibling is stretching.
* css3/flexbox/stretch-after-sibling-size-change-expected.txt: Added.
* css3/flexbox/stretch-after-sibling-size-change.html: Added.
Modified Paths
Added Paths
Diff
Modified: trunk/LayoutTests/ChangeLog (136323 => 136324)
--- trunk/LayoutTests/ChangeLog 2012-12-02 10:31:42 UTC (rev 136323)
+++ trunk/LayoutTests/ChangeLog 2012-12-02 10:39:51 UTC (rev 136324)
@@ -1,3 +1,15 @@
+2012-12-02 Tony Chang <t...@chromium.org>
+
+ Avoid a second layout of flex items in layoutAndPlaceChildren()
+ https://bugs.webkit.org/show_bug.cgi?id=102352
+
+ Reviewed by Ojan Vafai.
+
+ Add a test case to make sure we relayout when a sibling is stretching.
+
+ * css3/flexbox/stretch-after-sibling-size-change-expected.txt: Added.
+ * css3/flexbox/stretch-after-sibling-size-change.html: Added.
+
2012-12-02 Yongjun Zhang <yongjun_zh...@apple.com>
Need a method to close all idle localstorage databases immediately.
Added: trunk/LayoutTests/css3/flexbox/stretch-after-sibling-size-change-expected.txt (0 => 136324)
--- trunk/LayoutTests/css3/flexbox/stretch-after-sibling-size-change-expected.txt (rev 0)
+++ trunk/LayoutTests/css3/flexbox/stretch-after-sibling-size-change-expected.txt 2012-12-02 10:39:51 UTC (rev 136324)
@@ -0,0 +1 @@
+PASS
Added: trunk/LayoutTests/css3/flexbox/stretch-after-sibling-size-change.html (0 => 136324)
--- trunk/LayoutTests/css3/flexbox/stretch-after-sibling-size-change.html (rev 0)
+++ trunk/LayoutTests/css3/flexbox/stretch-after-sibling-size-change.html 2012-12-02 10:39:51 UTC (rev 136324)
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+<head>
+<link href="" rel="stylesheet">
+<script src=""
+<script>
+window._onload_ = function()
+{
+ document.getElementById("a").style.height = "20px"
+ checkLayout(".flexbox");
+};
+</script>
+</head>
+<body>
+<div data-expected-width="100" data-expected-height="20" class="flexbox" style="width: 100px">
+ <div id=a class="flex-one" data-expected-width="50" data-expected-height="20" style="background-color: blue; height: 30px;"></div>
+ <div id=b class="flex-one" data-expected-width="50" data-expected-height="20" style="background-color: green"></div>
+</div>
+</body>
+</html>
Modified: trunk/Source/WebCore/ChangeLog (136323 => 136324)
--- trunk/Source/WebCore/ChangeLog 2012-12-02 10:31:42 UTC (rev 136323)
+++ trunk/Source/WebCore/ChangeLog 2012-12-02 10:39:51 UTC (rev 136324)
@@ -1,3 +1,25 @@
+2012-12-02 Tony Chang <t...@chromium.org>
+
+ Avoid a second layout of flex items in layoutAndPlaceChildren()
+ https://bugs.webkit.org/show_bug.cgi?id=102352
+
+ Reviewed by Ojan Vafai.
+
+ Avoid doing a second layout if we're going to get the same size as before.
+ This prevents us from doing an exponential number of layouts in some
+ common cases.
+
+ Test: css3/flexbox/stretch-after-sibling-size-change.html
+
+ * html/shadow/SliderThumbElement.cpp:
+ (WebCore::RenderSliderContainer::layout): Force a layout of the track, which positions the thumb.
+ * rendering/RenderFlexibleBox.cpp:
+ (WebCore::RenderFlexibleBox::needToStretchChild): Determine if a child is going to stretch.
+ (WebCore::RenderFlexibleBox::resetAutoMarginsAndLogicalTopInCrossAxis): Makes sure we're in a consistent state before
+ we apply auto margins.
+ (WebCore::RenderFlexibleBox::layoutAndPlaceChildren):
+ * rendering/RenderFlexibleBox.h: Add needToStretchChild.
+
2012-12-02 Yongjun Zhang <yongjun_zh...@apple.com>
Need a method to close all idle localstorage databases immediately.
Modified: trunk/Source/WebCore/html/shadow/SliderThumbElement.cpp (136323 => 136324)
--- trunk/Source/WebCore/html/shadow/SliderThumbElement.cpp 2012-12-02 10:31:42 UTC (rev 136323)
+++ trunk/Source/WebCore/html/shadow/SliderThumbElement.cpp 2012-12-02 10:39:51 UTC (rev 136324)
@@ -178,10 +178,13 @@
}
RenderBox* thumb = 0;
+ RenderBox* track = 0;
if (input->sliderThumbElement() && input->sliderThumbElement()->renderer()) {
thumb = toRenderBox(input->sliderThumbElement()->renderer());
- // Reset the thumb location before layout.
- thumb->setLocation(LayoutPoint());
+ track = toRenderBox(thumb->parent());
+ // Force a layout to reset the position of the thumb so the code below doesn't move the thumb to the wrong place.
+ // FIXME: Make a custom Render class for the track and move the thumb positioning code there.
+ track->setChildNeedsLayout(true, MarkOnlyThis);
}
RenderFlexibleBox::layout();
@@ -190,7 +193,6 @@
// These should always exist, unless someone mutates the shadow DOM (e.g., in the inspector).
if (!thumb)
return;
- RenderBox* track = toRenderBox(thumb->parent());
double percentageOffset = sliderPosition(input).toDouble();
LayoutUnit availableExtent = isVertical ? track->contentHeight() : track->contentWidth();
Modified: trunk/Source/WebCore/rendering/RenderFlexibleBox.cpp (136323 => 136324)
--- trunk/Source/WebCore/rendering/RenderFlexibleBox.cpp 2012-12-02 10:31:42 UTC (rev 136323)
+++ trunk/Source/WebCore/rendering/RenderFlexibleBox.cpp 2012-12-02 10:39:51 UTC (rev 136324)
@@ -1065,6 +1065,21 @@
return count;
}
+bool RenderFlexibleBox::needToStretchChild(RenderBox* child)
+{
+ if (alignmentForChild(child) != AlignStretch)
+ return false;
+
+ Length crossAxisLength = isHorizontalFlow() ? child->style()->height() : child->style()->width();
+ return crossAxisLength.isAuto();
+}
+
+void RenderFlexibleBox::resetAutoMarginsAndLogicalTopInCrossAxis(RenderBox* child)
+{
+ if (hasAutoMarginsInCrossAxis(child))
+ child->updateLogicalHeight();
+}
+
void RenderFlexibleBox::layoutAndPlaceChildren(LayoutUnit& crossAxisOffset, const OrderedFlexItemList& children, const WTF::Vector<LayoutUnit>& childSizes, LayoutUnit availableFreeSpace, WTF::Vector<LineContext>& lineContexts)
{
ASSERT(childSizes.size() == children.size());
@@ -1090,7 +1105,12 @@
LayoutUnit childPreferredSize = childSizes[i] + mainAxisBorderAndPaddingExtentForChild(child);
setLogicalOverrideSize(child, childPreferredSize);
// FIXME: Can avoid laying out here in some cases. See https://webkit.org/b/87905.
- child->setChildNeedsLayout(true, MarkOnlyThis);
+ if (needToStretchChild(child) || childPreferredSize != mainAxisExtentForChild(child))
+ child->setChildNeedsLayout(true, MarkOnlyThis);
+ else {
+ // To avoid double applying margin changes in updateAutoMarginsInCrossAxis, we reset the margins here.
+ resetAutoMarginsAndLogicalTopInCrossAxis(child);
+ }
child->layoutIfNeeded();
updateAutoMarginsInMainAxis(child, autoMarginOffset);
Modified: trunk/Source/WebCore/rendering/RenderFlexibleBox.h (136323 => 136324)
--- trunk/Source/WebCore/rendering/RenderFlexibleBox.h 2012-12-02 10:31:42 UTC (rev 136323)
+++ trunk/Source/WebCore/rendering/RenderFlexibleBox.h 2012-12-02 10:39:51 UTC (rev 136324)
@@ -134,6 +134,8 @@
bool resolveFlexibleLengths(FlexSign, const OrderedFlexItemList&, LayoutUnit& availableFreeSpace, double& totalFlexGrow, double& totalWeightedFlexShrink, InflexibleFlexItemSize&, WTF::Vector<LayoutUnit>& childSizes);
void freezeViolations(const WTF::Vector<Violation>&, LayoutUnit& availableFreeSpace, double& totalFlexGrow, double& totalWeightedFlexShrink, InflexibleFlexItemSize&);
+ void resetAutoMarginsAndLogicalTopInCrossAxis(RenderBox*);
+ bool needToStretchChild(RenderBox*);
void setLogicalOverrideSize(RenderBox* child, LayoutUnit childPreferredSize);
void prepareChildForPositionedLayout(RenderBox* child, LayoutUnit mainAxisOffset, LayoutUnit crossAxisOffset, PositionedLayoutMode);
size_t numberOfInFlowPositionedChildren(const OrderedFlexItemList&) const;