WebKit Bugzilla
Attachment 358143 Details for
Bug 192625
: [LFC][BFC][MarginCollapsing] Add support for peculiar cases.
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-192625-20181229182305.patch (text/plain), 83.76 KB, created by
zalan
on 2018-12-29 18:23:12 PST
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
zalan
Created:
2018-12-29 18:23:12 PST
Size:
83.76 KB
patch
obsolete
>Subversion Revision: 239540 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 8ecfee1d2c9f6197df758209640135c8423828f2..f2efd609450db4e2e30f105fdd853dde777257b5 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,117 @@ >+2018-12-29 Zalan Bujtas <zalan@apple.com> >+ >+ [LFC][BFC][MarginCollapsing] Add support for peculiar cases. >+ https://bugs.webkit.org/show_bug.cgi?id=192625 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Implement some of the more peculiar cases like margin collpasing through multiple boxes etc. >+ Add ~100 new passing cases. >+ >+ * Sources.txt: >+ * WebCore.xcodeproj/project.pbxproj: >+ * layout/FormattingContext.cpp: >+ (WebCore::Layout::FormattingContext::FormattingContext): >+ (WebCore::Layout::FormattingContext::formattingState const): Deleted. >+ * layout/FormattingContext.h: >+ * layout/FormattingContextGeometry.cpp: >+ (WebCore::Layout::FormattingContext::Geometry::computedMinHeight): >+ (WebCore::Layout::FormattingContext::Geometry::floatingNonReplacedWidthAndMargin): >+ (WebCore::Layout::FormattingContext::Geometry::floatingReplacedWidthAndMargin): >+ (WebCore::Layout::FormattingContext::Geometry::inlineReplacedHeightAndMargin): >+ (WebCore::Layout::FormattingContext::Geometry::computedNonCollapsedHorizontalMargin): >+ (WebCore::Layout::FormattingContext::Geometry::computedNonCollapsedVerticalMargin): >+ (WebCore::Layout::FormattingContext::Geometry::computedNonCollapsedHorizontalMarginValue): Deleted. >+ (WebCore::Layout::FormattingContext::Geometry::computedNonCollapsedVerticalMarginValue): Deleted. >+ * layout/FormattingContextQuirks.cpp: >+ (WebCore::Layout::FormattingContext::Quirks::heightValueOfNearestContainingBlockWithFixedHeight): >+ * layout/LayoutState.h: >+ (WebCore::Layout::LayoutState::hasFormattingState const): >+ * layout/MarginTypes.h: >+ * layout/blockformatting/BlockFormattingContext.cpp: >+ (WebCore::Layout::BlockFormattingContext::formattingState const): >+ (WebCore::Layout::BlockFormattingContext::computeEstimatedMarginBefore const): >+ (WebCore::Layout::BlockFormattingContext::computeEstimatedMarginBeforeForAncestors const): >+ (WebCore::Layout::hasPrecomputedMarginBefore): >+ (WebCore::Layout::BlockFormattingContext::computeFloatingPosition const): >+ (WebCore::Layout::BlockFormattingContext::computePositionToAvoidFloats const): >+ (WebCore::Layout::BlockFormattingContext::computeVerticalPositionForFloatClear const): >+ (WebCore::Layout::BlockFormattingContext::computeHeightAndMargin const): >+ (WebCore::Layout::BlockFormattingContext::adjustedVerticalPositionAfterMarginCollapsing const): >+ * layout/blockformatting/BlockFormattingContext.h: >+ (WebCore::Layout::BlockFormattingContext::Geometry::inFlowNonReplacedHeightAndMargin): >+ (WebCore::Layout::BlockFormattingContext::Geometry::inFlowNonReplacedWidthAndMargin): >+ (WebCore::Layout::BlockFormattingContext::Geometry::inFlowReplacedWidthAndMargin): >+ * layout/blockformatting/BlockFormattingContextGeometry.cpp: >+ (WebCore::Layout::BlockFormattingContext::Geometry::inFlowNonReplacedHeightAndMargin): >+ (WebCore::Layout::BlockFormattingContext::Geometry::inFlowHeightAndMargin): >+ (WebCore::Layout::BlockFormattingContext::Geometry::estimatedMarginBefore): Deleted. >+ (WebCore::Layout::BlockFormattingContext::Geometry::estimatedMarginAfter): Deleted. >+ * layout/blockformatting/BlockFormattingContextQuirks.cpp: >+ (WebCore::Layout::BlockFormattingContext::Quirks::stretchedInFlowHeight): >+ (WebCore::Layout::BlockFormattingContext::Quirks::shouldIgnoreMarginAfter): >+ (WebCore::Layout::BlockFormattingContext::Quirks::stretchedHeight): Deleted. >+ * layout/blockformatting/BlockFormattingState.h: >+ (WebCore::Layout::BlockFormattingState::setPositiveAndNegativeVerticalMargin): >+ (WebCore::Layout::BlockFormattingState::hasPositiveAndNegativeVerticalMargin const): >+ (WebCore::Layout::BlockFormattingState::positiveAndNegativeVerticalMargin const): >+ (WebCore::Layout::BlockFormattingState::setHasEstimatedMarginBefore): >+ (WebCore::Layout::BlockFormattingState::clearHasEstimatedMarginBefore): >+ (WebCore::Layout::BlockFormattingState::hasEstimatedMarginBefore const): >+ * layout/blockformatting/BlockMargin.cpp: Added. >+ (WebCore::Layout::hasBorder): >+ (WebCore::Layout::hasPadding): >+ (WebCore::Layout::hasBorderBefore): >+ (WebCore::Layout::hasBorderAfter): >+ (WebCore::Layout::hasPaddingBefore): >+ (WebCore::Layout::hasPaddingAfter): >+ (WebCore::Layout::hasClearance): >+ (WebCore::Layout::establishesBlockFormattingContext): >+ (WebCore::Layout::BlockFormattingContext::Margin::marginBeforeCollapsesWithParentMarginAfter): >+ (WebCore::Layout::BlockFormattingContext::Margin::marginBeforeCollapsesWithParentMarginBefore): >+ (WebCore::Layout::BlockFormattingContext::Margin::marginBeforeCollapsesWithPreviousSiblingMarginAfter): >+ (WebCore::Layout::BlockFormattingContext::Margin::marginBeforeCollapsesWithFirstInFlowChildMarginBefore): >+ (WebCore::Layout::BlockFormattingContext::Margin::marginAfterCollapsesWithSiblingMarginBeforeWithClearance): >+ (WebCore::Layout::BlockFormattingContext::Margin::marginAfterCollapsesWithParentMarginBefore): >+ (WebCore::Layout::BlockFormattingContext::Margin::marginAfterCollapsesWithParentMarginAfter): >+ (WebCore::Layout::BlockFormattingContext::Margin::marginAfterCollapsesWithLastInFlowChildMarginAfter): >+ (WebCore::Layout::BlockFormattingContext::Margin::marginAfterCollapsesWithNextSiblingMarginBefore): >+ (WebCore::Layout::BlockFormattingContext::Margin::marginsCollapseThrough): >+ (WebCore::Layout::computedPositiveAndNegativeMargin): >+ (WebCore::Layout::marginValue): >+ (WebCore::Layout::BlockFormattingContext::Margin::updateCollapsedMarginAfter): >+ (WebCore::Layout::BlockFormattingContext::Margin::positiveNegativeValues): >+ (WebCore::Layout::BlockFormattingContext::Margin::positiveNegativeMarginBefore): >+ (WebCore::Layout::BlockFormattingContext::Margin::positiveNegativeMarginAfter): >+ (WebCore::Layout::BlockFormattingContext::Margin::estimatedMarginBefore): >+ (WebCore::Layout::BlockFormattingContext::Margin::vertical): >+ * layout/blockformatting/BlockMarginCollapse.cpp: Removed. >+ * layout/displaytree/DisplayBox.cpp: >+ (WebCore::Display::Box::Box): >+ * layout/displaytree/DisplayBox.h: >+ (WebCore::Display::Box::hasClearance const): >+ (WebCore::Display::Box::setEstimatedMarginBefore): >+ (WebCore::Display::Box::estimatedMarginBefore const): >+ (WebCore::Display::Box::setHasClearance): >+ (WebCore::Display::Box::invalidateEstimatedMarginBefore): >+ (WebCore::Display::Box::setVerticalMargin): >+ (WebCore::Display::Box::rectWithMargin const): >+ * layout/floats/FloatingContext.cpp: >+ (WebCore::Layout::FloatingContext::verticalPositionWithClearance const): >+ * layout/inlineformatting/InlineFormattingContext.cpp: >+ (WebCore::Layout::InlineFormattingContext::formattingState const): >+ (WebCore::Layout::InlineFormattingContext::splitInlineRunIfNeeded const): >+ (WebCore::Layout::InlineFormattingContext::createFinalRuns const): >+ (WebCore::Layout::InlineFormattingContext::postProcessInlineRuns const): >+ (WebCore::Layout::InlineFormattingContext::layoutInlineContent const): >+ (WebCore::Layout::InlineFormattingContext::placeInFlowPositionedChildren const): >+ (WebCore::Layout::InlineFormattingContext::collectInlineContentForSubtree const): >+ (WebCore::Layout::InlineFormattingContext::instrinsicWidthConstraints const): >+ * layout/inlineformatting/InlineFormattingContext.h: >+ (WebCore::Layout::InlineFormattingContext::inlineFormattingState const): Deleted. >+ * layout/inlineformatting/InlineFormattingContextGeometry.cpp: >+ (WebCore::Layout::InlineFormattingContext::Geometry::inlineBlockWidthAndMargin): >+ > 2018-12-22 Carlos Garcia Campos <cgarcia@igalia.com> > > [HarfBuzz] Width not correctly reported as 0 for zero font size >diff --git a/Source/WebCore/Sources.txt b/Source/WebCore/Sources.txt >index e7d934ad27f1bfa91231e1d86df0b7419d838b90..e6fb284caf77e1ebfffa75d0bc858d83cb1cd778 100644 >--- a/Source/WebCore/Sources.txt >+++ b/Source/WebCore/Sources.txt >@@ -1278,7 +1278,7 @@ layout/blockformatting/BlockFormattingContext.cpp > layout/blockformatting/BlockFormattingContextGeometry.cpp > layout/blockformatting/BlockFormattingContextQuirks.cpp > layout/blockformatting/BlockFormattingState.cpp >-layout/blockformatting/BlockMarginCollapse.cpp >+layout/blockformatting/BlockMargin.cpp > layout/blockformatting/BlockInvalidation.cpp > layout/displaytree/DisplayBox.cpp > layout/floats/FloatAvoider.cpp >diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >index de452c062a6ba26f47327077fc1f99acfcfd8ceb..bd3f77087b89ab297dedc6b96f83920f924abb38 100644 >--- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj >+++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >@@ -5882,7 +5882,7 @@ > 115CFA81208B8EDA001E6991 /* FloatingState.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = FloatingState.cpp; sourceTree = "<group>"; }; > 115CFA84208B9066001E6991 /* FloatingContext.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = FloatingContext.h; sourceTree = "<group>"; }; > 115CFA85208B9066001E6991 /* FloatingContext.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = FloatingContext.cpp; sourceTree = "<group>"; }; >- 115CFA89208B921A001E6991 /* BlockMarginCollapse.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = BlockMarginCollapse.cpp; sourceTree = "<group>"; }; >+ 115CFA89208B921A001E6991 /* BlockMargin.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = BlockMargin.cpp; sourceTree = "<group>"; }; > 115CFA95208B952B001E6991 /* LayoutBox.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LayoutBox.h; sourceTree = "<group>"; }; > 115CFA96208B952B001E6991 /* LayoutBox.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = LayoutBox.cpp; sourceTree = "<group>"; }; > 115F7805209CBCBD00739C13 /* Invalidation.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Invalidation.h; sourceTree = "<group>"; }; >@@ -16210,7 +16210,7 @@ > 115CFA78208B8D9D001E6991 /* BlockFormattingState.h */, > 1123AFDA209ABB2000736ACC /* BlockInvalidation.cpp */, > 1123AFD9209ABB2000736ACC /* BlockInvalidation.h */, >- 115CFA89208B921A001E6991 /* BlockMarginCollapse.cpp */, >+ 115CFA89208B921A001E6991 /* BlockMargin.cpp */, > ); > path = blockformatting; > sourceTree = "<group>"; >diff --git a/Source/WebCore/layout/FormattingContextQuirks.cpp b/Source/WebCore/layout/FormattingContextQuirks.cpp >index b4f44a825ef3aa58ad2b36a0e2ad21475f2e87d5..fa1d0a80bc092c1909a163361a421976bfcd90fe 100644 >--- a/Source/WebCore/layout/FormattingContextQuirks.cpp >+++ b/Source/WebCore/layout/FormattingContextQuirks.cpp >@@ -51,7 +51,7 @@ LayoutUnit FormattingContext::Quirks::heightValueOfNearestContainingBlockWithFix > if (containingBlock->isBodyBox() || containingBlock->isDocumentBox()) { > auto& displayBox = layoutState.displayBoxForLayoutBox(*containingBlock); > >- auto verticalMargin = FormattingContext::Geometry::computedNonCollapsedVerticalMarginValue(layoutState, *containingBlock); >+ auto verticalMargin = Geometry::computedNonCollapsedVerticalMarginValue(layoutState, *containingBlock); > auto verticalPadding = displayBox.paddingTop().valueOr(0) + displayBox.paddingBottom().valueOr(0); > auto verticalBorder = displayBox.borderTop() + displayBox.borderBottom(); > bodyAndDocumentVerticalMarginPaddingAndBorder += verticalMargin.before + verticalMargin.after + verticalPadding + verticalBorder; >diff --git a/Source/WebCore/layout/LayoutState.h b/Source/WebCore/layout/LayoutState.h >index 04775ab2bb668fc226a3fc1324042dbcf12fb33f..28446cf9add3e79869861c9cc79c6985bcd9f7ae 100644 >--- a/Source/WebCore/layout/LayoutState.h >+++ b/Source/WebCore/layout/LayoutState.h >@@ -75,6 +75,7 @@ public: > > FormattingState& formattingStateForBox(const Box&) const; > FormattingState& establishedFormattingState(const Box& formattingRoot) const; >+ bool hasFormattingState(const Box& formattingRoot) const { return m_formattingStates.contains(&formattingRoot); } > FormattingState& createFormattingStateForFormattingRootIfNeeded(const Box& formattingRoot); > > Display::Box& displayBoxForLayoutBox(const Box& layoutBox) const; >diff --git a/Source/WebCore/layout/MarginTypes.h b/Source/WebCore/layout/MarginTypes.h >index 85ffed6596867893f7d6e7df586524d687c31497..449ab4f6019fa2490d3abdff456f1736506182c2 100644 >--- a/Source/WebCore/layout/MarginTypes.h >+++ b/Source/WebCore/layout/MarginTypes.h >@@ -39,10 +39,11 @@ struct VerticalMargin { > }; > ComputedValues usedValues() const; > ComputedValues nonCollapsedValues() const { return m_nonCollapsed; } >- >+ > struct CollapsedValues { > Optional<LayoutUnit> before; > Optional<LayoutUnit> after; >+ bool isCollapsedThrough { false }; > }; > Optional<CollapsedValues> collapsedValues() const { return m_collapsed; } > void setCollapsedValues(CollapsedValues collapsedValues) { m_collapsed = collapsedValues; } >@@ -51,6 +52,7 @@ struct VerticalMargin { > > VerticalMargin() = default; > ~VerticalMargin() = default; >+ > private: > ComputedValues m_nonCollapsed; > Optional<CollapsedValues> m_collapsed; >@@ -70,6 +72,10 @@ struct PositiveAndNegativeVerticalMargin { > Values after; > }; > >+struct EstimatedMarginBefore { >+ LayoutUnit computedValue; >+}; >+ > inline VerticalMargin::VerticalMargin(VerticalMargin::ComputedValues nonCollapsed, Optional<VerticalMargin::CollapsedValues> collapsed) > : m_nonCollapsed(nonCollapsed) > , m_collapsed(collapsed) >diff --git a/Source/WebCore/layout/blockformatting/BlockFormattingContext.cpp b/Source/WebCore/layout/blockformatting/BlockFormattingContext.cpp >index 429c0a9811a48dbf4551a4be92130f250143a38b..934bc78b00c4cb25477510b2bbf67672e0dac3e9 100644 >--- a/Source/WebCore/layout/blockformatting/BlockFormattingContext.cpp >+++ b/Source/WebCore/layout/blockformatting/BlockFormattingContext.cpp >@@ -186,12 +186,14 @@ void BlockFormattingContext::computeStaticPosition(const Box& layoutBox) const > > void BlockFormattingContext::computeEstimatedMarginBefore(const Box& layoutBox) const > { >- auto& layoutState = this->layoutState(); >- auto estimatedMarginBefore = Geometry::estimatedMarginBefore(layoutState, layoutBox); >+ auto estimatedMarginBefore = Margin::estimatedMarginBefore(layoutState(), layoutBox); >+ blockFormattingState().setHasEstimatedMarginBefore(layoutBox); > >- auto& displayBox = layoutState.displayBoxForLayoutBox(layoutBox); >+ auto& displayBox = layoutState().displayBoxForLayoutBox(layoutBox); >+#if !ASSERT_DISABLED > displayBox.setEstimatedMarginBefore(estimatedMarginBefore); >- displayBox.moveVertically(estimatedMarginBefore); >+#endif >+ displayBox.setTop(adjustedVerticalPositionAfterMarginCollapsing(layoutBox, estimatedMarginBefore.computedValue)); > } > > void BlockFormattingContext::computeEstimatedMarginBeforeForAncestors(const Box& layoutBox) const >@@ -208,12 +210,11 @@ void BlockFormattingContext::computeEstimatedMarginBeforeForAncestors(const Box& > // So when we get to the point where we intersect the box with the float to decide if the box needs to move, we don't yet have the final vertical position. > // > // The idea here is that as long as we don't cross the block formatting context boundary, we should be able to pre-compute the final top margin. >- auto& layoutState = this->layoutState(); >+ auto& formattingState = blockFormattingState(); > > for (auto* ancestor = layoutBox.containingBlock(); ancestor && !ancestor->establishesBlockFormattingContext(); ancestor = ancestor->containingBlock()) { >- auto& displayBox = layoutState.displayBoxForLayoutBox(*ancestor); > // FIXME: with incremental layout, we might actually have a valid (non-estimated) margin top as well. >- if (displayBox.estimatedMarginBefore()) >+ if (formattingState.hasEstimatedMarginBefore(*ancestor)) > return; > > computeEstimatedMarginBefore(*ancestor); >@@ -238,10 +239,10 @@ void BlockFormattingContext::precomputeVerticalPositionForFormattingRootIfNeeded > } > > #ifndef NDEBUG >-static bool hasPrecomputedMarginBefore(const LayoutState& layoutState, const Box& layoutBox) >+static bool hasPrecomputedMarginBefore(const BlockFormattingState& formattingState, const Box& layoutBox) > { > for (auto* ancestor = layoutBox.containingBlock(); ancestor && !ancestor->establishesBlockFormattingContext(); ancestor = ancestor->containingBlock()) { >- if (layoutState.displayBoxForLayoutBox(*ancestor).estimatedMarginBefore()) >+ if (formattingState.hasEstimatedMarginBefore(*ancestor)) > continue; > return false; > } >@@ -253,7 +254,7 @@ void BlockFormattingContext::computeFloatingPosition(const FloatingContext& floa > { > auto& layoutState = this->layoutState(); > ASSERT(layoutBox.isFloatingPositioned()); >- ASSERT(hasPrecomputedMarginBefore(layoutState, layoutBox)); >+ ASSERT(hasPrecomputedMarginBefore(blockFormattingState(), layoutBox)); > > auto& displayBox = layoutState.displayBoxForLayoutBox(layoutBox); > // 8.3.1 Collapsing margins >@@ -273,7 +274,7 @@ void BlockFormattingContext::computePositionToAvoidFloats(const FloatingContext& > ASSERT(layoutBox.establishesBlockFormattingContext()); > ASSERT(!layoutBox.isFloatingPositioned()); > ASSERT(!layoutBox.hasFloatClear()); >- ASSERT(hasPrecomputedMarginBefore(layoutState, layoutBox)); >+ ASSERT(hasPrecomputedMarginBefore(blockFormattingState(), layoutBox)); > > if (floatingContext.floatingState().isEmpty()) > return; >@@ -292,7 +293,7 @@ void BlockFormattingContext::computeVerticalPositionForFloatClear(const Floating > // For formatting roots, we already precomputed final position. > if (!layoutBox.establishesFormattingContext()) > computeEstimatedMarginBeforeForAncestors(layoutBox); >- ASSERT(hasPrecomputedMarginBefore(layoutState, layoutBox)); >+ ASSERT(hasPrecomputedMarginBefore(blockFormattingState(), layoutBox)); > > if (auto verticalPositionWithClearance = floatingContext.verticalPositionWithClearance(layoutBox)) > layoutState.displayBoxForLayoutBox(layoutBox).setTop(*verticalPositionWithClearance); >@@ -372,12 +373,15 @@ void BlockFormattingContext::computeHeightAndMargin(const Box& layoutBox) const > } > > auto& displayBox = layoutState.displayBoxForLayoutBox(layoutBox); >+ auto& formattingState = this->blockFormattingState(); >+ if (formattingState.hasEstimatedMarginBefore(layoutBox)) { >+ formattingState.clearHasEstimatedMarginBefore(layoutBox); >+ ASSERT(layoutState.displayBoxForLayoutBox(layoutBox).estimatedMarginBefore()->computedValue == heightAndMargin.margin.usedValues().before); >+ } else >+ displayBox.setTop(adjustedVerticalPositionAfterMarginCollapsing(layoutBox, heightAndMargin.margin.usedValues().before)); >+ > displayBox.setContentBoxHeight(heightAndMargin.height); > displayBox.setVerticalMargin(heightAndMargin.margin); >- >- // If this box has already been moved by the estimated vertical margin, no need to move it again. >- if (layoutBox.isFloatingPositioned() || !displayBox.estimatedMarginBefore()) >- displayBox.moveVertically(heightAndMargin.margin.usedValues().before); > } > > FormattingContext::InstrinsicWidthConstraints BlockFormattingContext::instrinsicWidthConstraints() const >@@ -444,6 +448,37 @@ FormattingContext::InstrinsicWidthConstraints BlockFormattingContext::instrinsic > return instrinsicWidthConstraints; > } > >+LayoutUnit BlockFormattingContext::adjustedVerticalPositionAfterMarginCollapsing(const Box& layoutBox, LayoutUnit marginBefore) const >+{ >+ // Now that we've computed the final margin before, let's shift the box's vertical position. >+ // 1. Check if the margin before collapses with the previous box's margin after. if not -> return previous box's bottom inlcuding margin after + marginBefore >+ // 2. Check if the previous box's margins collapse through. If not -> return previous box' bottom excluding margin after + marginBefore (they are supposed to be equal) >+ // 3. Go to previous box and start from step #1 until we hit the parent box. >+ auto& layoutState = this->layoutState(); >+ auto* currentLayoutBox = &layoutBox; >+ while (currentLayoutBox) { >+ if (!currentLayoutBox->previousInFlowSibling()) >+ break; >+ auto& previousInFlowSibling = *currentLayoutBox->previousInFlowSibling(); >+ if (!Margin::marginBeforeCollapsesWithPreviousSiblingMarginAfter(layoutState, *currentLayoutBox)) { >+ auto& previousDisplayBox = layoutState.displayBoxForLayoutBox(previousInFlowSibling); >+ return previousDisplayBox.rectWithMargin().bottom() + marginBefore; >+ } >+ >+ if (!Margin::marginsCollapseThrough(layoutState, previousInFlowSibling)) { >+ auto& previousDisplayBox = layoutState.displayBoxForLayoutBox(previousInFlowSibling); >+ return previousDisplayBox.bottom() + marginBefore; >+ } >+ currentLayoutBox = &previousInFlowSibling; >+ } >+ >+ auto containingBlockContentBoxTop = layoutState.displayBoxForLayoutBox(*layoutBox.containingBlock()).contentBoxTop(); >+ if (Margin::marginBeforeCollapsesWithParentMarginBefore(layoutState, layoutBox) || Margin::marginBeforeCollapsesWithParentMarginAfter(layoutState, layoutBox)) >+ return containingBlockContentBoxTop; >+ >+ return containingBlockContentBoxTop + marginBefore; >+} >+ > } > } > >diff --git a/Source/WebCore/layout/blockformatting/BlockFormattingContext.h b/Source/WebCore/layout/blockformatting/BlockFormattingContext.h >index 68041d4908567fb889340d6b53b7e3f2082ec180..9a412ae402695fce1b957332c3685508edf34214 100644 >--- a/Source/WebCore/layout/blockformatting/BlockFormattingContext.h >+++ b/Source/WebCore/layout/blockformatting/BlockFormattingContext.h >@@ -50,6 +50,8 @@ public: > void layout() const override; > > private: >+ BlockFormattingState& blockFormattingState() const { return downcast<BlockFormattingState>(formattingState()); } >+ > void layoutFormattingContextRoot(FloatingContext&, const Box&) const; > void placeInFlowPositionedChildren(const Container&) const; > >@@ -67,6 +69,7 @@ private: > void precomputeVerticalPositionForFormattingRootIfNeeded(const Box&) const; > > InstrinsicWidthConstraints instrinsicWidthConstraints() const override; >+ LayoutUnit adjustedVerticalPositionAfterMarginCollapsing(const Box&, LayoutUnit marginBefore) const; > > // This class implements positioning and sizing for boxes participating in a block formatting context. > class Geometry : public FormattingContext::Geometry { >@@ -79,49 +82,47 @@ private: > static bool instrinsicWidthConstraintsNeedChildrenWidth(const Box&); > static InstrinsicWidthConstraints instrinsicWidthConstraints(const LayoutState&, const Box&); > >- static LayoutUnit estimatedMarginBefore(const LayoutState&, const Box&); >- static LayoutUnit estimatedMarginAfter(const LayoutState&, const Box&); >- > private: >- // This class implements margin collapsing for block formatting context. >- class MarginCollapse { >- public: >- static LayoutUnit marginBefore(const LayoutState&, const Box&); >- static LayoutUnit marginAfter(const LayoutState&, const Box&); >+ static HeightAndMargin inFlowNonReplacedHeightAndMargin(const LayoutState&, const Box&, Optional<LayoutUnit> usedHeight = { }); >+ static WidthAndMargin inFlowNonReplacedWidthAndMargin(const LayoutState&, const Box&, Optional<LayoutUnit> usedWidth = { }); >+ static WidthAndMargin inFlowReplacedWidthAndMargin(const LayoutState&, const Box&, Optional<LayoutUnit> usedWidth = { }); >+ static Point staticPositionForOutOfFlowPositioned(const LayoutState&, const Box&); >+ }; > >- static bool marginBeforeCollapsesWithParentMarginAfter(const LayoutState&, const Box&); >- static bool marginAfterCollapsesWithParentMarginAfter(const LayoutState&, const Box&); >+ class Margin { >+ public: >+ static VerticalMargin vertical(const LayoutState&, const Box&); > >- private: >- static LayoutUnit collapsedMarginAfterFromLastChild(const LayoutState&, const Box&); >- static LayoutUnit nonCollapsedMarginAfter(const LayoutState&, const Box&); >+ static EstimatedMarginBefore estimatedMarginBefore(const LayoutState&, const Box&); >+ static void updateCollapsedMarginAfter(const LayoutState&, const Box&, const VerticalMargin& nextSiblingVerticalMargin); > >- static LayoutUnit computedNonCollapsedMarginBefore(const LayoutState&, const Box&); >- static LayoutUnit computedNonCollapsedMarginAfter(const LayoutState&, const Box&); >+ static bool marginBeforeCollapsesWithParentMarginBefore(const LayoutState&, const Box&); >+ static bool marginBeforeCollapsesWithFirstInFlowChildMarginBefore(const LayoutState&, const Box&); >+ static bool marginBeforeCollapsesWithParentMarginAfter(const LayoutState&, const Box&); >+ static bool marginBeforeCollapsesWithPreviousSiblingMarginAfter(const LayoutState&, const Box&); > >- static LayoutUnit collapsedMarginBeforeFromFirstChild(const LayoutState&, const Box&); >- static LayoutUnit nonCollapsedMarginBefore(const LayoutState&, const Box&); >+ static bool marginAfterCollapsesWithParentMarginAfter(const LayoutState&, const Box&); >+ static bool marginAfterCollapsesWithLastInFlowChildMarginAfter(const LayoutState&, const Box&); >+ static bool marginAfterCollapsesWithParentMarginBefore(const LayoutState&, const Box&); >+ static bool marginAfterCollapsesWithNextSiblingMarginBefore(const LayoutState&, const Box&); >+ static bool marginAfterCollapsesWithSiblingMarginBeforeWithClearance(const LayoutState&, const Box&); > >- static bool marginBeforeCollapsesWithParentMarginBefore(const LayoutState&, const Box&); >- static bool marginBeforeCollapsesWithPreviousSibling(const Box&); >- static bool marginAfterCollapsesWithNextSibling(const Box&); >- static bool marginAfterCollapsesWithSiblingMarginBeforeWithClearance(const LayoutState&, const Box&); >- static bool marginAfterCollapsesWithParentMarginBefore(const LayoutState&, const Box&); >- static bool marginsCollapseThrough(const LayoutState&, const Box&); >- }; >+ static bool marginsCollapseThrough(const LayoutState&, const Box&); > >- static HeightAndMargin inFlowNonReplacedHeightAndMargin(const LayoutState&, const Box&, Optional<LayoutUnit> usedHeight = { }); >- static WidthAndMargin inFlowNonReplacedWidthAndMargin(const LayoutState&, const Box&, Optional<LayoutUnit> usedWidth = { }); >- static WidthAndMargin inFlowReplacedWidthAndMargin(const LayoutState&, const Box&, Optional<LayoutUnit> usedWidth = { }); >- static Point staticPositionForOutOfFlowPositioned(const LayoutState&, const Box&); >+ private: >+ enum class MarginType { Before, After }; >+ static PositiveAndNegativeVerticalMargin::Values positiveNegativeValues(const LayoutState&, const Box&, MarginType); >+ static PositiveAndNegativeVerticalMargin::Values positiveNegativeMarginBefore(const LayoutState&, const Box&); >+ static PositiveAndNegativeVerticalMargin::Values positiveNegativeMarginAfter(const LayoutState&, const Box&); > }; > > class Quirks { > public: > static bool needsStretching(const LayoutState&, const Box&); >- static HeightAndMargin stretchedHeight(const LayoutState&, const Box&, HeightAndMargin); >+ static HeightAndMargin stretchedInFlowHeight(const LayoutState&, const Box&, HeightAndMargin); > > static bool shouldIgnoreMarginBefore(const LayoutState&, const Box&); >+ static bool shouldIgnoreMarginAfter(const LayoutState&, const Box&); > }; > }; > >diff --git a/Source/WebCore/layout/blockformatting/BlockFormattingContextGeometry.cpp b/Source/WebCore/layout/blockformatting/BlockFormattingContextGeometry.cpp >index ee43872eab6e500be8ac72b15af9010beebf8106..007f72a3044c1cc3da18369e279bb5ab502c4332 100644 >--- a/Source/WebCore/layout/blockformatting/BlockFormattingContextGeometry.cpp >+++ b/Source/WebCore/layout/blockformatting/BlockFormattingContextGeometry.cpp >@@ -57,13 +57,9 @@ HeightAndMargin BlockFormattingContext::Geometry::inFlowNonReplacedHeightAndMarg > // Only children in the normal flow are taken into account (i.e., floating boxes and absolutely positioned boxes are ignored, > // and relatively positioned boxes are considered without their offset). Note that the child box may be an anonymous block box. > >- auto& style = layoutBox.style(); >- auto containingBlockWidth = layoutState.displayBoxForLayoutBox(*layoutBox.containingBlock()).contentBoxWidth(); > auto& displayBox = layoutState.displayBoxForLayoutBox(layoutBox); >- >- auto nonCollapsedMargin = VerticalMargin::ComputedValues { computedValueIfNotAuto(style.marginBefore(), containingBlockWidth).valueOr(0), >- computedValueIfNotAuto(style.marginAfter(), containingBlockWidth).valueOr(0) }; >- auto collapsedMargin = VerticalMargin::CollapsedValues { MarginCollapse::marginBefore(layoutState, layoutBox), MarginCollapse::marginAfter(layoutState, layoutBox) }; >+ auto nonCollapsedMargin = computedNonCollapsedVerticalMarginValue(layoutState, layoutBox); >+ auto collapsedMargin = Margin::vertical(layoutState, layoutBox).collapsedValues(); > auto borderAndPaddingTop = displayBox.borderTop() + displayBox.paddingTop().valueOr(0); > > auto height = usedHeight ? usedHeight.value() : computedHeightValue(layoutState, layoutBox, HeightType::Normal); >@@ -84,14 +80,14 @@ HeightAndMargin BlockFormattingContext::Geometry::inFlowNonReplacedHeightAndMarg > // 2. the bottom edge of the bottom (possibly collapsed) margin of its last in-flow child, if the child's bottom margin... > auto* lastInFlowChild = downcast<Container>(layoutBox).lastInFlowChild(); > ASSERT(lastInFlowChild); >- if (!MarginCollapse::marginAfterCollapsesWithParentMarginAfter(layoutState, *lastInFlowChild)) { >+ if (!Margin::marginAfterCollapsesWithParentMarginAfter(layoutState, *lastInFlowChild)) { > auto& lastInFlowDisplayBox = layoutState.displayBoxForLayoutBox(*lastInFlowChild); > return { lastInFlowDisplayBox.bottom() + lastInFlowDisplayBox.marginAfter() - borderAndPaddingTop, { nonCollapsedMargin, collapsedMargin } }; > } > > // 3. the bottom border edge of the last in-flow child whose top margin doesn't collapse with the element's bottom margin > auto* inFlowChild = lastInFlowChild; >- while (inFlowChild && MarginCollapse::marginBeforeCollapsesWithParentMarginAfter(layoutState, *inFlowChild)) >+ while (inFlowChild && Margin::marginBeforeCollapsesWithParentMarginAfter(layoutState, *inFlowChild)) > inFlowChild = inFlowChild->previousInFlowSibling(); > if (inFlowChild) { > auto& inFlowDisplayBox = layoutState.displayBoxForLayoutBox(*inFlowChild); >@@ -103,6 +99,9 @@ HeightAndMargin BlockFormattingContext::Geometry::inFlowNonReplacedHeightAndMarg > }; > > auto heightAndMargin = compute(); >+ // Adjust the previous sibling's margin bottom now that this box's vertical margin is computed. >+ if (Margin::marginBeforeCollapsesWithPreviousSiblingMarginAfter(layoutState, layoutBox)) >+ Margin::updateCollapsedMarginAfter(layoutState, *layoutBox.previousInFlowSibling(), heightAndMargin.margin); > > LOG_WITH_STREAM(FormattingContextLayout, stream << "[Height][Margin] -> inflow non-replaced -> height(" << heightAndMargin.height << "px) margin(" << heightAndMargin.margin.usedValues().before << "px, " << heightAndMargin.margin.usedValues().after << "px) -> layoutBox(" << &layoutBox << ")"); > return heightAndMargin; >@@ -261,7 +260,7 @@ HeightAndMargin BlockFormattingContext::Geometry::inFlowHeightAndMargin(const La > if (!Quirks::needsStretching(layoutState, layoutBox)) > return heightAndMargin; > >- heightAndMargin = Quirks::stretchedHeight(layoutState, layoutBox, heightAndMargin); >+ heightAndMargin = Quirks::stretchedInFlowHeight(layoutState, layoutBox, heightAndMargin); > > LOG_WITH_STREAM(FormattingContextLayout, stream << "[Height][Margin] -> inflow non-replaced -> streched to viewport -> height(" << heightAndMargin.height << "px) margin(" << heightAndMargin.margin.usedValues().before << "px, " << heightAndMargin.margin.usedValues().after << "px) -> layoutBox(" << &layoutBox << ")"); > return heightAndMargin; >@@ -322,30 +321,6 @@ FormattingContext::InstrinsicWidthConstraints BlockFormattingContext::Geometry:: > return { minimumIntrinsicWidth, maximumIntrinsicWidth }; > } > >-LayoutUnit BlockFormattingContext::Geometry::estimatedMarginBefore(const LayoutState& layoutState, const Box& layoutBox) >-{ >- ASSERT(layoutBox.isBlockLevelBox()); >- // Can't estimate vertical margins for out of flow boxes (and we shouldn't need to do it for float boxes). >- ASSERT(layoutBox.isInFlow()); >- // Can't cross block formatting context boundary. >- ASSERT(!layoutBox.establishesBlockFormattingContext()); >- >- // Let's just use the normal path for now. >- return MarginCollapse::marginBefore(layoutState, layoutBox); >-} >- >-LayoutUnit BlockFormattingContext::Geometry::estimatedMarginAfter(const LayoutState& layoutState, const Box& layoutBox) >-{ >- ASSERT(layoutBox.isBlockLevelBox()); >- // Can't estimate vertical margins for out of flow boxes (and we shouldn't need to do it for float boxes). >- ASSERT(layoutBox.isInFlow()); >- // Can't cross block formatting context boundary. >- ASSERT(!layoutBox.establishesBlockFormattingContext()); >- >- // Let's just use the normal path for now. >- return MarginCollapse::marginAfter(layoutState, layoutBox); >-} >- > } > } > >diff --git a/Source/WebCore/layout/blockformatting/BlockFormattingContextQuirks.cpp b/Source/WebCore/layout/blockformatting/BlockFormattingContextQuirks.cpp >index 4606f9dc6628ee03f30c7a95f439fb13e740709d..b03c23a0ea55d2cd383dfe0e7765187c75c16575 100644 >--- a/Source/WebCore/layout/blockformatting/BlockFormattingContextQuirks.cpp >+++ b/Source/WebCore/layout/blockformatting/BlockFormattingContextQuirks.cpp >@@ -66,8 +66,9 @@ bool BlockFormattingContext::Quirks::needsStretching(const LayoutState& layoutSt > return layoutBox.style().logicalHeight().isAuto(); > } > >-HeightAndMargin BlockFormattingContext::Quirks::stretchedHeight(const LayoutState& layoutState, const Box& layoutBox, HeightAndMargin heightAndMargin) >+HeightAndMargin BlockFormattingContext::Quirks::stretchedInFlowHeight(const LayoutState& layoutState, const Box& layoutBox, HeightAndMargin heightAndMargin) > { >+ ASSERT(layoutBox.isInFlow()); > ASSERT(layoutBox.isDocumentBox() || layoutBox.isBodyBox()); > > auto& documentBox = layoutBox.isDocumentBox() ? layoutBox : *layoutBox.parent(); >@@ -88,12 +89,10 @@ HeightAndMargin BlockFormattingContext::Quirks::stretchedHeight(const LayoutStat > // Here is the quirky part for body box: > // Stretch the body using the initial containing block's height and shrink it with document box's margin/border/padding. > // This looks extremely odd when html has non-auto height. >- auto verticalMargin = Geometry::estimatedMarginBefore(layoutState, documentBox) + Geometry::estimatedMarginAfter(layoutState, documentBox); >- strechedHeight -= verticalMargin; >+ auto documentBoxVerticalMargin = Geometry::computedNonCollapsedVerticalMarginValue(layoutState, documentBox); >+ strechedHeight -= (documentBoxVerticalMargin.before + documentBoxVerticalMargin.after); > >- // This quirk happens when the body height is 0 which means its vertical margins collapse through (top and bottom margins are adjoining). >- // However now that we stretch the body they don't collapse through anymore, so we need to use the non-collapsed values instead. >- auto bodyBoxVerticalMargin = heightAndMargin.height ? heightAndMargin.margin.usedValues() : heightAndMargin.margin.nonCollapsedValues(); >+ auto bodyBoxVerticalMargin = heightAndMargin.margin.usedValues(); > totalVerticalMargin = bodyBoxVerticalMargin.before + bodyBoxVerticalMargin.after; > } > >@@ -112,6 +111,20 @@ bool BlockFormattingContext::Quirks::shouldIgnoreMarginBefore(const LayoutState& > return layoutState.inQuirksMode() && isQuirkContainer(*layoutBox.parent()) && hasMarginBeforeQuirkValue(layoutBox); > } > >+bool BlockFormattingContext::Quirks::shouldIgnoreMarginAfter(const LayoutState& layoutState, const Box& layoutBox) >+{ >+ // Ignore maring after when the ignored margin before collapses through. >+ if (!shouldIgnoreMarginBefore(layoutState, layoutBox)) >+ return false; >+ >+ ASSERT(layoutBox.parent()); >+ auto& parent = *layoutBox.parent(); >+ if (parent.firstInFlowOrFloatingChild() != &layoutBox || parent.firstInFlowOrFloatingChild() != parent.lastInFlowOrFloatingChild()) >+ return false; >+ >+ return Margin::marginsCollapseThrough(layoutState, layoutBox); >+} >+ > } > } > >diff --git a/Source/WebCore/layout/blockformatting/BlockFormattingState.h b/Source/WebCore/layout/blockformatting/BlockFormattingState.h >index bb9669390ff9a2876fe714dc8544b01df6deaa84..bb456b5927fefe45c637831d5b24f717092bad2a 100644 >--- a/Source/WebCore/layout/blockformatting/BlockFormattingState.h >+++ b/Source/WebCore/layout/blockformatting/BlockFormattingState.h >@@ -28,6 +28,7 @@ > #if ENABLE(LAYOUT_FORMATTING_CONTEXT) > > #include "FormattingState.h" >+#include "MarginTypes.h" > #include <wtf/IsoMalloc.h> > > namespace WebCore { >@@ -42,6 +43,18 @@ public: > virtual ~BlockFormattingState(); > > std::unique_ptr<FormattingContext> createFormattingContext(const Box& formattingContextRoot) override; >+ >+ void setPositiveAndNegativeVerticalMargin(const Box& layoutBox, PositiveAndNegativeVerticalMargin verticalMargin) { m_positiveAndNegativeVerticalMargin.set(&layoutBox, verticalMargin); } >+ bool hasPositiveAndNegativeVerticalMargin(const Box& layoutBox) const { return m_positiveAndNegativeVerticalMargin.contains(&layoutBox); } >+ PositiveAndNegativeVerticalMargin positiveAndNegativeVerticalMargin(const Box& layoutBox) const { return m_positiveAndNegativeVerticalMargin.get(&layoutBox); } >+ >+ void setHasEstimatedMarginBefore(const Box& layoutBox) { m_estimatedMarginBeforeList.add(&layoutBox); } >+ void clearHasEstimatedMarginBefore(const Box& layoutBox) { m_estimatedMarginBeforeList.remove(&layoutBox); } >+ bool hasEstimatedMarginBefore(const Box& layoutBox) const { return m_estimatedMarginBeforeList.contains(&layoutBox); } >+ >+private: >+ HashMap<const Box*, PositiveAndNegativeVerticalMargin> m_positiveAndNegativeVerticalMargin; >+ HashSet<const Box*> m_estimatedMarginBeforeList; > }; > > } >diff --git a/Source/WebCore/layout/blockformatting/BlockMarginCollapse.cpp b/Source/WebCore/layout/blockformatting/BlockMarginCollapse.cpp >deleted file mode 100644 >index 567708745394a785b84d97c82f5f48135a3f8d50..0000000000000000000000000000000000000000 >--- a/Source/WebCore/layout/blockformatting/BlockMarginCollapse.cpp >+++ /dev/null >@@ -1,465 +0,0 @@ >-/* >- * Copyright (C) 2018 Apple Inc. All rights reserved. >- * >- * Redistribution and use in source and binary forms, with or without >- * modification, are permitted provided that the following conditions >- * are met: >- * 1. Redistributions of source code must retain the above copyright >- * notice, this list of conditions and the following disclaimer. >- * 2. Redistributions in binary form must reproduce the above copyright >- * notice, this list of conditions and the following disclaimer in the >- * documentation and/or other materials provided with the distribution. >- * >- * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' >- * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, >- * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR >- * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS >- * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR >- * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF >- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS >- * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN >- * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) >- * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF >- * THE POSSIBILITY OF SUCH DAMAGE. >- */ >- >-#include "config.h" >-#include "BlockFormattingContext.h" >- >-#if ENABLE(LAYOUT_FORMATTING_CONTEXT) >- >-#include "InlineFormattingState.h" >-#include "LayoutBox.h" >-#include "LayoutContainer.h" >-#include "LayoutUnit.h" >-#include "RenderStyle.h" >- >-namespace WebCore { >-namespace Layout { >- >-static bool hasBorder(const BorderValue& borderValue) >-{ >- if (borderValue.style() == BorderStyle::None || borderValue.style() == BorderStyle::Hidden) >- return false; >- return !!borderValue.width(); >-} >- >-static bool hasPadding(const Length& paddingValue) >-{ >- // FIXME: Check if percent value needs to be resolved. >- return !paddingValue.isZero(); >-} >- >-static bool hasBorderBefore(const Box& layoutBox) >-{ >- return hasBorder(layoutBox.style().borderBefore()); >-} >- >-static bool hasBorderAfter(const Box& layoutBox) >-{ >- return hasBorder(layoutBox.style().borderAfter()); >-} >- >-static bool hasPaddingBefore(const Box& layoutBox) >-{ >- return hasPadding(layoutBox.style().paddingBefore()); >-} >- >-static bool hasPaddingAfter(const Box& layoutBox) >-{ >- return hasPadding(layoutBox.style().paddingAfter()); >-} >- >-static bool hasClearance(const Box& layoutBox) >-{ >- if (!layoutBox.hasFloatClear()) >- return false; >- // FIXME >- return false; >-} >- >-static bool establishesBlockFormattingContext(const Box& layoutBox) >-{ >- // WebKit treats the document element renderer as a block formatting context root. It probably only impacts margin collapsing, so let's not do >- // a layout wide quirk on this for now. >- if (layoutBox.isDocumentBox()) >- return true; >- return layoutBox.establishesBlockFormattingContext(); >-} >- >-static LayoutUnit marginValue(LayoutUnit currentMarginValue, LayoutUnit candidateMarginValue) >-{ >- if (!candidateMarginValue) >- return currentMarginValue; >- if (!currentMarginValue) >- return candidateMarginValue; >- // Both margins are positive. >- if (candidateMarginValue > 0 && currentMarginValue > 0) >- return std::max(candidateMarginValue, currentMarginValue); >- // Both margins are negative. >- if (candidateMarginValue < 0 && currentMarginValue < 0) >- return 0 - std::max(std::abs(candidateMarginValue.toFloat()), std::abs(currentMarginValue.toFloat())); >- // One of the margins is negative. >- return currentMarginValue + candidateMarginValue; >-} >- >-LayoutUnit BlockFormattingContext::Geometry::MarginCollapse::computedNonCollapsedMarginBefore(const LayoutState& layoutState, const Box& layoutBox) >-{ >- ASSERT(layoutBox.isBlockLevelBox()); >- >- return computedNonCollapsedVerticalMarginValue(layoutState, layoutBox).before; >-} >- >-LayoutUnit BlockFormattingContext::Geometry::MarginCollapse::computedNonCollapsedMarginAfter(const LayoutState& layoutState, const Box& layoutBox) >-{ >- ASSERT(layoutBox.isBlockLevelBox()); >- >- return computedNonCollapsedVerticalMarginValue(layoutState, layoutBox).after; >-} >- >-LayoutUnit BlockFormattingContext::Geometry::MarginCollapse::nonCollapsedMarginBefore(const LayoutState& layoutState, const Box& layoutBox) >-{ >- ASSERT(layoutBox.isBlockLevelBox()); >- >- // Non collapsed margin top includes collapsed margin from inflow first child. >- return marginValue(computedNonCollapsedMarginBefore(layoutState, layoutBox), collapsedMarginBeforeFromFirstChild(layoutState, layoutBox)); >-} >- >-LayoutUnit BlockFormattingContext::Geometry::MarginCollapse::nonCollapsedMarginAfter(const LayoutState& layoutState, const Box& layoutBox) >-{ >- ASSERT(layoutBox.isBlockLevelBox()); >- >- // Non collapsed margin bottom includes collapsed margin from inflow last child. >- return marginValue(computedNonCollapsedMarginAfter(layoutState, layoutBox), collapsedMarginAfterFromLastChild(layoutState, layoutBox)); >-} >- >-LayoutUnit BlockFormattingContext::Geometry::MarginCollapse::collapsedMarginBeforeFromFirstChild(const LayoutState& layoutState, const Box& layoutBox) >-{ >- ASSERT(layoutBox.isBlockLevelBox()); >- >- // Check if the first child collapses its margin top. >- if (!is<Container>(layoutBox) || !downcast<Container>(layoutBox).hasInFlowChild()) >- return 0; >- >- // Do not collapse margin with a box from a non-block formatting context <div><span>foobar</span></div>. >- if (layoutBox.establishesFormattingContext() && !layoutBox.establishesBlockFormattingContextOnly()) >- return 0; >- >- // FIXME: Take collapsed through margin into account. >- auto& firstInFlowChild = *downcast<Container>(layoutBox).firstInFlowChild(); >- if (!marginBeforeCollapsesWithParentMarginBefore(layoutState, firstInFlowChild)) >- return 0; >- // Collect collapsed margin top recursively. >- return marginValue(computedNonCollapsedMarginBefore(layoutState, firstInFlowChild), collapsedMarginBeforeFromFirstChild(layoutState, firstInFlowChild)); >-} >- >-LayoutUnit BlockFormattingContext::Geometry::MarginCollapse::collapsedMarginAfterFromLastChild(const LayoutState& layoutState, const Box& layoutBox) >-{ >- ASSERT(layoutBox.isBlockLevelBox()); >- >- // Check if the last child propagates its margin bottom. >- if (!is<Container>(layoutBox) || !downcast<Container>(layoutBox).hasInFlowChild()) >- return 0; >- >- // Do not collapse margin with a box from a non-block formatting context <div><span>foobar</span></div>. >- if (layoutBox.establishesFormattingContext() && !layoutBox.establishesBlockFormattingContextOnly()) >- return 0; >- >- // FIXME: Check for collapsed through margin. >- auto& lastInFlowChild = *downcast<Container>(layoutBox).lastInFlowChild(); >- if (!marginAfterCollapsesWithParentMarginAfter(layoutState, lastInFlowChild)) >- return 0; >- >- // Collect collapsed margin bottom recursively. >- return marginValue(computedNonCollapsedMarginAfter(layoutState, lastInFlowChild), collapsedMarginAfterFromLastChild(layoutState, lastInFlowChild)); >-} >- >-bool BlockFormattingContext::Geometry::MarginCollapse::marginBeforeCollapsesWithParentMarginAfter(const LayoutState& layoutState, const Box& layoutBox) >-{ >- // 1. This is the last in-flow child and its margins collapse through and the margin after collapses with parent's margin after or >- // 2. This box's margin after collapses with the next sibling's margin before and that sibling collapses through and >- // we can get to the last in-flow child like that. >- auto* lastInFlowChild = layoutBox.parent()->lastInFlowChild(); >- for (auto* currentBox = &layoutBox; currentBox; currentBox = currentBox->nextInFlowSibling()) { >- if (!marginsCollapseThrough(layoutState, *currentBox)) >- return false; >- if (currentBox == lastInFlowChild) >- return marginAfterCollapsesWithParentMarginAfter(layoutState, *currentBox); >- if (!marginAfterCollapsesWithNextSibling(*currentBox)) >- return false; >- } >- ASSERT_NOT_REACHED(); >- return false; >-} >- >-bool BlockFormattingContext::Geometry::MarginCollapse::marginBeforeCollapsesWithParentMarginBefore(const LayoutState& layoutState, const Box& layoutBox) >-{ >- // The first inflow child could propagate its top margin to parent. >- // https://www.w3.org/TR/CSS21/box.html#collapsing-margins >- if (layoutBox.isAnonymous()) >- return false; >- >- ASSERT(layoutBox.isBlockLevelBox()); >- >- // Margins between a floated box and any other box do not collapse. >- if (layoutBox.isFloatingPositioned()) >- return false; >- >- // Margins of absolutely positioned boxes do not collapse. >- if (layoutBox.isOutOfFlowPositioned()) >- return false; >- >- // Margins of inline-block boxes do not collapse. >- if (layoutBox.isInlineBlockBox()) >- return false; >- >- // Only the first inlflow child collapses with parent. >- if (layoutBox.previousInFlowSibling()) >- return false; >- >- auto& parent = *layoutBox.parent(); >- // Margins of elements that establish new block formatting contexts do not collapse with their in-flow children >- if (establishesBlockFormattingContext(parent)) >- return false; >- >- if (hasBorderBefore(parent)) >- return false; >- >- if (hasPaddingBefore(parent)) >- return false; >- >- // ...and the child has no clearance. >- if (hasClearance(layoutBox)) >- return false; >- >- if (BlockFormattingContext::Quirks::shouldIgnoreMarginBefore(layoutState, layoutBox)) >- return false; >- >- return true; >-} >- >-bool BlockFormattingContext::Geometry::MarginCollapse::marginAfterCollapsesWithSiblingMarginBeforeWithClearance(const LayoutState& layoutState, const Box& layoutBox) >-{ >- // If the top and bottom margins of an element with clearance are adjoining, its margins collapse with the adjoining margins >- // of following siblings but that resulting margin does not collapse with the bottom margin of the parent block. >- if (!marginsCollapseThrough(layoutState, layoutBox)) >- return false; >- >- for (auto* previousSibling = layoutBox.previousInFlowSibling(); previousSibling; previousSibling = previousSibling->previousInFlowSibling()) { >- if (!marginsCollapseThrough(layoutState, *previousSibling)) >- return false; >- if (hasClearance(*previousSibling)) >- return true; >- } >- return false; >-} >- >-bool BlockFormattingContext::Geometry::MarginCollapse::marginAfterCollapsesWithParentMarginBefore(const LayoutState& layoutState, const Box& layoutBox) >-{ >- // 1. This is the first in-flow child and its margins collapse through and the margin before collapses with parent's margin before or >- // 2. This box's margin before collapses with the previous sibling's margin after and that sibling collapses through and >- // we can get to the first in-flow child like that. >- auto* firstInFlowChild = layoutBox.parent()->firstInFlowChild(); >- for (auto* currentBox = &layoutBox; currentBox; currentBox = currentBox->previousInFlowSibling()) { >- if (!marginsCollapseThrough(layoutState, *currentBox)) >- return false; >- if (currentBox == firstInFlowChild) >- return marginBeforeCollapsesWithParentMarginBefore(layoutState, *currentBox); >- if (!marginBeforeCollapsesWithPreviousSibling(*currentBox)) >- return false; >- } >- ASSERT_NOT_REACHED(); >- return false; >-} >- >-bool BlockFormattingContext::Geometry::MarginCollapse::marginAfterCollapsesWithParentMarginAfter(const LayoutState& layoutState, const Box& layoutBox) >-{ >- if (layoutBox.isAnonymous()) >- return false; >- >- ASSERT(layoutBox.isBlockLevelBox()); >- >- // Margins between a floated box and any other box do not collapse. >- if (layoutBox.isFloatingPositioned()) >- return false; >- >- // Margins of absolutely positioned boxes do not collapse. >- if (layoutBox.isOutOfFlowPositioned()) >- return false; >- >- // Margins of inline-block boxes do not collapse. >- if (layoutBox.isInlineBlockBox()) >- return false; >- >- // Only the last inlflow child collapses with parent. >- if (layoutBox.nextInFlowSibling()) >- return false; >- >- auto& parent = *layoutBox.parent(); >- // Margins of elements that establish new block formatting contexts do not collapse with their in-flow children. >- if (establishesBlockFormattingContext(parent)) >- return false; >- >- // The bottom margin of an in-flow block box with a 'height' of 'auto' collapses with its last in-flow block-level child's bottom margin, if: >- if (!parent.style().height().isAuto()) >- return false; >- >- // the box has no bottom padding, and >- if (hasPaddingBefore(parent)) >- return false; >- >- // the box has no bottom border, and >- if (hasBorderBefore(parent)) >- return false; >- >- // the child's bottom margin neither collapses with a top margin that has clearance... >- if (marginAfterCollapsesWithSiblingMarginBeforeWithClearance(layoutState, layoutBox)) >- return false; >- >- // nor (if the box's min-height is non-zero) with the box's top margin. >- auto computedMinHeight = parent.style().logicalMinHeight(); >- if (!computedMinHeight.isAuto() && computedMinHeight.value() && marginAfterCollapsesWithParentMarginBefore(layoutState, layoutBox)) >- return false; >- >- return true; >-} >- >-bool BlockFormattingContext::Geometry::MarginCollapse::marginBeforeCollapsesWithPreviousSibling(const Box& layoutBox) >-{ >- ASSERT(layoutBox.isBlockLevelBox()); >- >- if (!layoutBox.previousInFlowSibling()) >- return false; >- >- auto& previousInFlowSibling = *layoutBox.previousInFlowSibling(); >- >- // Margins between a floated box and any other box do not collapse. >- if (layoutBox.isFloatingPositioned() || previousInFlowSibling.isFloatingPositioned()) >- return false; >- >- // Margins of absolutely positioned boxes do not collapse. >- if ((layoutBox.isOutOfFlowPositioned() && !layoutBox.style().top().isAuto()) >- || (previousInFlowSibling.isOutOfFlowPositioned() && !previousInFlowSibling.style().bottom().isAuto())) >- return false; >- >- // Margins of inline-block boxes do not collapse. >- if (layoutBox.isInlineBlockBox() || previousInFlowSibling.isInlineBlockBox()) >- return false; >- >- // 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. >- if (hasClearance(layoutBox)) >- return false; >- >- return true; >-} >- >-bool BlockFormattingContext::Geometry::MarginCollapse::marginAfterCollapsesWithNextSibling(const Box& layoutBox) >-{ >- ASSERT(layoutBox.isBlockLevelBox()); >- >- if (!layoutBox.nextInFlowSibling()) >- return false; >- >- return marginBeforeCollapsesWithPreviousSibling(*layoutBox.nextInFlowSibling()); >-} >- >-bool BlockFormattingContext::Geometry::MarginCollapse::marginsCollapseThrough(const LayoutState& layoutState, const Box& layoutBox) >-{ >- ASSERT(layoutBox.isBlockLevelBox()); >- >- // A box's own margins collapse if the 'min-height' property is zero, and it has neither top or bottom borders nor top or bottom padding, >- // and it has a 'height' of either 0 or 'auto', and it does not contain a line box, and all of its in-flow children's margins (if any) collapse. >- if (hasBorderBefore(layoutBox) || hasBorderAfter(layoutBox)) >- return false; >- >- if (hasPaddingBefore(layoutBox) || hasPaddingAfter(layoutBox)) >- return false; >- >- // FIXME: Check for computed 0 height. >- if (!layoutBox.style().height().isAuto()) >- return false; >- >- // FIXME: Check for computed 0 height. >- if (!layoutBox.style().minHeight().isAuto()) >- return false; >- >- if (!is<Container>(layoutBox)) >- return true; >- >- if (layoutBox.establishesInlineFormattingContext()) { >- if (downcast<InlineFormattingState>(layoutState.establishedFormattingState(layoutBox)).inlineRuns().isEmpty()) >- return false; >- } else { >- for (auto* inflowChild = downcast<Container>(layoutBox).firstInFlowChild(); inflowChild; inflowChild = inflowChild->nextInFlowSibling()) { >- if (!marginsCollapseThrough(layoutState, *inflowChild)) >- return true; >- } >- } >- >- return true; >-} >- >-LayoutUnit BlockFormattingContext::Geometry::MarginCollapse::marginBefore(const LayoutState& layoutState, const Box& layoutBox) >-{ >- if (layoutBox.isAnonymous()) >- return 0; >- >- ASSERT(layoutBox.isBlockLevelBox()); >- >- // TODO: take _hasAdjoiningMarginBeforeAndAfter() into account. >- if (marginBeforeCollapsesWithParentMarginBefore(layoutState, layoutBox)) >- return 0; >- >- // FIXME: Find out the logic behind this. >- if (BlockFormattingContext::Quirks::shouldIgnoreMarginBefore(layoutState, layoutBox)) >- return 0; >- >- if (!marginBeforeCollapsesWithPreviousSibling(layoutBox)) { >- if (!marginsCollapseThrough(layoutState, layoutBox)) >- return nonCollapsedMarginBefore(layoutState, layoutBox); >- // Compute the collapsed through value. >- auto marginBefore = nonCollapsedMarginBefore(layoutState, layoutBox); >- auto marginAfter = nonCollapsedMarginAfter(layoutState, layoutBox); >- return marginValue(marginBefore, marginAfter); >- } >- >- // 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. >- auto* previousInFlowSibling = layoutBox.previousInFlowSibling(); >- if (!previousInFlowSibling) >- return nonCollapsedMarginBefore(layoutState, layoutBox); >- >- auto previousSiblingMarginAfter = nonCollapsedMarginAfter(layoutState, *previousInFlowSibling); >- auto marginBefore = nonCollapsedMarginBefore(layoutState, layoutBox); >- return marginValue(marginBefore, previousSiblingMarginAfter); >-} >- >-LayoutUnit BlockFormattingContext::Geometry::MarginCollapse::marginAfter(const LayoutState& layoutState, const Box& layoutBox) >-{ >- if (layoutBox.isAnonymous()) >- return 0; >- >- ASSERT(layoutBox.isBlockLevelBox()); >- >- // TODO: take _hasAdjoiningMarginBeforeAndBottom() into account. >- if (marginAfterCollapsesWithParentMarginAfter(layoutState, layoutBox)) >- return 0; >- >- if (marginsCollapseThrough(layoutState, layoutBox)) >- return 0; >- >- // Floats and out of flow positioned boxes do not collapse their margins. >- if (!marginAfterCollapsesWithNextSibling(layoutBox)) >- return nonCollapsedMarginAfter(layoutState, layoutBox); >- >- // 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. >- if (layoutBox.nextInFlowSibling()) >- return 0; >- return nonCollapsedMarginAfter(layoutState, layoutBox); >-} >- >-} >-} >-#endif >diff --git a/Source/WebCore/layout/displaytree/DisplayBox.cpp b/Source/WebCore/layout/displaytree/DisplayBox.cpp >index 027b434bbc6d4c2f5510afce9c507839e649e244..6db7dedb37ac9e38fb945682969e87d6be43eede 100644 >--- a/Source/WebCore/layout/displaytree/DisplayBox.cpp >+++ b/Source/WebCore/layout/displaytree/DisplayBox.cpp >@@ -60,7 +60,7 @@ Box::Box(const Box& other) > , m_horizontalMargin(other.m_horizontalMargin) > , m_verticalMargin(other.m_verticalMargin) > , m_horizontalNonComputedMargin(other.m_horizontalNonComputedMargin) >- , m_estimatedMarginBefore(other.m_estimatedMarginBefore) >+ , m_hasClearance(other.m_hasClearance) > , m_border(other.m_border) > , m_padding(other.m_padding) > #if !ASSERT_DISABLED >@@ -74,6 +74,7 @@ Box::Box(const Box& other) > , m_hasValidPadding(other.m_hasValidPadding) > , m_hasValidContentHeight(other.m_hasValidContentHeight) > , m_hasValidContentWidth(other.m_hasValidContentWidth) >+ , m_estimatedMarginBefore(other.m_estimatedMarginBefore) > #endif > { > } >diff --git a/Source/WebCore/layout/displaytree/DisplayBox.h b/Source/WebCore/layout/displaytree/DisplayBox.h >index 56392f47ee79e30d3f0e21894d3f14bb875d7e89..5acb087ffab49204f6cb6767d157d33070999d2f 100644 >--- a/Source/WebCore/layout/displaytree/DisplayBox.h >+++ b/Source/WebCore/layout/displaytree/DisplayBox.h >@@ -136,21 +136,20 @@ public: > LayoutUnit width() const { return borderLeft() + paddingLeft().valueOr(0) + contentBoxWidth() + paddingRight().valueOr(0) + borderRight(); } > LayoutUnit height() const { return borderTop() + paddingTop().valueOr(0) + contentBoxHeight() + paddingBottom().valueOr(0) + borderBottom(); } > Rect rect() const { return { top(), left(), width(), height() }; } >- Rect rectWithMargin() const { return { top() - marginBefore(), left() - marginStart(), marginStart() + width() + marginEnd(), marginBefore() + height() + marginAfter() }; } >+ Rect rectWithMargin() const; > > Layout::VerticalMargin verticalMargin() const; > LayoutUnit marginBefore() const; > LayoutUnit marginStart() const; > LayoutUnit marginAfter() const; > LayoutUnit marginEnd() const; >+ bool hasClearance() const { return m_hasClearance; } > > LayoutUnit nonCollapsedMarginBefore() const; > LayoutUnit nonCollapsedMarginAfter() const; > LayoutUnit nonComputedMarginStart() const; > LayoutUnit nonComputedMarginEnd() const; > >- Optional<LayoutUnit> estimatedMarginBefore() const { return m_estimatedMarginBefore; } >- > LayoutUnit borderTop() const; > LayoutUnit borderLeft() const; > LayoutUnit borderBottom() const; >@@ -175,6 +174,11 @@ public: > Rect paddingBox() const; > Rect contentBox() const; > >+#if !ASSERT_DISABLED >+ void setEstimatedMarginBefore(Layout::EstimatedMarginBefore marginBefore) { m_estimatedMarginBefore = marginBefore; } >+ Optional<Layout::EstimatedMarginBefore> estimatedMarginBefore() const { return m_estimatedMarginBefore; } >+#endif >+ > private: > struct Style { > Style(const RenderStyle&); >@@ -194,7 +198,7 @@ private: > void setHorizontalMargin(Layout::HorizontalMargin); > void setVerticalMargin(Layout::VerticalMargin); > void setHorizontalNonComputedMargin(Layout::HorizontalMargin); >- void setEstimatedMarginBefore(LayoutUnit marginBefore) { m_estimatedMarginBefore = marginBefore; } >+ void setHasClearance() { m_hasClearance = true; } > > void setBorder(Layout::Edges); > void setPadding(Optional<Layout::Edges>); >@@ -203,6 +207,7 @@ private: > void invalidateMargin(); > void invalidateBorder() { m_hasValidBorder = false; } > void invalidatePadding() { m_hasValidPadding = false; } >+ void invalidateEstimatedMarginBefore() { m_estimatedMarginBefore = { }; } > > void setHasValidTop() { m_hasValidTop = true; } > void setHasValidLeft() { m_hasValidLeft = true; } >@@ -227,7 +232,7 @@ private: > Layout::HorizontalMargin m_horizontalMargin; > Layout::VerticalMargin m_verticalMargin; > Layout::HorizontalMargin m_horizontalNonComputedMargin; >- Optional<LayoutUnit> m_estimatedMarginBefore; >+ bool m_hasClearance; > > Layout::Edges m_border; > Optional<Layout::Edges> m_padding; >@@ -243,6 +248,7 @@ private: > bool m_hasValidPadding { false }; > bool m_hasValidContentHeight { false }; > bool m_hasValidContentWidth { false }; >+ Optional<Layout::EstimatedMarginBefore> m_estimatedMarginBefore; > #endif > }; > >@@ -520,8 +526,8 @@ inline void Box::setVerticalMargin(Layout::VerticalMargin margin) > #if !ASSERT_DISABLED > setHasValidVerticalMargin(); > setHasValidVerticalNonCollapsedMargin(); >+ invalidateEstimatedMarginBefore(); > #endif >- ASSERT(!m_estimatedMarginBefore || *m_estimatedMarginBefore == margin.usedValues().before); > m_verticalMargin = margin; > } > >@@ -549,6 +555,14 @@ inline void Box::setPadding(Optional<Layout::Edges> padding) > m_padding = padding; > } > >+inline Box::Rect Box::rectWithMargin() const >+{ >+ auto marginAfter = this->marginAfter(); >+ if (m_verticalMargin.collapsedValues() && m_verticalMargin.collapsedValues()->isCollapsedThrough) >+ marginAfter = 0; >+ return { top() - marginBefore(), left() - marginStart(), marginStart() + width() + marginEnd(), marginBefore() + height() + marginAfter }; >+} >+ > inline Layout::VerticalMargin Box::verticalMargin() const > { > ASSERT(m_hasValidVerticalMargin); >diff --git a/Source/WebCore/layout/floats/FloatingContext.cpp b/Source/WebCore/layout/floats/FloatingContext.cpp >index 71fc0606522780dbad23a98f5994a8538ca32e39..fcdb5077e6cd8f533bcafbd111a7c80254579b88 100644 >--- a/Source/WebCore/layout/floats/FloatingContext.cpp >+++ b/Source/WebCore/layout/floats/FloatingContext.cpp >@@ -183,34 +183,32 @@ Optional<Position> FloatingContext::verticalPositionWithClearance(const Box& lay > if (clearance <= 0) > return { }; > >+ displayBox.setHasClearance(); > // Clearance inhibits margin collapsing. Let's reset the relevant adjoining margins. > if (auto* previousInFlowSibling = layoutBox.previousInFlowSibling()) { > auto& previousInFlowDisplayBox = layoutState.displayBoxForLayoutBox(*previousInFlowSibling); >+ // Does this box with clearance actually collapse its margin before with the previous inflow box's margin after? >+ auto verticalMargin = displayBox.verticalMargin(); >+ if (verticalMargin.collapsedValues() && verticalMargin.collapsedValues()->before) { >+ // Reset previous bottom after and current margin before to non-collapsing. >+ auto previousVerticalMargin = previousInFlowDisplayBox.verticalMargin(); >+ ASSERT(previousVerticalMargin.collapsedValues() && previousVerticalMargin.collapsedValues()->after); > >- // Since the previous inflow sibling has already been laid out, its margin is collapsed by now. >- ASSERT(!previousInFlowDisplayBox.marginAfter()); >- auto collapsedMargin = displayBox.marginBefore(); >- >- // Reset previous bottom and current top margins to non-collapsing. >- auto previousVerticalMargin = previousInFlowDisplayBox.verticalMargin(); >- if (previousVerticalMargin.collapsedValues() && previousVerticalMargin.collapsedValues()->after) { >+ auto collapsedMargin = *verticalMargin.collapsedValues()->before; > previousVerticalMargin.setCollapsedValues({ previousVerticalMargin.collapsedValues()->before, { } }); > previousInFlowDisplayBox.setVerticalMargin(previousVerticalMargin); >- } >- // FIXME: check if collapsing through has anything to do with this. >- auto verticalMargin = displayBox.verticalMargin(); >- if (verticalMargin.collapsedValues() && verticalMargin.collapsedValues()->before) { >+ > verticalMargin.setCollapsedValues({ { }, verticalMargin.collapsedValues()->after }); > displayBox.setVerticalMargin(verticalMargin); >- } > >- auto nonCollapsedMargin = previousInFlowDisplayBox.marginAfter() + displayBox.marginBefore(); >- auto marginOffset = nonCollapsedMargin - collapsedMargin; >- // Move the box to the position where it would be with non-collapsed margins. >- rootRelativeTop += marginOffset; >+ auto nonCollapsedMargin = previousVerticalMargin.usedValues().after + verticalMargin.usedValues().before; >+ auto marginDifference = nonCollapsedMargin - collapsedMargin; >+ // Move the box to the position where it would be with non-collapsed margins. >+ rootRelativeTop += marginDifference; > >- // Having negative clearance is also normal. It just means that the box with the non-collapsed margins is now lower than it needs to be. >- clearance -= marginOffset; >+ // Having negative clearance is also normal. It just means that the box with the non-collapsed margins is now lower than it needs to be. >+ clearance -= marginDifference; >+ } > } > // Now adjust the box's position with the clearance. > rootRelativeTop += clearance; >diff --git a/Tools/ChangeLog b/Tools/ChangeLog >index 8dcee1e52700fae0a737c5008d5a85f0f1a8f060..c6d38d6b73757239c3a55f81a36864e6bab3b85b 100644 >--- a/Tools/ChangeLog >+++ b/Tools/ChangeLog >@@ -1,3 +1,12 @@ >+2018-12-29 Zalan Bujtas <zalan@apple.com> >+ >+ [LFC][BFC][MarginCollapsing] Add support for peculiar cases. >+ https://bugs.webkit.org/show_bug.cgi?id=192625 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * LayoutReloaded/misc/LFC-passing-tests.txt: >+ > 2018-12-22 Carlos Garcia Campos <cgarcia@igalia.com> > > WebDriver: warn about non existing tests when parsing expectations >diff --git a/Tools/LayoutReloaded/misc/LFC-passing-tests.txt b/Tools/LayoutReloaded/misc/LFC-passing-tests.txt >index ff5eb38154b72ef8c8817fb2945f350ebb5d1012..225b7475da83aa5caae191ea591aa6251e69cf68 100644 >--- a/Tools/LayoutReloaded/misc/LFC-passing-tests.txt >+++ b/Tools/LayoutReloaded/misc/LFC-passing-tests.txt >@@ -4,23 +4,66 @@ fast/block/block-only/absolute-left-auto.html > fast/block/block-only/absolute-left-right-top-bottom-auto.html > fast/block/block-only/absolute-nested2.html > fast/block/block-only/absolute-nested.html >+fast/block/block-only/absolute-position-min-max-height.html >+fast/block/block-only/absolute-position-min-max-width.html >+fast/block/block-only/absolute-position-when-containing-block-is-not-in-the-formatting-context2.html > fast/block/block-only/absolute-position-when-containing-block-is-not-in-the-formatting-context.html > fast/block/block-only/absolute-simple.html > fast/block/block-only/absolute-width-shrink-to-fit.html > fast/block/block-only/absolute-width-stretch.html > fast/block/block-only/absolute-with-static-block-position-nested.html >+fast/block/block-only/almost-intruding-left-float-simple.html >+fast/block/block-only/body-height-with-auto-html-height-quirk2.html >+fast/block/block-only/body-height-with-auto-html-height-quirk.html >+fast/block/block-only/body-height-with-non-auto-html-height-quirk2.html >+fast/block/block-only/body-height-with-non-auto-html-height-quirk.html > fast/block/block-only/border-simple.html >+fast/block/block-only/collapsed-margin-with-min-height.html > fast/block/block-only/fixed-nested.html >+fast/block/block-only/float-and-siblings-with-margins.html >+fast/block/block-only/float-avoider-multiple-roots.html >+fast/block/block-only/float-avoider-simple-left.html >+fast/block/block-only/float-avoider-simple-right.html >+fast/block/block-only/float-avoider-with-margins.html >+fast/block/block-only/float-left-when-container-has-padding-margin.html >+fast/block/block-only/float-min-max-height.html >+fast/block/block-only/float-min-max-width.html >+fast/block/block-only/floating-and-next-previous-inflow-with-margin-with-no-border.html >+fast/block/block-only/floating-and-next-previous-inflow-with-margin.html >+fast/block/block-only/floating-box-clear-both-simple.html >+fast/block/block-only/floating-box-clear-right-simple.html >+fast/block/block-only/floating-box-left-and-right-multiple-with-top-offset.html >+fast/block/block-only/floating-box-left-and-right-multiple.html >+fast/block/block-only/floating-box-right-simple.html >+fast/block/block-only/floating-box-with-clear-siblings.html >+fast/block/block-only/floating-box-with-clear-simple.html >+fast/block/block-only/floating-box-with-new-formatting-context.html >+fast/block/block-only/floating-box-with-relative-positioned-sibling.html >+fast/block/block-only/floating-left-and-right-with-clearance.html >+fast/block/block-only/floating-left-right-simple.html >+fast/block/block-only/floating-left-right-with-all-margins.html >+fast/block/block-only/floating-lefts-and-rights-simple.html >+fast/block/block-only/floating-multiple-lefts-in-body.html >+fast/block/block-only/floating-multiple-lefts-multiple-lines.html >+fast/block/block-only/floating-multiple-lefts.html >+fast/block/block-only/floating-with-new-block-formatting-context.html >+fast/block/block-only/inflow-min-max-height.html >+fast/block/block-only/inflow-min-max-width.html > fast/block/block-only/margin-collapse-bottom-bottom.html > fast/block/block-only/margin-collapse-bottom-nested.html >+fast/block/block-only/margin-collapse-first-last-are-floating.html > fast/block/block-only/margin-collapse-simple.html > fast/block/block-only/margin-collapse-top-nested.html > fast/block/block-only/margin-collapse-when-child-has-padding-border.html >+fast/block/block-only/margin-collapse-with-block-formatting-context2.html >+fast/block/block-only/margin-collapse-with-block-formatting-context.html >+fast/block/block-only/margin-collapse-with-clearance.html > fast/block/block-only/margin-left-right-sizing-out-of-flow.html > fast/block/block-only/margin-left-right-sizing.html > fast/block/block-only/margin-propagation-simple-content-height.html > fast/block/block-only/margin-sibling-collapse-propagated.html > fast/block/block-only/margin-simple.html >+fast/block/block-only/min-max-height-percentage.html > fast/block/block-only/negative-margin-simple.html > fast/block/block-only/padding-nested.html > fast/block/block-only/padding-simple.html >@@ -31,80 +74,49 @@ fast/block/block-only/relative-position-when-containing-block-is-not-in-the-form > fast/block/block-only/relative-right.html > fast/block/block-only/relative-siblings.html > fast/block/block-only/relative-simple.html >-fast/block/block-only/absolute-position-when-containing-block-is-not-in-the-formatting-context2.html >-fast/block/block-only/margin-collapse-with-block-formatting-context.html >-fast/block/block-only/margin-collapse-with-block-formatting-context2.html >-fast/block/block-only/float-left-when-container-has-padding-margin.html >-fast/block/block-only/floating-box-left-and-right-multiple-with-top-offset.html >-fast/block/block-only/floating-box-left-and-right-multiple.html >-fast/block/block-only/floating-box-right-simple.html >-fast/block/block-only/floating-box-with-new-formatting-context.html >-fast/block/block-only/floating-box-with-relative-positioned-sibling.html >-fast/block/block-only/floating-left-right-simple.html >-fast/block/block-only/floating-left-right-with-all-margins.html >-fast/block/block-only/floating-lefts-and-rights-simple.html >-fast/block/block-only/floating-multiple-lefts-in-body.html >-fast/block/block-only/floating-multiple-lefts-multiple-lines.html >-fast/block/block-only/floating-multiple-lefts.html >-fast/block/block-only/floating-and-next-previous-inflow-with-margin.html >-fast/block/block-only/floating-and-next-previous-inflow-with-margin-with-no-border.html >-fast/block/block-only/floating-left-and-right-with-clearance.html >-fast/block/block-only/float-and-siblings-with-margins.html >-fast/block/block-only/margin-collapse-with-clearance.html >-fast/block/block-only/float-avoider-simple-left.html >-fast/block/block-only/float-avoider-simple-right.html >-fast/block/block-only/float-avoider-multiple-roots.html >-fast/block/block-only/float-avoider-with-margins.html >-fast/block/block-only/inflow-min-max-width.html >-fast/block/block-only/absolute-position-min-max-width.html >-fast/block/block-only/float-min-max-width.html >-fast/block/block-only/inflow-min-max-height.html >-fast/block/block-only/absolute-position-min-max-height.html >-fast/block/block-only/float-min-max-height.html >-fast/block/block-only/min-max-height-percentage.html >-fast/block/block-only/body-height-with-non-auto-html-height-quirk.html >-fast/block/block-only/body-height-with-non-auto-html-height-quirk2.html >-fast/block/block-only/body-height-with-auto-html-height-quirk.html >-fast/block/block-only/body-height-with-auto-html-height-quirk2.html >-fast/block/block-only/collapsed-margin-with-min-height.html >+fast/block/basic/002.html >+fast/block/basic/003.html >+fast/block/basic/006.html >+fast/block/basic/007.html >+fast/block/basic/008.html >+fast/block/basic/009.html >+fast/block/basic/012.html >+fast/block/basic/child-block-level-box-with-height-percent.html >+fast/block/basic/height-percentage-simple.html > fast/block/basic/inline-content-with-floating-image.html > 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 >-fast/inline/simple-shrink-to-fit-inline-block.html >-fast/inline/simple-inline-inflow-positioned.html >-fast/inline/simple-inline-with-out-of-flow-descendant.html >-fast/inline/simple-inline-with-out-of-flow-descendant2.html >-fast/inline/inline-content-with-padding-left-right.html >-fast/inline/inline-content-with-border-left-right.html >-fast/inline/inline-content-with-margin-left-right.html >-fast/inline/inline-content-and-nested-formatting-root-with-margin-left-right.html >-fast/inline/inline-content-with-image-simple.html >-fast/inline/inline-content-with-float-and-margin.html >-fast/block/basic/height-percentage-simple.html >-fast/block/basic/child-block-level-box-with-height-percent.html >+fast/block/basic/percent-height-inside-anonymous-block.html > fast/block/basic/quirk-mode-percent-height.html >+fast/block/basic/quirk-percent-height-grandchild.html > fast/block/float/001.html > fast/block/float/007.html > fast/block/float/008.html > fast/block/float/009.html > fast/block/float/013.html > fast/block/float/019.html >-fast/block/basic/002.html >-fast/block/basic/003.html >-fast/block/basic/006.html >-fast/block/basic/007.html >-fast/block/basic/008.html >-fast/block/basic/009.html >-fast/block/basic/012.html >+fast/block/float/negative-margin-clear.html >+fast/block/float/overhanging-after-height-decrease-offsets.html >+fast/block/float/overhanging-after-height-decrease.html >+fast/block/float/overlapping-floats-with-overflow-hidden.html >+fast/block/float/previous-sibling-abspos-002.html >+fast/block/float/relative-painted-twice.html >+fast/block/float/avoidance-rtl.html >+fast/block/float/br-with-clear.html >+fast/block/float/clamped-right-float.html >+fast/block/float/float-on-zero-height-line.html >+fast/block/float/float-overhangs-root.html >+fast/block/float/float-with-anonymous-previous-sibling.html >+fast/block/float/floats-not-cleared-crash.html > fast/block/margin-collapse/002.html > fast/block/margin-collapse/003.html > fast/block/margin-collapse/026.html > fast/block/margin-collapse/027.html >+fast/block/margin-collapse/028.html >+fast/block/margin-collapse/029.html >+fast/block/margin-collapse/035.html > fast/block/margin-collapse/039.html > fast/block/margin-collapse/040.html >+fast/block/positioning/003.html > fast/block/positioning/004.html > fast/block/positioning/005.html > fast/block/positioning/006.html >@@ -145,8 +157,29 @@ fast/block/positioning/046.html > fast/block/positioning/049.html > fast/block/positioning/052.html > fast/block/positioning/054.html >+fast/block/positioning/060.html >+fast/block/positioning/absolute-positioning-no-scrollbar.html >+fast/block/positioning/change-containing-block-for-absolute-positioned.html >+fast/block/positioning/change-containing-block-for-fixed-positioned.html >+fast/block/positioning/complex-positioned-movement.html >+fast/block/positioning/fixed-position-detached-frame.html >+fast/block/positioning/fixed-position-stacking-context2.html >+fast/block/positioning/fixed-position-stacking-context.html >+fast/block/positioning/hiding-inside-relpositioned-inline.html >+fast/block/positioning/insert-positioned-in-anonymous-crash.html >+fast/block/positioning/leftmargin-topmargin.html >+fast/block/positioning/negative-rel-position.html >+fast/block/positioning/abs-inside-inline-rel.html >+fast/block/positioning/pref-width-change.html >+fast/block/positioning/relative-overflow-replaced-float.html >+fast/block/positioning/static-inline-position-dynamic.html > fast/block/inside-inlines/basic-float-intrusion.html > fast/block/inside-inlines/crash-on-first-line-change.html >+fast/block/lineboxcontain/replaced.html >+fast/block/collapse-anon-block-with-float-siblings-only.html >+fast/block/crash-when-anonymous-blocks-are-merged-with-simple-line-layout.html >+fast/block/crash-when-subtree-is-still-attached.html >+fast/block/geometry-map-assertion-with-tall-content.html > fast/borders/0px-borders-no-line-height.html > fast/borders/0px-borders.html > fast/borders/block-mask-overlay-image-outset.html >@@ -156,11 +189,8 @@ fast/borders/border-image-scaled-gradient.html > fast/borders/border-image-slice-omission.html > fast/borders/border-left-right-same-bottom-different-color.html > fast/borders/border-painting-dashed-at-all.html >-fast/borders/border-painting-dashed.html > fast/borders/border-painting-dotted-at-all.html >-fast/borders/border-painting-dotted.html > fast/borders/border-painting-double-at-all.html >-fast/borders/border-painting-double.html > fast/borders/border-painting-groove-at-all.html > fast/borders/border-painting-inset-at-all.html > fast/borders/border-painting-inset.html >@@ -169,4 +199,86 @@ fast/borders/border-painting-outset.html > fast/borders/border-painting-ridge-at-all.html > fast/borders/border-painting-solid-at-all.html > fast/borders/border-painting-solid.html >-fast/inline-block/004.html >+fast/borders/border-radius-inset-outset.html >+fast/borders/border-radius-on-html.html >+fast/borders/border-radius-on-subpixel-position-non-hidpi.html >+fast/borders/border-radius-percent.html >+fast/borders/border-radius-valid-border-clipping.html >+fast/borders/border-radius-wide-border-01.html >+fast/borders/border-radius-with-box-shadow-01.html >+fast/borders/border-radius-with-box-shadow.html >+fast/borders/border-shadow-large-radius.html >+fast/borders/borderRadiusAllStylesAllCorners.html >+fast/borders/borderRadiusArcs01.html >+fast/borders/borderRadiusDashed01.html >+fast/borders/borderRadiusDashed02.html >+fast/borders/borderRadiusDashed03.html >+fast/borders/borderRadiusDotted01.html >+fast/borders/borderRadiusDotted02.html >+fast/borders/borderRadiusDotted03.html >+fast/borders/borderRadiusDouble01.html >+fast/borders/borderRadiusDouble02.html >+fast/borders/borderRadiusDouble03.html >+fast/borders/borderRadiusGroove01.html >+fast/borders/borderRadiusGroove02.html >+fast/borders/borderRadiusInset01.html >+fast/borders/borderRadiusInvalidColor.html >+fast/borders/borderRadiusOutset01.html >+fast/borders/borderRadiusRidge01.html >+fast/borders/borderRadiusSolid01.html >+fast/borders/borderRadiusSolid02.html >+fast/borders/borderRadiusSolid03.html >+fast/borders/borderRadiusSolid04.html >+fast/borders/dashed-border-on-subpixel-position.html >+fast/borders/dotted-border-on-subpixel-position.html >+fast/borders/double-1px-border-assert.html >+fast/borders/empty-drawrect-assert-after-pixelsnap.html >+fast/borders/empty-outline-border-assert.html >+fast/borders/hidpi-3x-input-hairline-border.html >+fast/borders/hidpi-border-clipping-right-after-move.html >+fast/borders/hidpi-border-painting-groove.html >+fast/borders/hidpi-border-painting-ridge.html >+fast/borders/hidpi-border-radius-outer-border-goes-rectangle.html >+fast/borders/hidpi-border-radius-with-subpixel-margin-not-renderable.html >+fast/borders/hidpi-border-width-flooring.html >+fast/borders/hidpi-outline-hairline-painting.html >+fast/borders/hidpi-outline-on-subpixel-position.html >+fast/borders/hidpi-rounded-border-on-subpixel-position.html >+fast/borders/hidpi-simple-hairline-border-painting.html >+fast/borders/mixed-border-style2.html >+fast/borders/negative-border-width.html >+fast/borders/outline-offset-min-assert.html >+fast/borders/outline-offset-overflow.html >+fast/borders/webkit-border-radius.html >+fast/inline/absolute-positioned-block-in-centred-block.html >+fast/inline/absolute-positioned-inline-in-centred-block.html >+fast/inline/anonymous-block-with-empty-inline.html >+fast/inline/hidpi-outline-auto-negative-offset-with-border-radius.html >+fast/inline/hidpi-outline-auto-with-fractional-radius.html >+fast/inline/hidpi-outline-auto-with-one-focusring-rect.html >+fast/inline/hidpi-pixel-gap-between-adjacent-selection-inlines.html >+fast/inline/hidpi-select-inline-on-subpixel-position.html >+fast/inline/hidpi-selection-gap-on-subpixel-position.html >+fast/inline/hidpi-selection-gap-overlaps-inline-selection.html >+fast/inline/inline-body-with-scrollbar-crash.html >+fast/inline/inline-child-height-width-calc-crash.html >+fast/inline/inline-content-with-border-left-right.html >+fast/inline/inline-content-with-float-and-margin.html >+fast/inline/inline-content-with-image-simple.html >+fast/inline/inline-content-with-margin-left-right.html >+fast/inline/inline-content-with-padding-left-right.html >+fast/inline/inline-marquee-crash.html >+fast/inline/inline-padding-disables-text-quirk.html >+fast/inline/new-float-needs-layout-when-line-is-dirty.html >+fast/inline/percentage-margins.html >+fast/inline/simple-inline-block.html >+fast/inline/simple-inline-inflow-positioned.html >+fast/inline/simple-inline-with-out-of-flow-descendant2.html >+fast/inline/simple-inline-with-out-of-flow-descendant.html >+fast/inline/simple-intruding-float1.html >+fast/inline/simple-intruding-floats2.html >+fast/inline/simple-intruding-floats3.html >+fast/inline/simple-line-layout-16bit-content.html >+fast/inline/simple-shrink-to-fit-inline-block.html >+fast/inline/skipped-whitespace-boundingBox.html >+fast/inline/skipped-whitespace-client-rect.html
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 192625
:
357130
|
357423
|
358137
|
358138
|
358142
|
358143
|
358144
|
358455
|
358479
|
358589
|
358670