[LFC] Merge top, bottom, height and vertical margin computation for out-of-flow non...
authorzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 11 Jun 2018 14:27:50 +0000 (14:27 +0000)
committerzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 11 Jun 2018 14:27:50 +0000 (14:27 +0000)
https://bugs.webkit.org/show_bug.cgi?id=186476

Reviewed by Antti Koivisto.

Implement https://www.w3.org/TR/CSS22/visudet.html#abs-non-replaced-height
(10.6.4 Absolutely positioned, non-replaced elements)

* layout/FormattingContext.cpp:
(WebCore::Layout::FormattingContext::computeOutOfFlowVerticalGeometry const):
(WebCore::Layout::FormattingContext::layoutOutOfFlowDescendants const):
(WebCore::Layout::FormattingContext::computeOutOfFlowHeight const): Deleted.
* layout/FormattingContext.h:
* layout/FormattingContextGeometry.cpp:
(WebCore::Layout::computedValueIfNotAuto):
(WebCore::Layout::FormattingContext::Geometry::outOfFlowNonReplacedVerticalGeometry):
(WebCore::Layout::FormattingContext::Geometry::outOfFlowReplacedVerticalGeometry):
(WebCore::Layout::FormattingContext::Geometry::outOfFlowVerticalGeometry):
(WebCore::Layout::FormattingContext::Geometry::outOfFlowNonReplacedHeightAndMargin): Deleted.
(WebCore::Layout::FormattingContext::Geometry::outOfFlowReplacedHeightAndMargin): Deleted.
(WebCore::Layout::FormattingContext::Geometry::outOfFlowHeightAndMargin): Deleted.

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

Source/WebCore/ChangeLog
Source/WebCore/layout/FormattingContext.cpp
Source/WebCore/layout/FormattingContext.h
Source/WebCore/layout/FormattingContextGeometry.cpp

index b789dad..2b81791 100644 (file)
@@ -1,3 +1,27 @@
+2018-06-10  Zalan Bujtas  <zalan@apple.com>
+
+        [LFC] Merge top, bottom, height and vertical margin computation for out-of-flow non-replaced elements
+        https://bugs.webkit.org/show_bug.cgi?id=186476
+
+        Reviewed by Antti Koivisto.
+
+        Implement https://www.w3.org/TR/CSS22/visudet.html#abs-non-replaced-height
+        (10.6.4 Absolutely positioned, non-replaced elements)
+
+        * layout/FormattingContext.cpp:
+        (WebCore::Layout::FormattingContext::computeOutOfFlowVerticalGeometry const):
+        (WebCore::Layout::FormattingContext::layoutOutOfFlowDescendants const):
+        (WebCore::Layout::FormattingContext::computeOutOfFlowHeight const): Deleted.
+        * layout/FormattingContext.h:
+        * layout/FormattingContextGeometry.cpp:
+        (WebCore::Layout::computedValueIfNotAuto):
+        (WebCore::Layout::FormattingContext::Geometry::outOfFlowNonReplacedVerticalGeometry):
+        (WebCore::Layout::FormattingContext::Geometry::outOfFlowReplacedVerticalGeometry):
+        (WebCore::Layout::FormattingContext::Geometry::outOfFlowVerticalGeometry):
+        (WebCore::Layout::FormattingContext::Geometry::outOfFlowNonReplacedHeightAndMargin): Deleted.
+        (WebCore::Layout::FormattingContext::Geometry::outOfFlowReplacedHeightAndMargin): Deleted.
+        (WebCore::Layout::FormattingContext::Geometry::outOfFlowHeightAndMargin): Deleted.
+
 2018-06-10  Carlos Garcia Campos  <cgarcia@igalia.com>
 
         [GTK][WPE] Add API run run javascript from a WebKitWebView in an isolated world
index 51c2623..92c39d8 100644 (file)
@@ -75,11 +75,13 @@ void FormattingContext::computeOutOfFlowWidthAndMargin(LayoutContext& layoutCont
     displayBox.setHorizontalMargin(widthAndMargin.margin);
 }
 
-void FormattingContext::computeOutOfFlowHeight(LayoutContext& layoutContext, const Box& layoutBox, Display::Box& displayBox) const
+void FormattingContext::computeOutOfFlowVerticalGeometry(LayoutContext& layoutContext, const Box& layoutBox, Display::Box& displayBox) const
 {
-    auto heightAndMargin = Geometry::outOfFlowHeightAndMargin(layoutContext, layoutBox);
-    displayBox.setHeight(heightAndMargin.height);
-    displayBox.setVerticalMargin(heightAndMargin.margin);
+    auto verticalGeometry = Geometry::outOfFlowVerticalGeometry(layoutContext, layoutBox);
+    displayBox.setTop(verticalGeometry.top);
+    displayBox.setHeight(verticalGeometry.height);
+    ASSERT(verticalGeometry.top + verticalGeometry.height == verticalGeometry.bottom);
+    displayBox.setVerticalMargin(verticalGeometry.margin);
 }
 
 void FormattingContext::computeBorderAndPadding(LayoutContext& layoutContext, const Box& layoutBox, Display::Box& displayBox) const
@@ -121,7 +123,7 @@ void FormattingContext::layoutOutOfFlowDescendants(LayoutContext& layoutContext)
         auto formattingContext = layoutContext.formattingContext(layoutBox);
         formattingContext->layout(layoutContext, layoutContext.establishedFormattingState(layoutBox, *formattingContext));
 
-        computeOutOfFlowHeight(layoutContext, layoutBox, displayBox);
+        computeOutOfFlowVerticalGeometry(layoutContext, layoutBox, displayBox);
         computeOutOfFlowPosition(layoutContext, layoutBox, displayBox);
     }
 }
index 9d230f2..3c6acf4 100644 (file)
@@ -91,7 +91,14 @@ protected:
             Display::Box::VerticalEdges margin;
         };
 
-        static HeightAndMargin outOfFlowHeightAndMargin(LayoutContext&, const Box&);
+        struct VerticalGeometry {
+            LayoutUnit top;
+            LayoutUnit bottom;
+            LayoutUnit height;
+            Display::Box::VerticalEdges margin;
+        };
+
+        static VerticalGeometry outOfFlowVerticalGeometry(LayoutContext&, const Box&);
         static WidthAndMargin outOfFlowWidthAndMargin(LayoutContext&, const Box&);
 
         static HeightAndMargin floatingHeightAndMargin(LayoutContext&, const Box&);
@@ -110,10 +117,10 @@ protected:
         static Display::Box::VerticalEdges computedNonCollapsedVerticalMarginValue(const LayoutContext&, const Box&);
 
     private:
-        static HeightAndMargin outOfFlowReplacedHeightAndMargin(LayoutContext&, const Box&);
+        static VerticalGeometry outOfFlowReplacedVerticalGeometry(LayoutContext&, const Box&);
         static WidthAndMargin outOfFlowReplacedWidthAndMargin(LayoutContext&, const Box&);
 
-        static HeightAndMargin outOfFlowNonReplacedHeightAndMargin(LayoutContext&, const Box&);
+        static VerticalGeometry outOfFlowNonReplacedVerticalGeometry(LayoutContext&, const Box&);
         static WidthAndMargin outOfFlowNonReplacedWidthAndMargin(LayoutContext&, const Box&);
 
         static HeightAndMargin floatingReplacedHeightAndMargin(LayoutContext&, const Box&);
@@ -125,7 +132,7 @@ protected:
 
 private:
     void computeOutOfFlowPosition(LayoutContext&, const Box&, Display::Box&) const;
-    void computeOutOfFlowHeight(LayoutContext&, const Box&, Display::Box&) const;
+    void computeOutOfFlowVerticalGeometry(LayoutContext&, const Box&, Display::Box&) const;
     void computeOutOfFlowWidthAndMargin(LayoutContext&, const Box&, Display::Box&) const;
 
     WeakPtr<Box> m_root;
index a40c43d..0b66168 100644 (file)
@@ -64,7 +64,14 @@ static LayoutUnit shrinkToFitWidth(LayoutContext&, const Box&)
     return { };
 }
 
-FormattingContext::Geometry::HeightAndMargin FormattingContext::Geometry::outOfFlowNonReplacedHeightAndMargin(LayoutContext& layoutContext, const Box& layoutBox)
+static std::optional<LayoutUnit> computedValueIfNotAuto(const Length& geometryProperty, LayoutUnit containingBlockWidth)
+{
+    if (geometryProperty.isAuto())
+        return std::nullopt;
+    return valueForLength(geometryProperty, containingBlockWidth);
+}
+
+FormattingContext::Geometry::VerticalGeometry FormattingContext::Geometry::outOfFlowNonReplacedVerticalGeometry(LayoutContext& layoutContext, const Box& layoutBox)
 {
     ASSERT(layoutBox.isOutOfFlowPositioned() && !layoutBox.replaced());
 
@@ -91,41 +98,92 @@ FormattingContext::Geometry::HeightAndMargin FormattingContext::Geometry::outOfF
     // 4. 'top' is 'auto', 'height' and 'bottom' are not 'auto', then set 'auto' values for 'margin-top' and 'margin-bottom' to 0, and solve for 'top'
     // 5. 'height' is 'auto', 'top' and 'bottom' are not 'auto', then 'auto' values for 'margin-top' and 'margin-bottom' are set to 0 and solve for 'height'
     // 6. 'bottom' is 'auto', 'top' and 'height' are not 'auto', then set 'auto' values for 'margin-top' and 'margin-bottom' to 0 and solve for 'bottom'
+
     auto& style = layoutBox.style();
-    auto top = style.logicalTop();
-    auto bottom = style.logicalBottom();
-    auto height = style.logicalHeight(); 
+    auto& displayBox = *layoutContext.displayBoxForLayoutBox(layoutBox);
+    auto& containingBlock = *layoutBox.containingBlock();
+    auto containingBlockHeight = layoutContext.displayBoxForLayoutBox(containingBlock)->height();
+    auto containingBlockWidth = layoutContext.displayBoxForLayoutBox(containingBlock)->width();
+
+    auto top = computedValueIfNotAuto(style.logicalTop(), containingBlockWidth);
+    auto bottom = computedValueIfNotAuto(style.logicalBottom(), containingBlockWidth);
+    auto height = computedValueIfNotAuto(style.logicalHeight(), containingBlockWidth);
+    auto marginTop = computedValueIfNotAuto(style.marginTop(), containingBlockWidth);
+    auto marginBottom = computedValueIfNotAuto(style.marginBottom(), containingBlockWidth);
+    auto paddingTop = displayBox.paddingTop();
+    auto paddingBottom = displayBox.paddingBottom();
+    auto borderTop = displayBox.borderTop();
+    auto borderBottom = displayBox.borderBottom();
+
+    if (!top && !height && !bottom)
+        top = displayBox.top();
+
+    if (top && height && bottom) {
+        if (!marginTop && !marginBottom) {
+            auto marginTopAndBottom = containingBlockHeight - (*top + borderTop + paddingTop + *height + paddingBottom + borderBottom + *bottom);
+            marginTop = marginBottom = marginTopAndBottom / 2;
+        } else if (!marginTop)
+            marginTop = containingBlockHeight - (*top + borderTop + paddingTop + *height + paddingBottom + borderBottom + *marginBottom + *bottom);
+        else
+            marginBottom = containingBlockHeight - (*top + *marginTop + borderTop + paddingTop + *height + paddingBottom + borderBottom + *bottom);
+        // Over-constrained?
+        auto boxHeight = *top + *marginTop + borderTop + paddingTop + *height + paddingBottom + borderBottom + *marginBottom + *bottom;
+        if (boxHeight > containingBlockHeight)
+            bottom = containingBlockHeight - (*top + *marginTop + borderTop + paddingTop + *height + paddingBottom + borderBottom + *marginBottom); 
+    }
 
-    auto containingBlockHeight = layoutContext.displayBoxForLayoutBox(*layoutBox.containingBlock())->height();
-    LayoutUnit computedHeightValue;
+    if (!top && !height && bottom) {
+        // #1
+        height = contentHeightForFormattingContextRoot(layoutContext, layoutBox);
+        marginTop = marginTop.value_or(0);
+        marginBottom = marginBottom.value_or(0);
+        top = containingBlockHeight - (*marginTop + borderTop + paddingTop + *height + paddingBottom + borderBottom + *marginBottom + *bottom); 
+    }
 
-    if (!height.isAuto())
-        computedHeightValue = valueForLength(height, containingBlockHeight);
-    else if ((top.isAuto() && bottom.isAuto())
-        || (top.isAuto() && !bottom.isAuto())
-        || (!top.isAuto() && bottom.isAuto())) {
-        // All auto (#3), #1 and #3
-        computedHeightValue = contentHeightForFormattingContextRoot(layoutContext, layoutBox);
-    } else if (!top.isAuto() && !bottom.isAuto()) {
-        // #5
-        auto& displayBox = *layoutContext.displayBoxForLayoutBox(layoutBox);
+    if (!top && !bottom && height) {
+        // #2
+        top = displayBox.top();
+        marginTop = marginTop.value_or(0);
+        marginBottom = marginBottom.value_or(0);
+        bottom = containingBlockHeight - (*top + *marginTop + borderTop + paddingTop + *height + paddingBottom + borderBottom + *marginBottom); 
+    }
 
-        auto marginTop = displayBox.marginTop();
-        auto marginBottom = displayBox.marginBottom();
-    
-        auto paddingTop = displayBox.paddingTop();
-        auto paddingBottom = displayBox.paddingBottom();
+    if (!height && !bottom && top) {
+        // #3
+        height = contentHeightForFormattingContextRoot(layoutContext, layoutBox);
+        marginTop = marginTop.value_or(0);
+        marginBottom = marginBottom.value_or(0);
+        bottom = containingBlockHeight - (*top + *marginTop + borderTop + paddingTop + *height + paddingBottom + borderBottom + *marginBottom); 
+    }
 
-        auto borderTop = displayBox.borderTop();
-        auto borderBottom = displayBox.borderBottom();
+    if (!top && height && bottom) {
+        // #4
+        marginTop = marginTop.value_or(0);
+        marginBottom = marginBottom.value_or(0);
+        top = containingBlockHeight - (*marginTop + borderTop + paddingTop + *height + paddingBottom + borderBottom + *marginBottom + *bottom); 
+    }
 
-        computedHeightValue = containingBlockHeight - (top.value() + marginTop + borderTop + paddingTop + paddingBottom + borderBottom + marginBottom + bottom.value());
-    } else {
-        // #2 #4 #6 have height != auto
-        ASSERT_NOT_REACHED();
+    if (!height && top && bottom) {
+        // #5
+        marginTop = marginTop.value_or(0);
+        marginBottom = marginBottom.value_or(0);
+        height = containingBlockHeight - (*top + *marginTop + borderTop + paddingTop + paddingBottom + borderBottom + *marginBottom + *bottom); 
     }
 
-    return { computedHeightValue, { } };
+    if (!bottom && top && height) {
+        // #6
+        marginTop = marginTop.value_or(0);
+        marginBottom = marginBottom.value_or(0);
+        bottom = containingBlockHeight - (*top + *marginTop + borderTop + paddingTop + *height + paddingBottom + borderBottom + *marginBottom); 
+    }
+
+    ASSERT(top);
+    ASSERT(bottom);
+    ASSERT(height);
+    ASSERT(marginTop);
+    ASSERT(marginBottom);
+
+    return { *top, *bottom, *height, { *marginTop, *marginBottom} };
 }
 
 FormattingContext::Geometry::WidthAndMargin FormattingContext::Geometry::outOfFlowNonReplacedWidthAndMargin(LayoutContext& layoutContext, const Box& layoutBox)
@@ -186,13 +244,14 @@ FormattingContext::Geometry::WidthAndMargin FormattingContext::Geometry::outOfFl
     return WidthAndMargin { computedWidthValue, { } };
 }
 
-FormattingContext::Geometry::HeightAndMargin FormattingContext::Geometry::outOfFlowReplacedHeightAndMargin(LayoutContext& layoutContext, const Box& layoutBox)
+FormattingContext::Geometry::VerticalGeometry FormattingContext::Geometry::outOfFlowReplacedVerticalGeometry(LayoutContext& layoutContext, const Box& layoutBox)
 {
     ASSERT(layoutBox.isOutOfFlowPositioned() && layoutBox.replaced());
     // 10.6.5 Absolutely positioned, replaced elements
     //
     // The used value of 'height' is determined as for inline replaced elements.
-    return inlineReplacedHeightAndMargin(layoutContext, layoutBox);
+    auto heightAndMargin = inlineReplacedHeightAndMargin(layoutContext, layoutBox);
+    return { { }, { }, heightAndMargin.height, heightAndMargin.margin };
 }
 
 FormattingContext::Geometry::WidthAndMargin FormattingContext::Geometry::outOfFlowReplacedWidthAndMargin(LayoutContext& layoutContext, const Box& layoutBox)
@@ -440,13 +499,13 @@ static LayoutPoint outOfFlowReplacedPosition(LayoutContext& layoutContext, const
     return { computedLeftValue, computedTopValue };
 }
 
-FormattingContext::Geometry::HeightAndMargin FormattingContext::Geometry::outOfFlowHeightAndMargin(LayoutContext& layoutContext, const Box& layoutBox)
+FormattingContext::Geometry::VerticalGeometry FormattingContext::Geometry::outOfFlowVerticalGeometry(LayoutContext& layoutContext, const Box& layoutBox)
 {
     ASSERT(layoutBox.isOutOfFlowPositioned());
 
     if (!layoutBox.replaced())
-        return outOfFlowNonReplacedHeightAndMargin(layoutContext, layoutBox);
-    return outOfFlowReplacedHeightAndMargin(layoutContext, layoutBox);
+        return outOfFlowNonReplacedVerticalGeometry(layoutContext, layoutBox);
+    return outOfFlowReplacedVerticalGeometry(layoutContext, layoutBox);
 }
 
 FormattingContext::Geometry::WidthAndMargin FormattingContext::Geometry::outOfFlowWidthAndMargin(LayoutContext& layoutContext, const Box& layoutBox)