[LFC] If the top and bottom margins of a box are adjoining, then it is possible for...
authorzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 30 Jun 2018 18:06:22 +0000 (18:06 +0000)
committerzalan@apple.com <zalan@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 30 Jun 2018 18:06:22 +0000 (18:06 +0000)
https://bugs.webkit.org/show_bug.cgi?id=187220

Reviewed by Antti Koivisto.

* layout/blockformatting/BlockMarginCollapse.cpp:
(WebCore::Layout::isMarginBottomCollapsedThrough):
(WebCore::Layout::BlockFormattingContext::MarginCollapse::collapsedMarginTopFromFirstChild):
(WebCore::Layout::BlockFormattingContext::MarginCollapse::marginTop):
(WebCore::Layout::BlockFormattingContext::MarginCollapse::marginBottom):
(WebCore::Layout::BlockFormattingContext::MarginCollapse::isMarginBottomCollapsedWithParent):
(WebCore::Layout::BlockFormattingContext::MarginCollapse::collapsedMarginBottomFromLastChild):

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

Source/WebCore/ChangeLog
Source/WebCore/layout/blockformatting/BlockMarginCollapse.cpp

index 63fc65f..7a1f3ee 100644 (file)
@@ -1,5 +1,20 @@
 2018-06-30  Zalan Bujtas  <zalan@apple.com>
 
+        [LFC] If the top and bottom margins of a box are adjoining, then it is possible for margins to collapse through it.
+        https://bugs.webkit.org/show_bug.cgi?id=187220
+
+        Reviewed by Antti Koivisto.
+
+        * layout/blockformatting/BlockMarginCollapse.cpp:
+        (WebCore::Layout::isMarginBottomCollapsedThrough):
+        (WebCore::Layout::BlockFormattingContext::MarginCollapse::collapsedMarginTopFromFirstChild):
+        (WebCore::Layout::BlockFormattingContext::MarginCollapse::marginTop):
+        (WebCore::Layout::BlockFormattingContext::MarginCollapse::marginBottom):
+        (WebCore::Layout::BlockFormattingContext::MarginCollapse::isMarginBottomCollapsedWithParent):
+        (WebCore::Layout::BlockFormattingContext::MarginCollapse::collapsedMarginBottomFromLastChild):
+
+2018-06-30  Zalan Bujtas  <zalan@apple.com>
+
         [LFC] Adjust final out-of-flow position with the computed margin value.
         https://bugs.webkit.org/show_bug.cgi?id=187219
 
index 52d3ca3..870c4d6 100644 (file)
@@ -112,16 +112,40 @@ static bool isMarginTopCollapsedWithParent(const LayoutContext& layoutContext, c
     return true;
 }
 
+static bool isMarginBottomCollapsedThrough(const LayoutContext& layoutContext, const Box& layoutBox)
+{
+    // If the top and bottom margins of a box are adjoining, then it is possible for margins to collapse through it.
+    auto& displayBox = *layoutContext.displayBoxForLayoutBox(layoutBox);
+
+    if (displayBox.borderTop() || displayBox.borderBottom())
+        return false;
+
+    if (displayBox.paddingTop() || displayBox.paddingBottom())
+        return false;
+
+    if (!layoutBox.style().height().isAuto() || !layoutBox.style().minHeight().isAuto())
+        return false;
+
+    if (!is<Container>(layoutBox))
+        return true;
+
+    auto& container = downcast<Container>(layoutBox);
+    if (container.hasInFlowOrFloatingChild())
+        return false;
+
+    return true;
+}
+
 LayoutUnit BlockFormattingContext::MarginCollapse::collapsedMarginTopFromFirstChild(const LayoutContext& layoutContext, const Box& layoutBox)
 {
     // Check if the first child collapses its margin top.
     if (!is<Container>(layoutBox) || !downcast<Container>(layoutBox).hasInFlowChild())
         return 0;
 
+    // FIXME: Take collapsed through margin into account.
     auto& firstInFlowChild = *downcast<Container>(layoutBox).firstInFlowChild();
     if (!isMarginTopCollapsedWithParent(layoutContext, firstInFlowChild))
         return 0;
-
     // Collect collapsed margin top recursively.
     return marginValue(computedNonCollapsedMarginTop(layoutContext, firstInFlowChild), collapsedMarginTopFromFirstChild(layoutContext, firstInFlowChild));
 }
@@ -165,9 +189,14 @@ LayoutUnit BlockFormattingContext::MarginCollapse::marginTop(const LayoutContext
     if (isMarginTopCollapsedWithParent(layoutContext, layoutBox))
         return 0;
 
-    // Floats and out of flow positioned boxes do not collapse their margins.
-    if (!isMarginTopCollapsedWithSibling(layoutBox))
-        return nonCollapsedMarginTop(layoutContext, layoutBox);
+    if (!isMarginTopCollapsedWithSibling(layoutBox)) {
+        if (!isMarginBottomCollapsedThrough(layoutContext, layoutBox))
+            return nonCollapsedMarginTop(layoutContext, layoutBox);
+        // Compute the collapsed through value.
+        auto marginTop = nonCollapsedMarginTop(layoutContext, layoutBox);
+        auto marginBottom = nonCollapsedMarginBottom(layoutContext, layoutBox); 
+        return marginValue(marginTop, marginBottom);
+    }
 
     // The bottom margin of an in-flow block-level element always collapses with the top margin of its next in-flow block-level sibling,
     // unless that sibling has clearance.
@@ -186,7 +215,10 @@ LayoutUnit BlockFormattingContext::MarginCollapse::marginBottom(const LayoutCont
         return 0;
 
     // TODO: take _hasAdjoiningMarginTopAndBottom() into account.
-    if (BlockFormattingContext::MarginCollapse::isMarginBottomCollapsedWithParent(layoutContext, layoutBox))
+    if (isMarginBottomCollapsedWithParent(layoutContext, layoutBox))
+        return 0;
+
+    if (isMarginBottomCollapsedThrough(layoutContext, layoutBox))
         return 0;
 
     // Floats and out of flow positioned boxes do not collapse their margins.
@@ -210,6 +242,9 @@ bool BlockFormattingContext::MarginCollapse::isMarginBottomCollapsedWithParent(c
     if (layoutBox.isFloatingOrOutOfFlowPositioned())
         return false;
 
+    if (isMarginBottomCollapsedThrough(layoutContext, layoutBox))
+        return false;
+
     // We never margin collapse the initial containing block.
     ASSERT(layoutBox.parent());
     auto& parent = *layoutBox.parent();
@@ -248,6 +283,7 @@ LayoutUnit BlockFormattingContext::MarginCollapse::collapsedMarginBottomFromLast
     if (!is<Container>(layoutBox) || !downcast<Container>(layoutBox).hasInFlowChild())
         return 0;
 
+    // FIXME: Check for collapsed through margin.
     auto& lastInFlowChild = *downcast<Container>(layoutBox).lastInFlowChild();
     if (!isMarginBottomCollapsedWithParent(layoutContext, lastInFlowChild))
         return 0;