WebKit Bugzilla
Attachment 338898 Details for
Bug 185036
: [LFC] Implement BlockMarginCollapse functions.
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-185036-20180426113337.patch (text/plain), 11.92 KB, created by
zalan
on 2018-04-26 11:33:38 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
zalan
Created:
2018-04-26 11:33:38 PDT
Size:
11.92 KB
patch
obsolete
>Subversion Revision: 231038 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index af46292fc656ab02433503336226c32a680599eb..e5d2df88adc783565b3e029d631653b34ebe45c6 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,28 @@ >+2018-04-26 Zalan Bujtas <zalan@apple.com> >+ >+ [LFC] Implement BlockMarginCollapse functions. >+ https://bugs.webkit.org/show_bug.cgi?id=185036 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * layout/blockformatting/BlockMarginCollapse.cpp: >+ (WebCore::Layout::marginValue): >+ (WebCore::Layout::BlockMarginCollapse::BlockMarginCollapse): >+ (WebCore::Layout::BlockMarginCollapse::marginTop const): >+ (WebCore::Layout::BlockMarginCollapse::marginBottom const): >+ (WebCore::Layout::BlockMarginCollapse::isMarginTopCollapsedWithSibling const): >+ (WebCore::Layout::BlockMarginCollapse::isMarginBottomCollapsedWithSibling const): >+ (WebCore::Layout::BlockMarginCollapse::isMarginTopCollapsedWithParent const): >+ (WebCore::Layout::BlockMarginCollapse::isMarginBottomCollapsedWithParent const): >+ (WebCore::Layout::BlockMarginCollapse::nonCollapsedMarginTop const): >+ (WebCore::Layout::BlockMarginCollapse::nonCollapsedMarginBottom const): >+ (WebCore::Layout::BlockMarginCollapse::collapsedMarginTopFromFirstChild const): >+ (WebCore::Layout::BlockMarginCollapse::collapsedMarginBottomFromLastChild const): >+ (WebCore::Layout::BlockMarginCollapse::hasAdjoiningMarginTopAndBottom const): >+ * layout/blockformatting/BlockMarginCollapse.h: >+ * layout/layouttree/LayoutBox.h: >+ (WebCore::Layout::Box::style const): >+ > 2018-04-25 Zalan Bujtas <zalan@apple.com> > > [LFC] Add support for is<> and downcast<> >diff --git a/Source/WebCore/layout/blockformatting/BlockMarginCollapse.cpp b/Source/WebCore/layout/blockformatting/BlockMarginCollapse.cpp >index f9ab0fbc665166635e7e5915b41d8b5cd8285dcf..bd4046cdc773db4b75f17ce6fc9a52ed8caab39a 100644 >--- a/Source/WebCore/layout/blockformatting/BlockMarginCollapse.cpp >+++ b/Source/WebCore/layout/blockformatting/BlockMarginCollapse.cpp >@@ -25,3 +25,234 @@ > > #include "config.h" > #include "BlockMarginCollapse.h" >+ >+#if ENABLE(LAYOUT_FORMATTING_CONTEXT) >+ >+#include "LayoutBox.h" >+#include "LayoutContainer.h" >+#include "LayoutUnit.h" >+#include "RenderStyle.h" >+#include <wtf/IsoMallocInlines.h> >+ >+namespace WebCore { >+namespace Layout { >+ >+WTF_MAKE_ISO_ALLOCATED_IMPL(BlockMarginCollapse); >+ >+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; >+} >+ >+BlockMarginCollapse::BlockMarginCollapse() >+{ >+} >+ >+LayoutUnit BlockMarginCollapse::marginTop(const Box& layoutBox) const >+{ >+ if (layoutBox.isAnonymous()) >+ return 0; >+ >+ // TODO: take _hasAdjoiningMarginTopAndBottom() into account. >+ if (isMarginTopCollapsedWithParent(layoutBox)) >+ return 0; >+ >+ // Floats and out of flow positioned boxes do not collapse their margins. >+ if (!isMarginTopCollapsedWithSibling(layoutBox)) >+ return nonCollapsedMarginTop(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. >+ auto* previousInFlowSibling = layoutBox.previousInFlowSibling(); >+ if (!previousInFlowSibling) >+ return nonCollapsedMarginTop(layoutBox); >+ >+ auto previousSiblingMarginBottom = nonCollapsedMarginBottom(*previousInFlowSibling); >+ auto marginTop = nonCollapsedMarginTop(layoutBox); >+ return marginValue(marginTop, previousSiblingMarginBottom); >+} >+ >+LayoutUnit BlockMarginCollapse::marginBottom(const Box& layoutBox) const >+{ >+ if (layoutBox.isAnonymous()) >+ return 0; >+ >+ // TODO: take _hasAdjoiningMarginTopAndBottom() into account. >+ if (isMarginBottomCollapsedWithParent(layoutBox)) >+ return 0; >+ >+ // Floats and out of flow positioned boxes do not collapse their margins. >+ if (!isMarginBottomCollapsedWithSibling(layoutBox)) >+ return nonCollapsedMarginBottom(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 nonCollapsedMarginBottom(layoutBox); >+} >+ >+bool BlockMarginCollapse::isMarginTopCollapsedWithSibling(const Box& layoutBox) const >+{ >+ if (layoutBox.isFloatingPositioned()) >+ return false; >+ >+ if (!layoutBox.isPositioned() || layoutBox.isInFlowPositioned()) >+ return true; >+ >+ // Out of flow positioned. >+ ASSERT(layoutBox.isOutOfFlowPositioned()); >+ return layoutBox.style().top().isAuto(); >+} >+ >+bool BlockMarginCollapse::isMarginBottomCollapsedWithSibling(const Box& layoutBox) const >+{ >+ if (layoutBox.isFloatingPositioned()) >+ return false; >+ >+ if (!layoutBox.isPositioned() || layoutBox.isInFlowPositioned()) >+ return true; >+ >+ // Out of flow positioned. >+ ASSERT(layoutBox.isOutOfFlowPositioned()); >+ return layoutBox.style().bottom().isAuto(); >+} >+ >+bool BlockMarginCollapse::isMarginTopCollapsedWithParent(const Box& layoutBox) const >+{ >+ // 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; >+ >+ if (layoutBox.isFloatingOrOutOfFlowPositioned()) >+ return false; >+ >+ // We never margin collapse the initial containing block. >+ ASSERT(layoutBox.parent()); >+ auto& parent = *layoutBox.parent(); >+ // Is this box the first inlflow child? >+ if (parent.firstInFlowChild() != &layoutBox) >+ return false; >+ >+ if (parent.establishesBlockFormattingContext()) >+ return false; >+ >+ // Margins of the root element's box do not collapse. >+ if (parent.isInitialContainingBlock()) >+ return false; >+ >+ if (!parent.style().borderTop().nonZero()) >+ return false; >+ >+ if (!parent.style().paddingTop().isZero()) >+ return false; >+ >+ return true; >+} >+ >+bool BlockMarginCollapse::isMarginBottomCollapsedWithParent(const Box& layoutBox) const >+{ >+ // last inflow box to parent. >+ // https://www.w3.org/TR/CSS21/box.html#collapsing-margins >+ if (layoutBox.isAnonymous()) >+ return false; >+ >+ if (layoutBox.isFloatingOrOutOfFlowPositioned()) >+ return false; >+ >+ // We never margin collapse the initial containing block. >+ ASSERT(layoutBox.parent()); >+ auto& parent = *layoutBox.parent(); >+ // Is this the last inlflow child? >+ if (parent.lastInFlowChild() != &layoutBox) >+ return false; >+ >+ if (parent.establishesBlockFormattingContext()) >+ return false; >+ >+ // Margins of the root element's box do not collapse. >+ if (parent.isInitialContainingBlock()) >+ return false; >+ >+ if (!parent.style().borderTop().nonZero()) >+ return false; >+ >+ if (!parent.style().paddingTop().isZero()) >+ return false; >+ >+ if (!parent.style().height().isAuto()) >+ return false; >+ >+ return true; >+} >+ >+LayoutUnit BlockMarginCollapse::nonCollapsedMarginTop(const Box& layoutBox) const >+{ >+ // Non collapsed margin top includes collapsed margin from inflow first child. >+ return marginValue(layoutBox.style().marginTop().value(), collapsedMarginTopFromFirstChild(layoutBox)); >+} >+ >+LayoutUnit BlockMarginCollapse::nonCollapsedMarginBottom(const Box& layoutBox) const >+{ >+ // Non collapsed margin bottom includes collapsed margin from inflow last child. >+ return marginValue(layoutBox.style().marginBottom().value(), collapsedMarginBottomFromLastChild(layoutBox)); >+} >+ >+LayoutUnit BlockMarginCollapse::collapsedMarginTopFromFirstChild(const Box& layoutBox) const >+{ >+ // Check if the first child collapses its margin top. >+ if (!is<Container>(layoutBox) || !downcast<Container>(layoutBox).hasInFlowChild()) >+ return 0; >+ >+ auto& firstInFlowChild = *downcast<Container>(layoutBox).firstInFlowChild(); >+ if (!isMarginTopCollapsedWithParent(firstInFlowChild)) >+ return 0; >+ >+ // Collect collapsed margin top recursively. >+ return marginValue(firstInFlowChild.style().marginTop().value(), collapsedMarginTopFromFirstChild(firstInFlowChild)); >+} >+ >+LayoutUnit BlockMarginCollapse::collapsedMarginBottomFromLastChild(const Box& layoutBox) const >+{ >+ // Check if the last child propagates its margin bottom. >+ if (!is<Container>(layoutBox) || !downcast<Container>(layoutBox).hasInFlowChild()) >+ return 0; >+ >+ auto& lastInFlowChild = *downcast<Container>(layoutBox).lastInFlowChild(); >+ if (!isMarginBottomCollapsedWithParent(lastInFlowChild)) >+ return 0; >+ >+ // Collect collapsed margin bottom recursively. >+ return marginValue(lastInFlowChild.style().marginBottom().value(), collapsedMarginBottomFromLastChild(lastInFlowChild)); >+} >+ >+bool BlockMarginCollapse::hasAdjoiningMarginTopAndBottom(const Box&) const >+{ >+ // Two margins are adjoining if and only if: >+ // 1. both belong to in-flow block-level boxes that participate in the same block formatting context >+ // 2. no line boxes, no clearance, no padding and no border separate them (Note that certain zero-height line boxes (see 9.4.2) are ignored for this purpose.) >+ // 3. both belong to vertically-adjacent box edges, i.e. form one of the following pairs: >+ // top margin of a box and top margin of its first in-flow child >+ // bottom margin of box and top margin of its next in-flow following sibling >+ // bottom margin of a last in-flow child and bottom margin of its parent if the parent has 'auto' computed height >+ // top and bottom margins of a box that does not establish a new block formatting context and that has zero computed 'min-height', >+ // zero or 'auto' computed 'height', and no in-flow children >+ // A collapsed margin is considered adjoining to another margin if any of its component margins is adjoining to that margin. >+ return false; >+} >+ >+} >+} >+#endif >diff --git a/Source/WebCore/layout/blockformatting/BlockMarginCollapse.h b/Source/WebCore/layout/blockformatting/BlockMarginCollapse.h >index b20fab8198e0cc071c392e5277892672a99a547d..8dd229c91c9e0857f683e1a21a0407e484ba1e28 100644 >--- a/Source/WebCore/layout/blockformatting/BlockMarginCollapse.h >+++ b/Source/WebCore/layout/blockformatting/BlockMarginCollapse.h >@@ -55,7 +55,6 @@ private: > LayoutUnit nonCollapsedMarginBottom(const Box&) const; > LayoutUnit collapsedMarginTopFromFirstChild(const Box&) const; > LayoutUnit collapsedMarginBottomFromLastChild(const Box&) const; >- LayoutUnit marginValue(LayoutUnit currentMarginValue, LayoutUnit candidateMarginValue) const; > > bool hasAdjoiningMarginTopAndBottom(const Box&) const; > }; >diff --git a/Source/WebCore/layout/layouttree/LayoutBox.h b/Source/WebCore/layout/layouttree/LayoutBox.h >index d3124a5747e95db00390ed63adfd06151d9e3cb7..d8fdb76f216a0abb2d42e4b4c89af6d5ba9b1902 100644 >--- a/Source/WebCore/layout/layouttree/LayoutBox.h >+++ b/Source/WebCore/layout/layouttree/LayoutBox.h >@@ -87,6 +87,7 @@ public: > bool isInlineBox() const { return m_baseTypeFlags & InlineBoxFlag; } > bool isInlineContainer() const { return m_baseTypeFlags & InlineContainerFlag; } > >+ const RenderStyle& style() const { return m_style; } > auto& weakPtrFactory() const { return m_weakFactory; } > > protected:
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 185036
: 338898