[LFC][Floats] Add support for placing formatting roots in-between floats.
authorzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 21 Feb 2019 17:58:15 +0000 (17:58 +0000)
committerzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 21 Feb 2019 17:58:15 +0000 (17:58 +0000)
https://bugs.webkit.org/show_bug.cgi?id=194902

Reviewed by Antti Koivisto.

Source/WebCore:

This patch add support for placing a formatting root box in-between existing floats.
The initial vertical position of a formatting root is its static position which can make the box
placed above exsiting floats (whereas we can never place a regular float above existing floats.)

Test: fast/block/block-only/floats-and-block-formatting-roots.html

* layout/blockformatting/BlockFormattingContext.cpp:
(WebCore::Layout::BlockFormattingContext::computePositionToAvoidFloats const):
* layout/floats/FloatingContext.cpp:
(WebCore::Layout::FloatPair::LeftRightIndex::isEmpty const):
(WebCore::Layout::FloatPair::isEmpty const):
(WebCore::Layout::FloatPair::operator* const):
(WebCore::Layout::Iterator::operator* const):
(WebCore::Layout::begin):
(WebCore::Layout::end):
(WebCore::Layout::FloatingContext::positionForFloat const):
(WebCore::Layout::FloatingContext::positionForFormattingContextRoot const):
(WebCore::Layout::findAvailablePosition):
(WebCore::Layout::FloatingContext::findPositionForFloatBox const):
(WebCore::Layout::FloatingContext::findPositionForFormattingContextRoot const):
(WebCore::Layout::FloatPair::FloatPair):
(WebCore::Layout::FloatPair::left const):
(WebCore::Layout::FloatPair::right const):
(WebCore::Layout::FloatPair::intersects const):
(WebCore::Layout::FloatPair::operator == const):
(WebCore::Layout::FloatPair::horizontalConstraints const):
(WebCore::Layout::FloatPair::bottom const):
(WebCore::Layout::Iterator::operator++):
(WebCore::Layout::Iterator::set):
(WebCore::Layout::FloatingPair::isEmpty const): Deleted.
(WebCore::Layout::FloatingPair::verticalConstraint const): Deleted.
(WebCore::Layout::FloatingContext::positionForFloatAvoiding const): Deleted.
(WebCore::Layout::FloatingContext::floatingPosition const): Deleted.
(WebCore::Layout::FloatingPair::FloatingPair): Deleted.
(WebCore::Layout::FloatingPair::left const): Deleted.
(WebCore::Layout::FloatingPair::right const): Deleted.
(WebCore::Layout::FloatingPair::intersects const): Deleted.
(WebCore::Layout::FloatingPair::operator == const): Deleted.
(WebCore::Layout::FloatingPair::horizontalConstraints const): Deleted.
(WebCore::Layout::FloatingPair::bottom const): Deleted.
* layout/floats/FloatingContext.h:

Tools:

* LayoutReloaded/misc/LFC-passing-tests.txt:

LayoutTests:

* fast/block/block-only/floats-and-block-formatting-roots-expected.html: Added.
* fast/block/block-only/floats-and-block-formatting-roots.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@241869 268f45cc-cd09-0410-ab3c-d52691b4dbfc

LayoutTests/ChangeLog
LayoutTests/fast/block/block-only/floats-and-block-formatting-roots-expected.html [new file with mode: 0644]
LayoutTests/fast/block/block-only/floats-and-block-formatting-roots.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/layout/blockformatting/BlockFormattingContext.cpp
Source/WebCore/layout/floats/FloatingContext.cpp
Source/WebCore/layout/floats/FloatingContext.h
Tools/ChangeLog
Tools/LayoutReloaded/misc/LFC-passing-tests.txt

index 6c9d341..f7b0897 100644 (file)
@@ -1,3 +1,13 @@
+2019-02-21  Zalan Bujtas  <zalan@apple.com>
+
+        [LFC][Floats] Add support for placing formatting roots in-between floats.
+        https://bugs.webkit.org/show_bug.cgi?id=194902
+
+        Reviewed by Antti Koivisto.
+
+        * fast/block/block-only/floats-and-block-formatting-roots-expected.html: Added.
+        * fast/block/block-only/floats-and-block-formatting-roots.html: Added.
+
 2019-02-21  Diego Pino Garcia  <dpino@igalia.com>
 
         [GTK] Gardening for unexpected passes
diff --git a/LayoutTests/fast/block/block-only/floats-and-block-formatting-roots-expected.html b/LayoutTests/fast/block/block-only/floats-and-block-formatting-roots-expected.html
new file mode 100644 (file)
index 0000000..42a20e1
--- /dev/null
@@ -0,0 +1,51 @@
+<style>
+.container {
+       width: 300px;
+       height: 100px;
+}
+
+div {
+       position: relative;
+}
+
+.float {
+       background-color: blue;
+}
+
+.root {
+       background-color: red;
+}
+</style>
+
+<div class=container>
+<div class=float style="width: 100px; height: 20px;"></div>
+<div class=float style="top: -20px; left: 190px; width: 110px; height: 20px;"></div>
+<div class=float style="top: -20px; width: 200px; height: 20px;"></div>
+<div class=float style="top: -20px; left: 190px; width: 110px; height: 20px;"></div>
+<div class=root  style="top: -80px; left: 100px; width: 90px; height: 20px;"></div>
+</div>
+
+<div class=container>
+<div class=float style="width: 100px; height: 20px;"></div>
+<div class=float style="top: -20px; left: 190px; width: 110px; height: 20px;"></div>
+<div class=float style="top: -20px; width: 200px; height: 20px;"></div>
+<div class=float style="top: -20px; left: 190px; width: 110px; height: 20px;"></div>
+<div class=root  style="top: -60px; left: 200px; width: 100px; height: 20px;"></div>
+</div>
+
+<div class=container>
+<div class=float style="width: 100px; height: 20px;"></div>
+<div class=float style="top: -20px; left: 190px; width: 110px; height: 20px;"></div>
+<div class=float style="top: -20px; width: 200px; height: 20px;"></div>
+<div class=float style="top: -20px; left: 190px; width: 110px; height: 20px;"></div>
+<div class=root  style="top: -40px; left: 0px; width: 190px; height: 20px;"></div>
+</div>
+
+<div class=container>
+<div class=float style="width: 100px; height: 20px;"></div>
+<div class=float style="top: -20px; left: 190px; width: 110px; height: 20px;"></div>
+<div class=float style="top: -20px; width: 200px; height: 20px;"></div>
+<div class=float style="top: -20px; left: 190px; width: 110px; height: 20px;"></div>
+<div class=root  style="top: -20px; left: 0px; width: 300px; height: 20px;"></div>
+</div>
+
diff --git a/LayoutTests/fast/block/block-only/floats-and-block-formatting-roots.html b/LayoutTests/fast/block/block-only/floats-and-block-formatting-roots.html
new file mode 100644 (file)
index 0000000..c3732de
--- /dev/null
@@ -0,0 +1,47 @@
+<style>
+.container {
+       width: 300px;
+       height: 100px;
+}
+
+.float {
+       background-color: blue;
+}
+
+.root {
+       overflow: hidden;
+       background-color: red;
+}
+</style>
+
+<div class=container>
+<div class=float style="float: left; width: 100px; height: 20px;"></div>
+<div class=float style="float: right; width: 110px; height: 20px;"></div>
+<div class=float style="float: left; width: 200px; height: 20px;"></div>
+<div class=float style="float: right; width: 110px; height: 20px;"></div>
+<div class=root style="width: 90px; height: 20px;"></div>
+</div>
+
+<div class=container>
+<div class=float style="float: left; width: 100px; height: 20px;"></div>
+<div class=float style="float: right; width: 110px; height: 20px;"></div>
+<div class=float style="float: left; width: 200px; height: 20px;"></div>
+<div class=float style="float: right; width: 110px; height: 20px;"></div>
+<div class=root style="width: 100px; height: 20px;"></div>
+</div>
+
+<div class=container>
+<div class=float style="float: left; width: 100px; height: 20px;"></div>
+<div class=float style="float: right; width: 110px; height: 20px;"></div>
+<div class=float style="float: left; width: 200px; height: 20px;"></div>
+<div class=float style="float: right; width: 110px; height: 20px;"></div>
+<div class=root style="width: 190px; height: 20px;"></div>
+</div>
+
+<div class=container>
+<div class=float style="float: left; width: 100px; height: 20px;"></div>
+<div class=float style="float: right; width: 110px; height: 20px;"></div>
+<div class=float style="float: left; width: 200px; height: 20px;"></div>
+<div class=float style="float: right; width: 110px; height: 20px;"></div>
+<div class=root style="width: 300px; height: 20px;"></div>
+</div>
index 384c6ed..2399fa5 100644 (file)
@@ -1,3 +1,52 @@
+2019-02-21  Zalan Bujtas  <zalan@apple.com>
+
+        [LFC][Floats] Add support for placing formatting roots in-between floats.
+        https://bugs.webkit.org/show_bug.cgi?id=194902
+
+        Reviewed by Antti Koivisto.
+
+        This patch add support for placing a formatting root box in-between existing floats.
+        The initial vertical position of a formatting root is its static position which can make the box
+        placed above exsiting floats (whereas we can never place a regular float above existing floats.)
+
+        Test: fast/block/block-only/floats-and-block-formatting-roots.html
+
+        * layout/blockformatting/BlockFormattingContext.cpp:
+        (WebCore::Layout::BlockFormattingContext::computePositionToAvoidFloats const):
+        * layout/floats/FloatingContext.cpp:
+        (WebCore::Layout::FloatPair::LeftRightIndex::isEmpty const):
+        (WebCore::Layout::FloatPair::isEmpty const):
+        (WebCore::Layout::FloatPair::operator* const):
+        (WebCore::Layout::Iterator::operator* const):
+        (WebCore::Layout::begin):
+        (WebCore::Layout::end):
+        (WebCore::Layout::FloatingContext::positionForFloat const):
+        (WebCore::Layout::FloatingContext::positionForFormattingContextRoot const):
+        (WebCore::Layout::findAvailablePosition):
+        (WebCore::Layout::FloatingContext::findPositionForFloatBox const):
+        (WebCore::Layout::FloatingContext::findPositionForFormattingContextRoot const):
+        (WebCore::Layout::FloatPair::FloatPair):
+        (WebCore::Layout::FloatPair::left const):
+        (WebCore::Layout::FloatPair::right const):
+        (WebCore::Layout::FloatPair::intersects const):
+        (WebCore::Layout::FloatPair::operator == const):
+        (WebCore::Layout::FloatPair::horizontalConstraints const):
+        (WebCore::Layout::FloatPair::bottom const):
+        (WebCore::Layout::Iterator::operator++):
+        (WebCore::Layout::Iterator::set):
+        (WebCore::Layout::FloatingPair::isEmpty const): Deleted.
+        (WebCore::Layout::FloatingPair::verticalConstraint const): Deleted.
+        (WebCore::Layout::FloatingContext::positionForFloatAvoiding const): Deleted.
+        (WebCore::Layout::FloatingContext::floatingPosition const): Deleted.
+        (WebCore::Layout::FloatingPair::FloatingPair): Deleted.
+        (WebCore::Layout::FloatingPair::left const): Deleted.
+        (WebCore::Layout::FloatingPair::right const): Deleted.
+        (WebCore::Layout::FloatingPair::intersects const): Deleted.
+        (WebCore::Layout::FloatingPair::operator == const): Deleted.
+        (WebCore::Layout::FloatingPair::horizontalConstraints const): Deleted.
+        (WebCore::Layout::FloatingPair::bottom const): Deleted.
+        * layout/floats/FloatingContext.h:
+
 2019-02-21  Rob Buis  <rbuis@igalia.com>
 
         Update MIME type parser
index c549c21..74e0bad 100644 (file)
@@ -291,7 +291,7 @@ void BlockFormattingContext::computePositionToAvoidFloats(const FloatingContext&
     if (floatingContext.floatingState().isEmpty())
         return;
 
-    if (auto adjustedPosition = floatingContext.positionForFloatAvoiding(layoutBox))
+    if (auto adjustedPosition = floatingContext.positionForFormattingContextRoot(layoutBox))
         layoutState.displayBoxForLayoutBox(layoutBox).setTopLeft(*adjustedPosition);
 }
 
index 98ce2e8..095af9f 100644 (file)
@@ -62,25 +62,31 @@ WTF_MAKE_ISO_ALLOCATED_IMPL(FloatingContext);
 
 class Iterator;
 
-class FloatingPair {
+class FloatPair {
 public:
-    bool isEmpty() const { return !m_leftIndex && !m_rightIndex; }
+    struct LeftRightIndex {
+        bool isEmpty() const { return !left && !right;}
+
+        Optional<unsigned> left;
+        Optional<unsigned> right;
+    };
+
+    bool isEmpty() const { return m_floatPair.isEmpty(); }
     const FloatingState::FloatItem* left() const;
     const FloatingState::FloatItem* right() const;
     bool intersects(const Display::Box::Rect&) const;
     PositionInContextRoot verticalConstraint() const { return m_verticalPosition; }
     FloatAvoider::HorizontalConstraints horizontalConstraints() const;
     PositionInContextRoot bottom() const;
-    bool operator==(const FloatingPair&) const;
+    LeftRightIndex operator*() const { return m_floatPair; };
+    bool operator==(const FloatPair&) const;
 
 private:
     friend class Iterator;
-    FloatingPair(const FloatingState::FloatList&);
+    FloatPair(const FloatingState::FloatList&);
 
     const FloatingState::FloatList& m_floats;
-
-    Optional<unsigned> m_leftIndex;
-    Optional<unsigned> m_rightIndex;
+    LeftRightIndex m_floatPair;
     PositionInContextRoot m_verticalPosition;
 };
 
@@ -88,7 +94,7 @@ class Iterator {
 public:
     Iterator(const FloatingState::FloatList&, Optional<PositionInContextRoot> verticalPosition);
 
-    const FloatingPair& operator*() const { return m_current; }
+    const FloatPair& operator*() const { return m_current; }
     Iterator& operator++();
     bool operator==(const Iterator&) const;
     bool operator!=(const Iterator&) const;
@@ -97,18 +103,18 @@ private:
     void set(PositionInContextRoot verticalPosition);
 
     const FloatingState::FloatList& m_floats;
-    FloatingPair m_current;
+    FloatPair m_current;
 };
 
-static Iterator begin(const FloatingState& floatingState, PositionInContextRoot initialVerticalPosition)
+static Iterator begin(const FloatingState::FloatList& floats, PositionInContextRoot initialVerticalPosition)
 {
     // Start with the inner-most floating pair for the initial vertical position.
-    return Iterator(floatingState.floats(), initialVerticalPosition);
+    return Iterator(floats, initialVerticalPosition);
 }
 
-static Iterator end(const FloatingState& floatingState)
+static Iterator end(const FloatingState::FloatList& floats)
 {
-    return Iterator(floatingState.floats(), WTF::nullopt);
+    return Iterator(floats, { });
 }
 
 #ifndef NDEBUG
@@ -172,11 +178,11 @@ Point FloatingContext::positionForFloat(const Box& layoutBox) const
 
     // Find the top most position where the float box fits.
     FloatBox floatBox = { layoutBox, m_floatingState, layoutState() };
-    floatingPosition(floatBox);
+    findPositionForFloatBox(floatBox);
     return floatBox.rectInContainingBlock().topLeft();
 }
 
-Optional<Point> FloatingContext::positionForFloatAvoiding(const Box& layoutBox) const
+Optional<Point> FloatingContext::positionForFormattingContextRoot(const Box& layoutBox) const
 {
     ASSERT(layoutBox.establishesBlockFormattingContext());
     ASSERT(!layoutBox.isFloatingPositioned());
@@ -187,7 +193,7 @@ Optional<Point> FloatingContext::positionForFloatAvoiding(const Box& layoutBox)
         return { };
 
     FloatAvoider floatAvoider = { layoutBox, m_floatingState, layoutState() };
-    floatingPosition(floatAvoider);
+    findPositionForFormattingContextRoot(floatAvoider);
     return { floatAvoider.rectInContainingBlock().topLeft() };
 }
 
@@ -259,79 +265,127 @@ FloatingContext::ClearancePosition FloatingContext::verticalPositionWithClearanc
     return { };
 }
 
-void FloatingContext::floatingPosition(FloatAvoider& floatAvoider) const
+static FloatPair::LeftRightIndex findAvailablePosition(FloatAvoider& floatAvoider, const FloatingState::FloatList& floats)
 {
     Optional<PositionInContextRoot> bottomMost;
-    auto end = Layout::end(m_floatingState);
-    for (auto iterator = begin(m_floatingState, { floatAvoider.rect().top() }); iterator != end; ++iterator) {
+    Optional<FloatPair::LeftRightIndex> innerMostLeftAndRight;
+    auto end = Layout::end(floats);
+    for (auto iterator = begin(floats, { floatAvoider.rect().top() }); iterator != end; ++iterator) {
         ASSERT(!(*iterator).isEmpty());
-        auto floats = *iterator;
+        auto leftRightFloatPair = *iterator;
+        innerMostLeftAndRight = innerMostLeftAndRight.valueOr(*leftRightFloatPair);
 
         // Move the box horizontally so that it either
         // 1. aligns with the current floating pair
         // 2. or with the containing block's content box if there's no float to align with at this vertical position.
-        floatAvoider.setHorizontalConstraints(floats.horizontalConstraints());
-        floatAvoider.setVerticalConstraint(floats.verticalConstraint());
+        floatAvoider.setHorizontalConstraints(leftRightFloatPair.horizontalConstraints());
+        floatAvoider.setVerticalConstraint(leftRightFloatPair.verticalConstraint());
 
         // Ensure that the float avoider
         // 1. does not "overflow" its containing block with the current horiztonal constraints. It simply means that the float avoider's
         // containing block could push the candidate position beyond the current float horizontally (too far to the left/right)
         // 2. avoids floats on both sides.
-        if (!floatAvoider.overflowsContainingBlock() && !floats.intersects(floatAvoider.rect()))
-            return;
+        if (!floatAvoider.overflowsContainingBlock() && !leftRightFloatPair.intersects(floatAvoider.rect()))
+            return *innerMostLeftAndRight;
 
-        bottomMost = floats.bottom();
+        bottomMost = leftRightFloatPair.bottom();
         // Move to the next floating pair.
     }
 
     // The candidate box is already below of all the floats.
     if (!bottomMost)
-        return;
+        return { };
 
     // Passed all the floats and still does not fit? Push it below the last float.
     floatAvoider.setVerticalConstraint(*bottomMost);
     floatAvoider.setHorizontalConstraints({ });
+    ASSERT(innerMostLeftAndRight);
+    return *innerMostLeftAndRight;
+}
+
+void FloatingContext::findPositionForFloatBox(FloatBox& floatBox) const
+{
+    findAvailablePosition(floatBox, m_floatingState.floats());
+}
+
+void FloatingContext::findPositionForFormattingContextRoot(FloatAvoider& floatAvoider) const
+{
+    // A non-floating formatting root's initial vertical position is its static position.
+    // It means that such boxes can end up vertically placed in-between existing floats (which is
+    // never the case for floats, since they cannot be placed above existing floats).
+    //  ____  ____
+    // |    || F1 |
+    // | L1 | ----
+    // |    |  ________
+    //  ----  |   R1   |
+    //         --------
+    // Document order: 1. float: left (L1) 2. float: right (R1) 3. formatting root (F1)
+    //
+    // 1. Probe for available placement at initial position (note it runs a backward probing algorithm at a specific vertical position)
+    // 2. Check if there's any intersecing float below (forward seaching)
+    // 3. Align the box with the intersected float and probe for placement again (#1). 
+    auto& floats = m_floatingState.floats();
+    while (true) {
+        auto innerMostLeftAndRight = findAvailablePosition(floatAvoider, floats);
+        if (innerMostLeftAndRight.isEmpty())
+            return;
+
+        auto overlappingFloatBox = [&floats](auto startFloatIndex, auto floatAvoiderRect) -> const FloatingState::FloatItem* {
+            for (auto i = startFloatIndex; i < floats.size(); ++i) {
+                auto& floatBox = floats[i];
+                if (floatBox.rectWithMargin().intersects(floatAvoiderRect))
+                    return &floatBox;
+            }
+            return nullptr;
+        };
+
+        auto startIndex = std::max(innerMostLeftAndRight.left.valueOr(0), innerMostLeftAndRight.right.valueOr(0)) + 1;
+        auto* intersectedFloatBox = overlappingFloatBox(startIndex, floatAvoider.rect());
+        if (!intersectedFloatBox)
+            return;
+        floatAvoider.setVerticalConstraint({ intersectedFloatBox->rectWithMargin().top() });
+    }
 }
 
-FloatingPair::FloatingPair(const FloatingState::FloatList& floats)
+FloatPair::FloatPair(const FloatingState::FloatList& floats)
     : m_floats(floats)
 {
 }
 
-const FloatingState::FloatItem* FloatingPair::left() const
+const FloatingState::FloatItem* FloatPair::left() const
 {
-    if (!m_leftIndex)
+    if (!m_floatPair.left)
         return nullptr;
 
-    ASSERT(m_floats[*m_leftIndex].isLeftPositioned());
-    return &m_floats[*m_leftIndex];
+    ASSERT(m_floats[*m_floatPair.left].isLeftPositioned());
+    return &m_floats[*m_floatPair.left];
 }
 
-const FloatingState::FloatItem* FloatingPair::right() const
+const FloatingState::FloatItem* FloatPair::right() const
 {
-    if (!m_rightIndex)
+    if (!m_floatPair.right)
         return nullptr;
 
-    ASSERT(!m_floats[*m_rightIndex].isLeftPositioned());
-    return &m_floats[*m_rightIndex];
+    ASSERT(!m_floats[*m_floatPair.right].isLeftPositioned());
+    return &m_floats[*m_floatPair.right];
 }
 
-bool FloatingPair::intersects(const Display::Box::Rect& floatAvoiderRect) const
+bool FloatPair::intersects(const Display::Box::Rect& floatAvoiderRect) const
 {
     auto intersects = [&](auto* floating) {
         return floating && floating->rectWithMargin().intersects(floatAvoiderRect);
     };
 
-    ASSERT(m_leftIndex || m_rightIndex);
+    ASSERT(!m_floatPair.isEmpty());
     return intersects(left()) || intersects(right());
 }
 
-bool FloatingPair::operator ==(const FloatingPair& other) const
+bool FloatPair::operator ==(const FloatPair& other) const
 {
-    return m_leftIndex == other.m_leftIndex && m_rightIndex == other.m_rightIndex;
+    return m_floatPair.left == other.m_floatPair.left && m_floatPair.right == other.m_floatPair.right;
 }
 
-FloatAvoider::HorizontalConstraints FloatingPair::horizontalConstraints() const
+FloatAvoider::HorizontalConstraints FloatPair::horizontalConstraints() const
 {
     Optional<PositionInContextRoot> leftEdge;
     Optional<PositionInContextRoot> rightEdge;
@@ -345,7 +399,7 @@ FloatAvoider::HorizontalConstraints FloatingPair::horizontalConstraints() const
     return { leftEdge, rightEdge };
 }
 
-PositionInContextRoot FloatingPair::bottom() const
+PositionInContextRoot FloatPair::bottom() const
 {
     auto* left = this->left();
     auto* right = this->right();
@@ -428,15 +482,15 @@ Iterator& Iterator::operator++()
     auto updateRight = (leftBottom == rightBottom) || (!leftBottom || (rightBottom && leftBottom > rightBottom)); 
 
     if (updateLeft) {
-        ASSERT(m_current.m_leftIndex);
+        ASSERT(m_current.m_floatPair.left);
         m_current.m_verticalPosition = *leftBottom;
-        m_current.m_leftIndex = findPreviousFloatingWithLowerBottom(Float::Left, *m_current.m_leftIndex);
+        m_current.m_floatPair.left = findPreviousFloatingWithLowerBottom(Float::Left, *m_current.m_floatPair.left);
     }
     
     if (updateRight) {
-        ASSERT(m_current.m_rightIndex);
+        ASSERT(m_current.m_floatPair.right);
         m_current.m_verticalPosition = *rightBottom;
-        m_current.m_rightIndex = findPreviousFloatingWithLowerBottom(Float::Right, *m_current.m_rightIndex);
+        m_current.m_floatPair.right = findPreviousFloatingWithLowerBottom(Float::Right, *m_current.m_floatPair.right);
     }
 
     return *this;
@@ -447,15 +501,11 @@ void Iterator::set(PositionInContextRoot verticalPosition)
     // Move the iterator to the initial vertical position by starting at the inner-most floating pair (last floats on left/right).
     // 1. Check if the inner-most pair covers the vertical position.
     // 2. Move outwards from the inner-most pair until the vertical postion intersects.
-    // (Note that verticalPosition has already been adjusted with the top of the last float.)
-
     m_current.m_verticalPosition = verticalPosition;
     // No floats at all?
     if (m_floats.isEmpty()) {
         ASSERT_NOT_REACHED();
-
-        m_current.m_leftIndex = { };
-        m_current.m_rightIndex = { };
+        m_current.m_floatPair = { };
         return;
     }
 
@@ -463,7 +513,7 @@ void Iterator::set(PositionInContextRoot verticalPosition)
 
         ASSERT(!m_floats.isEmpty());
 
-        auto index = floatingType == Float::Left ? m_current.m_leftIndex : m_current.m_rightIndex;
+        auto index = floatingType == Float::Left ? m_current.m_floatPair.left : m_current.m_floatPair.right;
         // Start from the end if we don't have current yet.
         index = index.valueOr(m_floats.size());
         while (true) {
@@ -471,20 +521,20 @@ void Iterator::set(PositionInContextRoot verticalPosition)
             if (!index)
                 return { };
 
-            auto bottom = m_floats[*index].rectWithMargin().bottom();
             // Is this floating intrusive on this position?
-            if (bottom > verticalPosition)
+            auto rect = m_floats[*index].rectWithMargin();
+            if (rect.top() <= verticalPosition && rect.bottom() > verticalPosition)
                 return index;
         }
 
         return { };
     };
 
-    m_current.m_leftIndex = findFloatingBelow(Float::Left);
-    m_current.m_rightIndex = findFloatingBelow(Float::Right);
+    m_current.m_floatPair.left = findFloatingBelow(Float::Left);
+    m_current.m_floatPair.right = findFloatingBelow(Float::Right);
 
-    ASSERT(!m_current.m_leftIndex || (*m_current.m_leftIndex < m_floats.size() && m_floats[*m_current.m_leftIndex].isLeftPositioned()));
-    ASSERT(!m_current.m_rightIndex || (*m_current.m_rightIndex < m_floats.size() && !m_floats[*m_current.m_rightIndex].isLeftPositioned()));
+    ASSERT(!m_current.m_floatPair.left || (*m_current.m_floatPair.left < m_floats.size() && m_floats[*m_current.m_floatPair.left].isLeftPositioned()));
+    ASSERT(!m_current.m_floatPair.right || (*m_current.m_floatPair.right < m_floats.size() && !m_floats[*m_current.m_floatPair.right].isLeftPositioned()));
 }
 
 bool Iterator::operator==(const Iterator& other) const
index 2f460e0..26b1177 100644 (file)
@@ -51,7 +51,7 @@ public:
     FloatingState& floatingState() const { return m_floatingState; }
 
     Point positionForFloat(const Box&) const;
-    Optional<Point> positionForFloatAvoiding(const Box&) const;
+    Optional<Point> positionForFormattingContextRoot(const Box&) const;
 
     struct ClearancePosition {
         Optional<Position> position;
@@ -62,7 +62,8 @@ public:
 private:
     LayoutState& layoutState() const { return m_floatingState.layoutState(); }
 
-    void floatingPosition(FloatAvoider&) const;
+    void findPositionForFloatBox(FloatBox&) const;
+    void findPositionForFormattingContextRoot(FloatAvoider&) const;
 
     FloatingState& m_floatingState;
 };
index acbbe25..e178f87 100644 (file)
@@ -1,3 +1,12 @@
+2019-02-21  Zalan Bujtas  <zalan@apple.com>
+
+        [LFC][Floats] Add support for placing formatting roots in-between floats.
+        https://bugs.webkit.org/show_bug.cgi?id=194902
+
+        Reviewed by Antti Koivisto.
+
+        * LayoutReloaded/misc/LFC-passing-tests.txt:
+
 2019-02-21  Adrian Perez de Castro  <aperez@igalia.com>
 
         [WPE] Do not hardcode WPEBackend-fdo library name for linking tests
index 5affc29..ced009e 100644 (file)
@@ -81,6 +81,7 @@ fast/block/block-only/floating-multiple-lefts-in-body.html
 fast/block/block-only/floating-multiple-lefts-multiple-lines.html
 fast/block/block-only/floating-multiple-lefts.html
 fast/block/block-only/floating-with-new-block-formatting-context.html
+fast/block/block-only/floats-and-block-formatting-roots.html
 fast/block/block-only/inflow-min-max-height.html
 fast/block/block-only/inflow-min-max-width.html
 fast/block/block-only/margin-collapse-bottom-bottom.html
@@ -843,9 +844,10 @@ css2.1/20110323/float-replaced-width-004.htm
 css2.1/20110323/float-replaced-width-005.htm
 css2.1/20110323/float-replaced-width-006.htm
 css2.1/20110323/float-replaced-width-011.htm
-css2.1/20110323/floats-wrap-top-below-bfc-002l.htm
 css2.1/20110323/floats-001.html
 css2.1/20110323/floats-102.html
+css2.1/20110323/floats-wrap-top-below-bfc-002l.htm
+css2.1/20110323/floats-wrap-top-below-bfc-002r.htm
 css2.1/20110323/inline-block-non-replaced-width-001.htm
 css2.1/20110323/inline-block-non-replaced-width-002.htm
 css2.1/20110323/inline-block-non-replaced-width-003.htm