[LFC][Floating] Add skeleton for basic positioning.
authorzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 26 Jul 2018 14:30:39 +0000 (14:30 +0000)
committerzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 26 Jul 2018 14:30:39 +0000 (14:30 +0000)
https://bugs.webkit.org/show_bug.cgi?id=187974

Reviewed by Antti Koivisto.

Add floating boxes to an empty floating context.

* layout/FloatingContext.cpp:
(WebCore::Layout::FloatingContext::FloatingContext):
(WebCore::Layout::FloatingContext::computePosition):
* layout/FloatingContext.h:
(WebCore::Layout::FloatingContext::floatingState const):
(WebCore::Layout::FloatingContext::layoutContext const):
* layout/FloatingState.cpp:
(WebCore::Layout::FloatingState::FloatingState):
(WebCore::Layout::FloatingState::append):
* layout/FloatingState.h:
(WebCore::Layout::FloatingState::create):
(WebCore::Layout::FloatingState::isEmpty const):
(WebCore::Layout::FloatingState::layoutContext const):
* layout/FormattingState.h:
* layout/LayoutContext.cpp:
(WebCore::Layout::LayoutContext::establishedFormattingState):
* layout/LayoutContext.h:
* layout/blockformatting/BlockFormattingContext.cpp:
(WebCore::Layout::BlockFormattingContext::layout const):
(WebCore::Layout::BlockFormattingContext::layoutFormattingContextRoot const):
(WebCore::Layout::BlockFormattingContext::computeFloatingPosition const):
* layout/blockformatting/BlockFormattingContext.h:
* layout/blockformatting/BlockInvalidation.cpp:
(WebCore::Layout::invalidationStopsAtFormattingContextBoundary):
* layout/layouttree/LayoutBox.cpp:
(WebCore::Layout::Box::isLeftFloatingPositioned const):
(WebCore::Layout::Box::isRightFloatingPositioned const):
* layout/layouttree/LayoutBox.h:

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

13 files changed:
Source/WebCore/ChangeLog
Source/WebCore/layout/FloatingContext.cpp
Source/WebCore/layout/FloatingContext.h
Source/WebCore/layout/FloatingState.cpp
Source/WebCore/layout/FloatingState.h
Source/WebCore/layout/FormattingState.h
Source/WebCore/layout/LayoutContext.cpp
Source/WebCore/layout/LayoutContext.h
Source/WebCore/layout/blockformatting/BlockFormattingContext.cpp
Source/WebCore/layout/blockformatting/BlockFormattingContext.h
Source/WebCore/layout/blockformatting/BlockInvalidation.cpp
Source/WebCore/layout/layouttree/LayoutBox.cpp
Source/WebCore/layout/layouttree/LayoutBox.h

index 52a8290..15c3885 100644 (file)
@@ -1,5 +1,43 @@
 2018-07-26  Zalan Bujtas  <zalan@apple.com>
 
+        [LFC][Floating] Add skeleton for basic positioning.
+        https://bugs.webkit.org/show_bug.cgi?id=187974
+
+        Reviewed by Antti Koivisto.
+
+        Add floating boxes to an empty floating context.
+
+        * layout/FloatingContext.cpp:
+        (WebCore::Layout::FloatingContext::FloatingContext):
+        (WebCore::Layout::FloatingContext::computePosition):
+        * layout/FloatingContext.h:
+        (WebCore::Layout::FloatingContext::floatingState const):
+        (WebCore::Layout::FloatingContext::layoutContext const):
+        * layout/FloatingState.cpp:
+        (WebCore::Layout::FloatingState::FloatingState):
+        (WebCore::Layout::FloatingState::append):
+        * layout/FloatingState.h:
+        (WebCore::Layout::FloatingState::create):
+        (WebCore::Layout::FloatingState::isEmpty const):
+        (WebCore::Layout::FloatingState::layoutContext const):
+        * layout/FormattingState.h:
+        * layout/LayoutContext.cpp:
+        (WebCore::Layout::LayoutContext::establishedFormattingState):
+        * layout/LayoutContext.h:
+        * layout/blockformatting/BlockFormattingContext.cpp:
+        (WebCore::Layout::BlockFormattingContext::layout const):
+        (WebCore::Layout::BlockFormattingContext::layoutFormattingContextRoot const):
+        (WebCore::Layout::BlockFormattingContext::computeFloatingPosition const):
+        * layout/blockformatting/BlockFormattingContext.h:
+        * layout/blockformatting/BlockInvalidation.cpp:
+        (WebCore::Layout::invalidationStopsAtFormattingContextBoundary):
+        * layout/layouttree/LayoutBox.cpp:
+        (WebCore::Layout::Box::isLeftFloatingPositioned const):
+        (WebCore::Layout::Box::isRightFloatingPositioned const):
+        * layout/layouttree/LayoutBox.h:
+
+2018-07-26  Zalan Bujtas  <zalan@apple.com>
+
         [LFC][BFC] Do not try to access containing block's height during descendant height computation
         https://bugs.webkit.org/show_bug.cgi?id=187970
 
index 9ebfb2d..df1dcf6 100644 (file)
@@ -28,6 +28,9 @@
 
 #if ENABLE(LAYOUT_FORMATTING_CONTEXT)
 
+#include "LayoutBox.h"
+#include "LayoutContainer.h"
+#include "LayoutContext.h"
 #include <wtf/IsoMallocInlines.h>
 
 namespace WebCore {
@@ -35,12 +38,29 @@ namespace Layout {
 
 WTF_MAKE_ISO_ALLOCATED_IMPL(FloatingContext);
 
-FloatingContext::FloatingContext(FloatingState&)
+FloatingContext::FloatingContext(FloatingState& floatingState)
+    : m_floatingState(floatingState)
 {
 }
 
-void FloatingContext::computePosition(const Box&, Display::Box&)
+Position FloatingContext::computePosition(const Box& layoutBox)
 {
+    auto& layoutContext = m_floatingState.layoutContext();
+    // 1. No floating box on the context yet -> align it with the containing block's left/right edge.
+    if (m_floatingState.isEmpty()) {
+        // Push the box to the left/right edge.
+        auto* containingBlock = layoutBox.containingBlock();
+        auto* displayBox = layoutContext.displayBoxForLayoutBox(*containingBlock);
+
+        if (layoutBox.isLeftFloatingPositioned())
+            return { displayBox->contentBoxLeft(), displayBox->contentBoxTop() };
+
+        auto boxWidth = layoutContext.displayBoxForLayoutBox(layoutBox)->width();
+        return { displayBox->contentBoxRight() - boxWidth, displayBox->contentBoxTop() };
+    }
+
+    ASSERT_NOT_IMPLEMENTED_YET();
+    return { };
 }
 
 }
index 41c31f1..e471f4a 100644 (file)
@@ -27,7 +27,8 @@
 
 #if ENABLE(LAYOUT_FORMATTING_CONTEXT)
 
-#include "LayoutUnit.h"
+#include "FloatingState.h"
+#include "LayoutUnits.h"
 #include <wtf/IsoMalloc.h>
 
 namespace WebCore {
@@ -39,7 +40,7 @@ class Box;
 namespace Layout {
 
 class Box;
-class FloatingState;
+class LayoutContext;
 
 // FloatingContext is responsible for adjusting the position of a box in the current formatting context
 // by taking the floating boxes into account.
@@ -48,10 +49,14 @@ class FloatingContext {
 public:
     FloatingContext(FloatingState&);
 
-    void computePosition(const Box&, Display::Box&);
-    LayoutUnit left(LayoutUnit verticalPosition);
-    LayoutUnit right(LayoutUnit verticalPosition);
-    LayoutUnit bottom();
+    FloatingState& floatingState() const { return m_floatingState; }
+
+    Position computePosition(const Box&);
+
+private:
+    LayoutContext& layoutContext() const { return m_floatingState.layoutContext(); }
+
+    FloatingState& m_floatingState;
 };
 
 }
index 50519a9..3fdcac1 100644 (file)
@@ -28,6 +28,8 @@
 
 #if ENABLE(LAYOUT_FORMATTING_CONTEXT)
 
+#include "LayoutBox.h"
+#include "LayoutContext.h"
 #include <wtf/IsoMallocInlines.h>
 
 namespace WebCore {
@@ -35,10 +37,29 @@ namespace Layout {
 
 WTF_MAKE_ISO_ALLOCATED_IMPL(FloatingState);
 
-FloatingState::FloatingState()
+FloatingState::FloatingState(LayoutContext& layoutContext)
+    : m_layoutContext(layoutContext)
 {
 }
 
+void FloatingState::append(const Box& layoutBox)
+{
+    // Floating state should hold boxes with computed position/size.
+    ASSERT(m_layoutContext.displayBoxForLayoutBox(layoutBox));
+
+    if (layoutBox.isLeftFloatingPositioned()) {
+        m_leftFloatings.append(makeWeakPtr(const_cast<Box&>(layoutBox)));
+        return;
+    }
+
+    if (layoutBox.isRightFloatingPositioned()) {
+        m_rightFloatings.append(makeWeakPtr(const_cast<Box&>(layoutBox)));
+        return;
+    }
+
+    ASSERT_NOT_REACHED();
+}
+
 }
 }
 #endif
index 6fe7e22..9369985 100644 (file)
 
 #include <wtf/IsoMalloc.h>
 #include <wtf/Ref.h>
+#include <wtf/WeakPtr.h>
 
 namespace WebCore {
 
 namespace Layout {
 
+class Box;
 class FormattingState;
+class LayoutContext;
 
 // FloatingState holds the floating boxes per formatting context.
 class FloatingState : public RefCounted<FloatingState> {
     WTF_MAKE_ISO_ALLOCATED(FloatingState);
 public:
-    static Ref<FloatingState> create() { return adoptRef(*new FloatingState()); }
+    static Ref<FloatingState> create(LayoutContext& layoutContext) { return adoptRef(*new FloatingState(layoutContext)); }
+
+    void append(const Box& layoutBox);
+
+    bool isEmpty() const { return m_leftFloatings.isEmpty() && m_rightFloatings.isEmpty(); }
 
 private:
-    FloatingState();
+    friend class FloatingContext;
+    FloatingState(LayoutContext&);
+
+    LayoutContext& layoutContext() const { return m_layoutContext; }
+
+    LayoutContext& m_layoutContext;
+
+    using FloatingList = Vector<WeakPtr<Box>>;
+    FloatingList m_leftFloatings;
+    FloatingList m_rightFloatings;
 };
 
 }
index 59c5538..880b452 100644 (file)
@@ -28,6 +28,7 @@
 #if ENABLE(LAYOUT_FORMATTING_CONTEXT)
 
 #include "FloatingState.h"
+#include "FormattingContext.h"
 #include "LayoutBox.h"
 #include "LayoutContext.h"
 #include "LayoutUnit.h"
index 8ca9c9b..482a47f 100644 (file)
@@ -127,7 +127,7 @@ FormattingState& LayoutContext::establishedFormattingState(const Box& formatting
             // should not interfere with the content inside.
             // <div style="float: left"></div><div style="overflow: hidden"> <- is a non-intrusive float, because overflow: hidden triggers new block formatting context.</div>
             if (formattingRoot.establishesBlockFormattingContext())
-                return std::make_unique<InlineFormattingState>(FloatingState::create(), *this);
+                return std::make_unique<InlineFormattingState>(FloatingState::create(*this), *this);
 
             // Otherwise, the formatting context inherits the floats from the parent formatting context.
             // Find the formatting state in which this formatting root lives, not the one it creates and use its floating state.
@@ -139,7 +139,7 @@ FormattingState& LayoutContext::establishedFormattingState(const Box& formatting
         return *m_formattingStates.ensure(&formattingRoot, [&] {
 
             // Block formatting context always establishes a new floating state.
-            return std::make_unique<BlockFormattingState>(FloatingState::create(), *this);
+            return std::make_unique<BlockFormattingState>(FloatingState::create(*this), *this);
         }).iterator->value;
     }
     CRASH();
index dc4cdb0..08b4c1f 100644 (file)
@@ -28,6 +28,7 @@
 #if ENABLE(LAYOUT_FORMATTING_CONTEXT)
 
 #include "FormattingContext.h"
+#include <wtf/HashMap.h>
 #include <wtf/HashSet.h>
 #include <wtf/IsoMalloc.h>
 #include <wtf/OptionSet.h>
index 1933224..faf1e89 100644 (file)
@@ -79,7 +79,7 @@ void BlockFormattingContext::layout(LayoutContext& layoutContext, FormattingStat
             auto& displayBox = layoutPair.displayBox;
 
             if (layoutBox.establishesFormattingContext()) {
-                layoutFormattingContextRoot(layoutContext, formattingState, layoutBox, displayBox);
+                layoutFormattingContextRoot(layoutContext, floatingContext, formattingState, layoutBox, displayBox);
                 layoutQueue.removeLast();
                 // Since this box is a formatting context root, it takes care of its entire subtree.
                 // Continue with next sibling if exists.
@@ -94,6 +94,8 @@ void BlockFormattingContext::layout(LayoutContext& layoutContext, FormattingStat
             computeStaticPosition(layoutContext, layoutBox, displayBox);
             computeBorderAndPadding(layoutContext, layoutBox, displayBox);
             computeWidthAndMargin(layoutContext, layoutBox, displayBox);
+            if (layoutBox.isFloatingPositioned())
+                computeFloatingPosition(floatingContext, layoutBox, displayBox);
             if (!is<Container>(layoutBox) || !downcast<Container>(layoutBox).hasInFlowOrFloatingChild())
                 break;
             auto& firstChild = *downcast<Container>(layoutBox).firstInFlowOrFloatingChild();
@@ -112,8 +114,6 @@ void BlockFormattingContext::layout(LayoutContext& layoutContext, FormattingStat
             ASSERT(!layoutBox.establishesFormattingContext());
 
             computeHeightAndMargin(layoutContext, layoutBox, displayBox);
-            // Adjust position now that we have all the previous floats placed in this context -if needed.
-            floatingContext.computePosition(layoutBox, displayBox);
             if (!is<Container>(layoutBox))
                 continue;
             auto& container = downcast<Container>(layoutBox);
@@ -131,20 +131,21 @@ void BlockFormattingContext::layout(LayoutContext& layoutContext, FormattingStat
     LOG_WITH_STREAM(FormattingContextLayout, stream << "[End] -> block formatting context -> layout context(" << &layoutContext << ") formatting root(" << &root() << ")");
 }
 
-void BlockFormattingContext::layoutFormattingContextRoot(LayoutContext& layoutContext, FormattingState& formattingState, const Box& layoutBox, Display::Box& displayBox) const
+void BlockFormattingContext::layoutFormattingContextRoot(LayoutContext& layoutContext, FloatingContext& floatingContext, FormattingState&, const Box& layoutBox, Display::Box& displayBox) const
 {
     // Start laying out this formatting root in the formatting contenxt it lives in.
     LOG_WITH_STREAM(FormattingContextLayout, stream << "[Compute] -> [Position][Border][Padding][Width][Margin] -> for layoutBox(" << &layoutBox << ")");
     computeStaticPosition(layoutContext, layoutBox, displayBox);
     computeBorderAndPadding(layoutContext, layoutBox, displayBox);
     computeWidthAndMargin(layoutContext, layoutBox, displayBox);
+    if (layoutBox.isFloatingPositioned())
+        computeFloatingPosition(floatingContext, layoutBox, displayBox);
 
     // Swich over to the new formatting context (the one that the root creates).
     auto formattingContext = layoutContext.formattingContext(layoutBox);
     formattingContext->layout(layoutContext, layoutContext.establishedFormattingState(layoutBox));
 
     // Come back and finalize the root's geometry.
-    FloatingContext(formattingState.floatingState()).computePosition(layoutBox, displayBox);
     LOG_WITH_STREAM(FormattingContextLayout, stream << "[Compute] -> [Height][Margin] -> for layoutBox(" << &layoutBox << ")");
     computeHeightAndMargin(layoutContext, layoutBox, displayBox);
     // Now that we computed the root's height, we can go back and layout the out-of-flow descedants (if any).
@@ -156,6 +157,13 @@ void BlockFormattingContext::computeStaticPosition(LayoutContext& layoutContext,
     displayBox.setTopLeft(Geometry::staticPosition(layoutContext, layoutBox));
 }
 
+void BlockFormattingContext::computeFloatingPosition(FloatingContext& floatingContext, const Box& layoutBox, Display::Box& displayBox) const
+{
+    ASSERT(layoutBox.isFloatingPositioned());
+    displayBox.setTopLeft(floatingContext.computePosition(layoutBox));
+    floatingContext.floatingState().append(layoutBox);
+}
+
 void BlockFormattingContext::computeInFlowPositionedPosition(LayoutContext& layoutContext, const Box& layoutBox, Display::Box& displayBox) const
 {
     displayBox.setTopLeft(Geometry::inFlowPositionedPosition(layoutContext, layoutBox));
index 7564f38..cf5a6ea 100644 (file)
@@ -38,6 +38,7 @@ namespace Layout {
 
 class BlockFormattingState;
 class Box;
+class FloatingContext;
 
 // This class implements the layout logic for block formatting contexts.
 // https://www.w3.org/TR/CSS22/visuren.html#block-formatting
@@ -49,12 +50,13 @@ public:
     void layout(LayoutContext&, FormattingState&) const override;
 
 private:
-    void layoutFormattingContextRoot(LayoutContext&, FormattingState&, const Box&, Display::Box&) const;
+    void layoutFormattingContextRoot(LayoutContext&, FloatingContext&, FormattingState&, const Box&, Display::Box&) const;
 
     void computeWidthAndMargin(LayoutContext&, const Box&, Display::Box&) const;
     void computeHeightAndMargin(LayoutContext&, const Box&, Display::Box&) const;
 
     void computeStaticPosition(LayoutContext&, const Box&, Display::Box&) const override;
+    void computeFloatingPosition(FloatingContext&, const Box&, Display::Box&) const;
     void computeInFlowPositionedPosition(LayoutContext&, const Box&, Display::Box&) const override;
     void computeInFlowWidthAndMargin(LayoutContext&, const Box&, Display::Box&) const;
     void computeInFlowHeightAndMargin(LayoutContext&, const Box&, Display::Box&) const;
index 7e151a1..a9fa192 100644 (file)
@@ -42,6 +42,8 @@ WTF_MAKE_ISO_ALLOCATED_IMPL(BlockInvalidation);
 
 static bool invalidationStopsAtFormattingContextBoundary(const Container& formattingContextRoot, const Box&, StyleDiff)
 {
+    UNUSED_PARAM(formattingContextRoot);
+
     ASSERT(formattingContextRoot.establishesFormattingContext());
     return true;
 }
index df765e5..13a89d4 100644 (file)
@@ -100,6 +100,16 @@ bool Box::isFloatingPositioned() const
     return m_style.floating() != Float::No;
 }
 
+bool Box::isLeftFloatingPositioned() const
+{
+    return m_style.floating() == Float::Left;
+}
+
+bool Box::isRightFloatingPositioned() const
+{
+    return m_style.floating() == Float::Right;
+}
+
 const Container* Box::containingBlock() const
 {
     // The containing block in which the root element lives is a rectangle called the initial containing block.
index 893729e..f83a73a 100644 (file)
@@ -60,6 +60,8 @@ public:
     bool isAbsolutelyPositioned() const;
     bool isFixedPositioned() const;
     bool isFloatingPositioned() const;
+    bool isLeftFloatingPositioned() const;
+    bool isRightFloatingPositioned() const;
 
     bool isFloatingOrOutOfFlowPositioned() const { return isFloatingPositioned() || isOutOfFlowPositioned(); }