- Revision
- 240207
- Author
- [email protected]
- Date
- 2019-01-19 21:26:40 -0800 (Sat, 19 Jan 2019)
Log Message
[LFC][Floats] Ensure that floats in FloatingContext::m_floats are always horizontally ordered.
https://bugs.webkit.org/show_bug.cgi?id=193613
Reviewed by Antti Koivisto.
Source/WebCore:
Float items in m_floats list should stay in horizontal position order (left/right edge).
When adding a new float item to floating state list, we have to ensure that it is definitely the left(right)-most item.
Normally it is, but negative horizontal margins can push the float box beyond another float box.
<div style="float: left; height: 10px; width: 10px;"></div>
<div style="float: left; height: 10px; width: 10px; margin-left: -80px;"></div>
The second float's right edge beyond the first float' left edge. THe second float is not the right(inner)-most float anymore.
Test: fast/block/float/floats-with-negative-horizontal-margin.html
* layout/floats/FloatingContext.cpp:
(WebCore::Layout::areFloatsHorizontallySorted):
(WebCore::Layout::FloatingContext::positionForFloat const):
(WebCore::Layout::FloatingContext::positionForFloatAvoiding const):
(WebCore::Layout::FloatingContext::verticalPositionWithClearance const):
* layout/floats/FloatingState.cpp:
(WebCore::Layout::FloatingState::append):
Tools:
* LayoutReloaded/misc/LFC-passing-tests.txt:
LayoutTests:
* fast/block/float/floats-with-negative-horizontal-margin-expected.html: Added.
* fast/block/float/floats-with-negative-horizontal-margin.html: Added.
Modified Paths
Added Paths
Diff
Modified: trunk/LayoutTests/ChangeLog (240206 => 240207)
--- trunk/LayoutTests/ChangeLog 2019-01-20 00:28:44 UTC (rev 240206)
+++ trunk/LayoutTests/ChangeLog 2019-01-20 05:26:40 UTC (rev 240207)
@@ -1,3 +1,13 @@
+2019-01-19 Zalan Bujtas <[email protected]>
+
+ [LFC][Floats] Ensure that floats in FloatingContext::m_floats are always horizontally ordered.
+ https://bugs.webkit.org/show_bug.cgi?id=193613
+
+ Reviewed by Antti Koivisto.
+
+ * fast/block/float/floats-with-negative-horizontal-margin-expected.html: Added.
+ * fast/block/float/floats-with-negative-horizontal-margin.html: Added.
+
2019-01-19 Eric Liang <[email protected]>
AXSelected attribute on RadioButton should not be settable.
Added: trunk/LayoutTests/fast/block/float/floats-with-negative-horizontal-margin-expected.html (0 => 240207)
--- trunk/LayoutTests/fast/block/float/floats-with-negative-horizontal-margin-expected.html (rev 0)
+++ trunk/LayoutTests/fast/block/float/floats-with-negative-horizontal-margin-expected.html 2019-01-20 05:26:40 UTC (rev 240207)
@@ -0,0 +1,11 @@
+<div style="position: relative; width: 500px">
+ <div style="position: absolute; background-color: red; height: 100px; width: 100px;"></div>
+ <div style="position: absolute; left: 20px; background-color: green; height: 150px; width: 60px;"></div>
+ <div style="position: absolute; left: 0px; background-color: blue; height: 50px; width: 40px;"></div>
+ <div style="position: absolute; left: 100px; background-color: brown; height: 30px; width: 30px;"></div>
+
+ <div style="position: absolute; right: 0px; background-color: red; height: 100px; width: 100px;"></div>
+ <div style="position: absolute; right: 20px; background-color: green; height: 150px; width: 60px;"></div>
+ <div style="position: absolute; right: 0px; background-color: blue; height: 50px; width: 40px;"></div>
+ <div style="position: absolute; right: 100px; background-color: brown; height: 30px; width: 30px;"></div>
+</div>
\ No newline at end of file
Added: trunk/LayoutTests/fast/block/float/floats-with-negative-horizontal-margin.html (0 => 240207)
--- trunk/LayoutTests/fast/block/float/floats-with-negative-horizontal-margin.html (rev 0)
+++ trunk/LayoutTests/fast/block/float/floats-with-negative-horizontal-margin.html 2019-01-20 05:26:40 UTC (rev 240207)
@@ -0,0 +1,10 @@
+<div style="width: 500px;">
+ <div style="float: left; background-color: red; height: 100px; width: 100px;"></div>
+ <div style="float: right; background-color: red; height: 100px; width: 100px;"></div>
+ <div style="float: left; background-color: green; height: 150px; width: 60px; margin-left: -80px;"></div>
+ <div style="float: left; background-color: blue; height: 50px; width: 40px; margin-left: -100px;"></div>
+ <div style="float: left; background-color: brown; height: 30px; width: 30px;"></div>
+ <div style="float: right; background-color: green; height: 150px; width: 60px; margin-right: -80px"></div>
+ <div style="float: right; background-color: blue; height: 50px; width: 40px; margin-right: -100px"></div>
+ <div style="float: right; background-color: brown; height: 30px; width: 30px;"></div>
+</div>
\ No newline at end of file
Modified: trunk/Source/WebCore/ChangeLog (240206 => 240207)
--- trunk/Source/WebCore/ChangeLog 2019-01-20 00:28:44 UTC (rev 240206)
+++ trunk/Source/WebCore/ChangeLog 2019-01-20 05:26:40 UTC (rev 240207)
@@ -1,3 +1,30 @@
+2019-01-19 Zalan Bujtas <[email protected]>
+
+ [LFC][Floats] Ensure that floats in FloatingContext::m_floats are always horizontally ordered.
+ https://bugs.webkit.org/show_bug.cgi?id=193613
+
+ Reviewed by Antti Koivisto.
+
+ Float items in m_floats list should stay in horizontal position order (left/right edge).
+
+ When adding a new float item to floating state list, we have to ensure that it is definitely the left(right)-most item.
+ Normally it is, but negative horizontal margins can push the float box beyond another float box.
+
+ <div style="float: left; height: 10px; width: 10px;"></div>
+ <div style="float: left; height: 10px; width: 10px; margin-left: -80px;"></div>
+
+ The second float's right edge beyond the first float' left edge. THe second float is not the right(inner)-most float anymore.
+
+ Test: fast/block/float/floats-with-negative-horizontal-margin.html
+
+ * layout/floats/FloatingContext.cpp:
+ (WebCore::Layout::areFloatsHorizontallySorted):
+ (WebCore::Layout::FloatingContext::positionForFloat const):
+ (WebCore::Layout::FloatingContext::positionForFloatAvoiding const):
+ (WebCore::Layout::FloatingContext::verticalPositionWithClearance const):
+ * layout/floats/FloatingState.cpp:
+ (WebCore::Layout::FloatingState::append):
+
2019-01-19 Youenn Fablet <[email protected]>
getUserMedia with a deviceId exact constraint with an empty string value should succeed
Modified: trunk/Source/WebCore/layout/floats/FloatingContext.cpp (240206 => 240207)
--- trunk/Source/WebCore/layout/floats/FloatingContext.cpp 2019-01-20 00:28:44 UTC (rev 240206)
+++ trunk/Source/WebCore/layout/floats/FloatingContext.cpp 2019-01-20 05:26:40 UTC (rev 240207)
@@ -111,6 +111,38 @@
return Iterator(floatingState.floats(), WTF::nullopt);
}
+#ifndef NDEBUG
+static bool areFloatsHorizontallySorted(const FloatingState& floatingState)
+{
+ auto& floats = floatingState.floats();
+ auto rightEdgeOfLeftFloats = LayoutUnit::min();
+ auto leftEdgeOfRightFloats = LayoutUnit::max();
+ WTF::Optional<LayoutUnit> leftBottom;
+ WTF::Optional<LayoutUnit> rightBottom;
+
+ for (auto& floatItem : floats) {
+ if (floatItem.isLeftPositioned()) {
+ auto rightEdge = floatItem.rectWithMargin().right();
+ if (rightEdge < rightEdgeOfLeftFloats) {
+ if (leftBottom && floatItem.rectWithMargin().top() < *leftBottom)
+ return false;
+ }
+ leftBottom = floatItem.rectWithMargin().bottom();
+ rightEdgeOfLeftFloats = rightEdge;
+ } else {
+ auto leftEdge = floatItem.rectWithMargin().left();
+ if (leftEdge > leftEdgeOfRightFloats) {
+ if (rightBottom && floatItem.rectWithMargin().top() < *rightBottom)
+ return false;
+ }
+ rightBottom = floatItem.rectWithMargin().bottom();
+ leftEdgeOfRightFloats = leftEdge;
+ }
+ }
+ return true;
+}
+#endif
+
FloatingContext::FloatingContext(FloatingState& floatingState)
: m_floatingState(floatingState)
{
@@ -119,6 +151,7 @@
Point FloatingContext::positionForFloat(const Box& layoutBox) const
{
ASSERT(layoutBox.isFloatingPositioned());
+ ASSERT(areFloatsHorizontallySorted(m_floatingState));
if (m_floatingState.isEmpty()) {
auto& displayBox = layoutState().displayBoxForLayoutBox(layoutBox);
@@ -148,6 +181,7 @@
ASSERT(layoutBox.establishesBlockFormattingContext());
ASSERT(!layoutBox.isFloatingPositioned());
ASSERT(!layoutBox.hasFloatClear());
+ ASSERT(areFloatsHorizontallySorted(m_floatingState));
if (m_floatingState.isEmpty())
return { };
@@ -161,6 +195,7 @@
{
ASSERT(layoutBox.hasFloatClear());
ASSERT(layoutBox.isBlockLevelBox());
+ ASSERT(areFloatsHorizontallySorted(m_floatingState));
if (m_floatingState.isEmpty())
return { };
Modified: trunk/Source/WebCore/layout/floats/FloatingState.cpp (240206 => 240207)
--- trunk/Source/WebCore/layout/floats/FloatingState.cpp 2019-01-20 00:28:44 UTC (rev 240206)
+++ trunk/Source/WebCore/layout/floats/FloatingState.cpp 2019-01-20 05:26:40 UTC (rev 240207)
@@ -83,7 +83,30 @@
ASSERT(belongsToThisFloatingContext(layoutBox, *m_formattingContextRoot));
ASSERT(is<Container>(*m_formattingContextRoot));
- m_floats.append({ layoutBox, *this });
+ auto newFloatItem = FloatItem { layoutBox, *this };
+ if (m_floats.isEmpty())
+ return m_floats.append(newFloatItem);
+
+ auto& displayBox = m_layoutState.displayBoxForLayoutBox(layoutBox);
+ auto isLeftPositioned = layoutBox.isLeftFloatingPositioned();
+ // When adding a new float item to the list, we have to ensure that it is definitely the left(right)-most item.
+ // Normally it is, but negative horizontal margins can push the float box beyond another float box.
+ // Float items in m_floats list should stay in horizontal position order (left/right edge) on the same vertical position.
+ auto hasNegativeHorizontalMargin = (isLeftPositioned && displayBox.marginStart() < 0) || (!isLeftPositioned && displayBox.marginEnd() < 0);
+ if (!hasNegativeHorizontalMargin)
+ return m_floats.append(newFloatItem);
+
+ for (int i = m_floats.size() - 1; i >= 0; --i) {
+ auto& floatItem = m_floats[i];
+ if (isLeftPositioned != floatItem.isLeftPositioned())
+ continue;
+ if (newFloatItem.rectWithMargin().top() < floatItem.rectWithMargin().bottom())
+ continue;
+ if ((isLeftPositioned && newFloatItem.rectWithMargin().right() >= floatItem.rectWithMargin().right())
+ || (!isLeftPositioned && newFloatItem.rectWithMargin().left() <= floatItem.rectWithMargin().left()))
+ return m_floats.insert(i + 1, newFloatItem);
+ }
+ return m_floats.insert(0, newFloatItem);
}
FloatingState::Constraints FloatingState::constraints(PositionInContextRoot verticalPosition, const Box& formattingContextRoot) const
Modified: trunk/Tools/ChangeLog (240206 => 240207)
--- trunk/Tools/ChangeLog 2019-01-20 00:28:44 UTC (rev 240206)
+++ trunk/Tools/ChangeLog 2019-01-20 05:26:40 UTC (rev 240207)
@@ -1,3 +1,12 @@
+2019-01-19 Zalan Bujtas <[email protected]>
+
+ [LFC][Floats] Ensure that floats in FloatingContext::m_floats are always horizontally ordered.
+ https://bugs.webkit.org/show_bug.cgi?id=193613
+
+ Reviewed by Antti Koivisto.
+
+ * LayoutReloaded/misc/LFC-passing-tests.txt:
+
2019-01-19 Antoine Quint <[email protected]>
Add a POINTER_EVENTS feature flag
Modified: trunk/Tools/LayoutReloaded/misc/LFC-passing-tests.txt (240206 => 240207)
--- trunk/Tools/LayoutReloaded/misc/LFC-passing-tests.txt 2019-01-20 00:28:44 UTC (rev 240206)
+++ trunk/Tools/LayoutReloaded/misc/LFC-passing-tests.txt 2019-01-20 05:26:40 UTC (rev 240207)
@@ -121,6 +121,7 @@
fast/block/float/floats-not-cleared-crash.html
fast/block/float/crash-when-intruding-float-has-anonymous-parent-and-detach.html
fast/block/float/float-in-descendant-formatting-context.html
+fast/block/float/floats-with-negative-horizontal-margin.html
fast/block/margin-collapse/002.html
fast/block/margin-collapse/003.html
fast/block/margin-collapse/026.html