[LFC][IFC] Add support for inline-block elements.
authorzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 1 Nov 2018 14:20:48 +0000 (14:20 +0000)
committerzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Thu, 1 Nov 2018 14:20:48 +0000 (14:20 +0000)
https://bugs.webkit.org/show_bug.cgi?id=191143

Reviewed by Antti Koivisto.

Source/WebCore:

This patch add support for laying out non-shrink-to-width inline-block elements.

Test: fast/inline/simple-inline-block.html

* layout/FormattingContext.h:
(WebCore::Layout::FormattingContext::Geometry::floatingNonReplacedWidthAndMargin):
* layout/FormattingContextGeometry.cpp:
(WebCore::Layout::contentHeightForFormattingContextRoot):
(WebCore::Layout::FormattingContext::Geometry::shrinkToFitWidth):
* layout/inlineformatting/InlineFormattingContext.cpp:
(WebCore::Layout::InlineFormattingContext::layoutFormattingContextRoot const):
* layout/inlineformatting/InlineFormattingContextGeometry.cpp:
(WebCore::Layout::InlineFormattingContext::Geometry::inlineBlockWidthAndMargin):
(WebCore::Layout::InlineFormattingContext::Geometry::inlineBlockHeightAndMargin):
* layout/layouttree/LayoutInlineContainer.cpp:
(WebCore::Layout::InlineContainer::establishesInlineFormattingContext const):
* layout/layouttree/LayoutInlineContainer.h:
* layout/layouttree/LayoutTreeBuilder.cpp:
(WebCore::Layout::TreeBuilder::createSubTree):

Tools:

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

LayoutTests:

* fast/inline/simple-inline-block-expected.txt: Added.
* fast/inline/simple-inline-block.html: Added.
* platform/ios/TestExpectations:

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

14 files changed:
LayoutTests/ChangeLog
LayoutTests/fast/inline/simple-inline-block-expected.txt [new file with mode: 0644]
LayoutTests/fast/inline/simple-inline-block.html [new file with mode: 0644]
LayoutTests/platform/ios/TestExpectations
Source/WebCore/ChangeLog
Source/WebCore/layout/FormattingContext.h
Source/WebCore/layout/FormattingContextGeometry.cpp
Source/WebCore/layout/inlineformatting/InlineFormattingContext.cpp
Source/WebCore/layout/inlineformatting/InlineFormattingContextGeometry.cpp
Source/WebCore/layout/layouttree/LayoutInlineContainer.cpp
Source/WebCore/layout/layouttree/LayoutInlineContainer.h
Source/WebCore/layout/layouttree/LayoutTreeBuilder.cpp
Tools/ChangeLog
Tools/LayoutReloaded/misc/LFC-passing-tests.txt

index 092e4bb..67f142c 100644 (file)
@@ -1,3 +1,14 @@
+2018-10-31  Zalan Bujtas  <zalan@apple.com>
+
+        [LFC][IFC] Add support for inline-block elements.
+        https://bugs.webkit.org/show_bug.cgi?id=191143
+
+        Reviewed by Antti Koivisto.
+
+        * fast/inline/simple-inline-block-expected.txt: Added.
+        * fast/inline/simple-inline-block.html: Added.
+        * platform/ios/TestExpectations:
+
 2018-11-01  YUHAN WU  <yuhan_wu@apple.com>
 
         MediaRecorder should fire dataavailable event when all tracks are ended and stop() is called
diff --git a/LayoutTests/fast/inline/simple-inline-block-expected.txt b/LayoutTests/fast/inline/simple-inline-block-expected.txt
new file mode 100644 (file)
index 0000000..f70737a
--- /dev/null
@@ -0,0 +1,13 @@
+layer at (0,0) size 800x600
+  RenderView at (0,0) size 800x600
+layer at (0,0) size 800x600
+  RenderBlock {HTML} at (0,0) size 800x600
+    RenderBody {BODY} at (8,8) size 784x584
+      RenderBlock {DIV} at (0,0) size 300x102
+        RenderText {#text} at (0,1) size 90x18
+          text run at (0,1) width 90: "first line with "
+        RenderBlock {DIV} at (89,0) size 103x102 [border: (1px solid #FF0000)]
+          RenderText {#text} at (1,1) size 76x18
+            text run at (1,1) width 76: "inline block"
+        RenderText {#text} at (191,1) size 52x18
+          text run at (191,1) width 52: " content"
diff --git a/LayoutTests/fast/inline/simple-inline-block.html b/LayoutTests/fast/inline/simple-inline-block.html
new file mode 100644 (file)
index 0000000..15afad6
--- /dev/null
@@ -0,0 +1,15 @@
+<style>
+div {
+       width: 300px;
+}
+
+#inline-b {
+       border: 1px solid red;
+       display: inline-block;
+       height: 100px;
+       width: 100px;
+}
+
+</style>
+
+<div>first line with <div id=inline-b>inline block</div> content</div>
index b3448b0..31d612e 100644 (file)
@@ -3112,6 +3112,7 @@ fast/block/basic/inline-content-with-floating-images2.html [ Failure ]
 fast/inline/simple-intruding-float1.html [ Failure ]
 fast/inline/simple-intruding-floats2.html [ Failure ]
 fast/inline/simple-intruding-floats3.html [ Failure ]
+fast/inline/simple-inline-block.html [ Failure ]
 
 # Datalist
 webkit.org/b/186714 fast/forms/datalist/datalist-textinput-keydown.html [ Skip ]
index 36553c6..51da8cb 100644 (file)
@@ -1,3 +1,30 @@
+2018-10-31  Zalan Bujtas  <zalan@apple.com>
+
+        [LFC][IFC] Add support for inline-block elements.
+        https://bugs.webkit.org/show_bug.cgi?id=191143
+
+        Reviewed by Antti Koivisto.
+
+        This patch add support for laying out non-shrink-to-width inline-block elements.
+
+        Test: fast/inline/simple-inline-block.html
+
+        * layout/FormattingContext.h:
+        (WebCore::Layout::FormattingContext::Geometry::floatingNonReplacedWidthAndMargin):
+        * layout/FormattingContextGeometry.cpp:
+        (WebCore::Layout::contentHeightForFormattingContextRoot):
+        (WebCore::Layout::FormattingContext::Geometry::shrinkToFitWidth):
+        * layout/inlineformatting/InlineFormattingContext.cpp:
+        (WebCore::Layout::InlineFormattingContext::layoutFormattingContextRoot const):
+        * layout/inlineformatting/InlineFormattingContextGeometry.cpp:
+        (WebCore::Layout::InlineFormattingContext::Geometry::inlineBlockWidthAndMargin):
+        (WebCore::Layout::InlineFormattingContext::Geometry::inlineBlockHeightAndMargin):
+        * layout/layouttree/LayoutInlineContainer.cpp:
+        (WebCore::Layout::InlineContainer::establishesInlineFormattingContext const):
+        * layout/layouttree/LayoutInlineContainer.h:
+        * layout/layouttree/LayoutTreeBuilder.cpp:
+        (WebCore::Layout::TreeBuilder::createSubTree):
+
 2018-11-01  Claudio Saavedra  <csaavedra@igalia.com>
 
         Fix build with VIDEO and WEB_AUDIO disabled
index a23477f..58948af 100644 (file)
@@ -94,6 +94,7 @@ protected:
             std::optional<LayoutUnit> precomputedMarginLeft = { }, std::optional<LayoutUnit> precomputedMarginRight = { });
 
         static HeightAndMargin complicatedCases(const LayoutState&, const Box&, std::optional<LayoutUnit> usedHeight = { });
+        static LayoutUnit shrinkToFitWidth(const LayoutState&, const FormattingContext&, const Box&);
 
         static Edges computedBorder(const LayoutState&, const Box&);
         static std::optional<Edges> computedPadding(const LayoutState&, const Box&);
@@ -118,8 +119,6 @@ protected:
         static WidthAndMargin floatingReplacedWidthAndMargin(const LayoutState&, const Box&, std::optional<LayoutUnit> usedWidth = { });
 
         static WidthAndMargin floatingNonReplacedWidthAndMargin(LayoutState&, const FormattingContext&, const Box&, std::optional<LayoutUnit> usedWidth = { });
-
-        static LayoutUnit shrinkToFitWidth(LayoutState&, const FormattingContext&, const Box&);
     };
 
 private:
index 4cf7dbd..a92b992 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "FloatingState.h"
 #include "FormattingState.h"
+#include "InlineFormattingState.h"
 
 namespace WebCore {
 namespace Layout {
@@ -50,14 +51,22 @@ static LayoutUnit contentHeightForFormattingContextRoot(const LayoutState& layou
     if (!is<Container>(layoutBox) || !downcast<Container>(layoutBox).hasInFlowOrFloatingChild())
         return 0;
 
+    LayoutUnit top;
+    LayoutUnit bottom;
     auto& formattingRootContainer = downcast<Container>(layoutBox);
-    if (formattingRootContainer.establishesInlineFormattingContext())
-        return 0;
-
-    auto& firstDisplayBox = layoutState.displayBoxForLayoutBox(*formattingRootContainer.firstInFlowChild());
-    auto& lastDisplayBox = layoutState.displayBoxForLayoutBox(*formattingRootContainer.lastInFlowChild());
-    auto top = firstDisplayBox.rectWithMargin().top();
-    auto bottom = lastDisplayBox.rectWithMargin().bottom();
+    if (formattingRootContainer.establishesInlineFormattingContext()) {
+        // This is temp and will be replaced by the correct display box once inline runs move over to the display tree.
+        auto& inlineRuns = downcast<InlineFormattingState>(layoutState.establishedFormattingState(layoutBox)).inlineRuns();
+        if (!inlineRuns.isEmpty()) {
+            top = inlineRuns[0].logicalTop();
+            bottom =  inlineRuns.last().logicalBottom();
+        }
+    } else if (formattingRootContainer.establishesBlockFormattingContext() || layoutBox.isDocumentBox()) {
+        auto& firstDisplayBox = layoutState.displayBoxForLayoutBox(*formattingRootContainer.firstInFlowChild());
+        auto& lastDisplayBox = layoutState.displayBoxForLayoutBox(*formattingRootContainer.lastInFlowChild());
+        top = firstDisplayBox.rectWithMargin().top();
+        bottom = lastDisplayBox.rectWithMargin().bottom();
+    }
 
     auto* formattingContextRoot = &layoutBox;
     // TODO: The document renderer is not a formatting context root by default at all. Need to find out what it is.
@@ -199,7 +208,7 @@ static LayoutUnit staticHorizontalPositionForOutOfFlowPositioned(const LayoutSta
     return left;
 }
 
-LayoutUnit FormattingContext::Geometry::shrinkToFitWidth(LayoutState& layoutState, const FormattingContext& formattingContext, const Box& layoutBox)
+LayoutUnit FormattingContext::Geometry::shrinkToFitWidth(const LayoutState& layoutState, const FormattingContext& formattingContext, const Box& layoutBox)
 {
     LOG_WITH_STREAM(FormattingContextLayout, stream << "[Width] -> shrink to fit -> unsupported -> width(" << LayoutUnit { } << "px) layoutBox: " << &layoutBox << ")");
     // Calculation of the shrink-to-fit width is similar to calculating the width of a table cell using the automatic table layout algorithm.
index ed02c36..6056263 100644 (file)
@@ -241,11 +241,12 @@ void InlineFormattingContext::layoutFormattingContextRoot(const Box& layoutBox)
         displayBox.setVerticalMargin(heightAndMargin.collapsedMargin.value_or(heightAndMargin.margin));
     };
 
+    layoutState.createFormattingStateForFormattingRootIfNeeded(layoutBox);
     computeBorderAndPadding(layoutBox);
     computeWidthAndMargin();
 
     // Swich over to the new formatting context (the one that the root creates).
-    layoutState.createFormattingStateForFormattingRootIfNeeded(layoutBox).formattingContext(layoutBox)->layout();
+    layoutState.establishedFormattingState(layoutBox).formattingContext(layoutBox)->layout();
 
     // Come back and finalize the root's height and margin.
     computeHeightAndMargin();
index d385f3d..dbd9faf 100644 (file)
 #if ENABLE(LAYOUT_FORMATTING_CONTEXT)
 
 #include "FormattingContext.h"
+#include "InlineFormattingState.h"
+#include "LayoutBox.h"
+#include "LayoutContainer.h"
+#include "LayoutFormattingState.h"
 
 namespace WebCore {
 namespace Layout {
 
-WidthAndMargin InlineFormattingContext::Geometry::inlineBlockWidthAndMargin(const LayoutState&, const Box&)
+WidthAndMargin InlineFormattingContext::Geometry::inlineBlockWidthAndMargin(const LayoutState& layoutState, const Box& formattingContextRoot)
 {
-    return { };
+    ASSERT(formattingContextRoot.isInFlow());
+
+    // 10.3.10 'Inline-block', replaced elements in normal flow
+
+    // Exactly as inline replaced elements.
+    if (formattingContextRoot.replaced())
+        return inlineReplacedWidthAndMargin(layoutState, formattingContextRoot);
+
+    // 10.3.9 'Inline-block', non-replaced elements in normal flow
+
+    // If 'width' is 'auto', the used value is the shrink-to-fit width as for floating elements.
+    // A computed value of 'auto' for 'margin-left' or 'margin-right' becomes a used value of '0'.
+    auto& containingBlock = *formattingContextRoot.containingBlock();
+    auto containingBlockWidth = layoutState.displayBoxForLayoutBox(containingBlock).contentBoxWidth();
+    // #1
+    auto width = computedValueIfNotAuto(formattingContextRoot.style().logicalWidth(), containingBlockWidth);
+    if (!width) {
+        auto formattingContext = layoutState.establishedFormattingState(formattingContextRoot).formattingContext(formattingContextRoot);
+        width = shrinkToFitWidth(layoutState, *formattingContext, formattingContextRoot);
+    }
+
+    // #2
+    auto margin = computedNonCollapsedHorizontalMarginValue(layoutState, formattingContextRoot);
+
+    return WidthAndMargin { *width, margin, margin };
 }
 
-HeightAndMargin InlineFormattingContext::Geometry::inlineBlockHeightAndMargin(const LayoutState&, const Box&)
+HeightAndMargin InlineFormattingContext::Geometry::inlineBlockHeightAndMargin(const LayoutState& layoutState, const Box& layoutBox)
 {
-    return { };
+    ASSERT(layoutBox.isInFlow());
+
+    // 10.6.2 Inline replaced elements, block-level replaced elements in normal flow, 'inline-block' replaced elements in normal flow and floating replaced elements
+    if (layoutBox.replaced())
+        return inlineReplacedHeightAndMargin(layoutState, layoutBox);
+
+    // 10.6.6 Complicated cases
+    // - 'Inline-block', non-replaced elements.
+    return complicatedCases(layoutState, layoutBox);
 }
 
 }
index 980d9a9..5ed09f3 100644 (file)
@@ -41,6 +41,19 @@ InlineContainer::InlineContainer(std::optional<ElementAttributes> attributes, Re
 {
 }
 
+bool InlineContainer::establishesInlineFormattingContext() const
+{
+    if (!isInlineBlockBox())
+        return false;
+
+    // 9.4.2 Inline formatting contexts
+    // An inline formatting context is established by a block container box that contains no block-level boxes.
+    if (auto* firstInFlowChild = this->firstInFlowChild())
+        return firstInFlowChild->isInlineLevelBox();
+
+    return false;
+}
+
 }
 }
 
index 5ef6c53..12333ac 100644 (file)
@@ -40,6 +40,8 @@ class InlineContainer : public Container {
     WTF_MAKE_ISO_ALLOCATED(InlineContainer);
 public:
     InlineContainer(std::optional<ElementAttributes>, RenderStyle&&, BaseTypeFlags = InlineContainerFlag);
+
+    bool establishesInlineFormattingContext() const final;
 };
 
 }
index 08fb770..c3ccf53 100644 (file)
@@ -100,6 +100,8 @@ void TreeBuilder::createSubTree(const RenderElement& rootRenderer, Container& ro
                 box = std::make_unique<BlockContainer>(elementAttributes(renderer), RenderStyle::clone(renderer.style()));
             else if (display == DisplayType::Inline)
                 box = std::make_unique<InlineContainer>(elementAttributes(renderer), RenderStyle::clone(renderer.style()));
+            else if (display == DisplayType::InlineBlock)
+                box = std::make_unique<InlineContainer>(elementAttributes(renderer), RenderStyle::clone(renderer.style()));
             else {
                 ASSERT_NOT_IMPLEMENTED_YET();
                 continue;
index eab07cd..f01f84c 100644 (file)
@@ -1,3 +1,12 @@
+2018-10-31  Zalan Bujtas  <zalan@apple.com>
+
+        [LFC][IFC] Add support for inline-block elements.
+        https://bugs.webkit.org/show_bug.cgi?id=191143
+
+        Reviewed by Antti Koivisto.
+
+        * LayoutReloaded/misc/LFC-passing-tests.txt:
+
 2018-11-01  Claudio Saavedra  <csaavedra@igalia.com>
 
         [WPE] Add missing libsoup patch to jhbuild
index 9a9e209..bcf068b 100644 (file)
@@ -67,3 +67,4 @@ fast/block/basic/inline-content-with-floating-images2.html
 fast/inline/simple-intruding-float1.html
 fast/inline/simple-intruding-floats2.html
 fast/inline/simple-intruding-floats3.html
+fast/inline/simple-inline-block.html