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
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));
}
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.
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.
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();
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;