WebKit Bugzilla
Attachment 346991 Details for
Bug 188492
: [LFC][Floating] Add basic clearance support
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-188492-20180812162511.patch (text/plain), 19.58 KB, created by
zalan
on 2018-08-12 16:25:12 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
zalan
Created:
2018-08-12 16:25:12 PDT
Size:
19.58 KB
patch
obsolete
>Subversion Revision: 234786 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index 3aee6be28631e84216016f833dc72dfc3e4f30ab..1f1f954752400dea8cfa30057356fc681b53ffbd 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,38 @@ >+2018-08-12 Zalan Bujtas <zalan@apple.com> >+ >+ [LFC][Floating] Add basic clearance support >+ https://bugs.webkit.org/show_bug.cgi?id=188492 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ Adjust final position of a block level box with clearance when float is present. >+ >+ Test: fast/block/block-only/floating-left-and-right-with-clearance.html >+ >+ * layout/FloatingContext.cpp: >+ (WebCore::Layout::FloatingContext::positionForFloat const): >+ (WebCore::Layout::FloatingContext::verticalPositionWithClearance const): >+ (WebCore::Layout::FloatingContext::alignWithContainingBlock const): >+ (WebCore::Layout::FloatingContext::toContainingBlock const): >+ (WebCore::Layout::FloatingContext::computePosition const): Deleted. >+ * layout/FloatingContext.h: >+ * layout/FloatingState.cpp: >+ (WebCore::Layout::FloatingState::bottom const): >+ * layout/FloatingState.h: >+ (WebCore::Layout::FloatingState::leftBottom const): >+ (WebCore::Layout::FloatingState::rightBottom const): >+ (WebCore::Layout::FloatingState::bottom const): >+ * layout/Verification.cpp: >+ (WebCore::Layout::LayoutContext::verifyAndOutputMismatchingLayoutTree const): >+ * layout/blockformatting/BlockFormattingContext.cpp: >+ (WebCore::Layout::BlockFormattingContext::layout const): >+ (WebCore::Layout::BlockFormattingContext::computeFloatingPosition const): >+ (WebCore::Layout::BlockFormattingContext::computeVerticalPositionWithClearance const): >+ * layout/blockformatting/BlockFormattingContext.h: >+ * layout/layouttree/LayoutBox.cpp: >+ (WebCore::Layout::Box::hasClearance const): >+ * layout/layouttree/LayoutBox.h: >+ > 2018-08-12 Zalan Bujtas <zalan@apple.com> > > [LFC] Float prev/next sibling should prevent top/bottom margin collapsing with parent. >diff --git a/Source/WebCore/layout/FloatingContext.cpp b/Source/WebCore/layout/FloatingContext.cpp >index 6f78dfcf1f88d0b06b9ebb48ea9b33ff26884215..390b858df12e2b5e83c7d3726dd332cd1c8bcc12 100644 >--- a/Source/WebCore/layout/FloatingContext.cpp >+++ b/Source/WebCore/layout/FloatingContext.cpp >@@ -113,7 +113,7 @@ FloatingContext::FloatingContext(FloatingState& floatingState) > { > } > >-Position FloatingContext::computePosition(const Box& layoutBox) const >+Position FloatingContext::positionForFloat(const Box& layoutBox) const > { > ASSERT(layoutBox.isFloatingPositioned()); > FloatingState::FloatItem floatItem = { layoutBox, m_floatingState }; >@@ -131,6 +131,50 @@ Position FloatingContext::computePosition(const Box& layoutBox) const > return toContainingBlock(floatItem, floatPosition); > } > >+std::optional<LayoutUnit> FloatingContext::verticalPositionWithClearance(const Box& layoutBox) const >+{ >+ ASSERT(layoutBox.hasClearance()); >+ ASSERT(layoutBox.isBlockLevelBox()); >+ >+ if (m_floatingState.isEmpty()) >+ return { }; >+ >+ auto bottom = [&](std::optional<LayoutUnit> floatBottom) -> std::optional<LayoutUnit> { >+ // 'bottom' is in the formatting root's coordinate system. >+ if (!floatBottom) >+ return { }; >+ >+ // 9.5.2 Controlling flow next to floats: the 'clear' property >+ // Then the amount of clearance is set to the greater of: >+ // >+ // 1. The amount necessary to place the border edge of the block even with the bottom outer edge of the lowest float that is to be cleared. >+ // 2. The amount necessary to place the top border edge of the block at its hypothetical position. >+ >+ auto absoluteDisplayBox = FormattingContext::mapToAncestor(layoutContext(), layoutBox, downcast<Container>(m_floatingState.root())); >+ if (floatBottom <= absoluteDisplayBox.rectWithMargin().top()) >+ return { }; >+ >+ // The return vertical position is in the containing block's coordinate system. >+ auto* containingBlockDisplayBox = layoutContext().displayBoxForLayoutBox(*layoutBox.containingBlock()); >+ return *floatBottom - containingBlockDisplayBox->top(); >+ }; >+ >+ auto clear = layoutBox.style().clear(); >+ auto& formattingContextRoot = layoutBox.formattingContextRoot(); >+ >+ if (clear == Clear::Left) >+ return bottom(m_floatingState.leftBottom(formattingContextRoot)); >+ >+ if (clear == Clear::Right) >+ return bottom(m_floatingState.rightBottom(formattingContextRoot)); >+ >+ if (clear == Clear::Both) >+ return bottom(m_floatingState.bottom(formattingContextRoot)); >+ >+ ASSERT_NOT_REACHED(); >+ return { }; >+} >+ > Position FloatingContext::floatingPosition(const FloatingState::FloatItem& floatItem) const > { > auto initialVerticalPosition = this->initialVerticalPosition(floatItem); >@@ -176,13 +220,13 @@ LayoutUnit FloatingContext::alignWithContainingBlock(const FloatingState::FloatI > { > // If there is no floating to align with, push the box to the left/right edge of its containing block's content box. > // (Either there's no floats at all or this box does not fit at any vertical positions where the floats are.) >- auto& containgBlockDisplayBox = floatItem.containingBlockDisplayBox(); >- auto containingBlockContentBoxLeft = containgBlockDisplayBox.left() + containgBlockDisplayBox.contentBoxLeft(); >+ auto& containingBlockDisplayBox = floatItem.containingBlockDisplayBox(); >+ auto containingBlockContentBoxLeft = containingBlockDisplayBox.left() + containingBlockDisplayBox.contentBoxLeft(); > > if (floatItem.layoutBox().isLeftFloatingPositioned()) > return containingBlockContentBoxLeft; > >- return containingBlockContentBoxLeft + containgBlockDisplayBox.contentBoxWidth() - floatItem.displayBox().marginBox().width(); >+ return containingBlockContentBoxLeft + containingBlockDisplayBox.contentBoxWidth() - floatItem.displayBox().marginBox().width(); > } > > LayoutUnit FloatingContext::alignWithFloatings(const FloatingPair& floatingPair, const FloatingState::FloatItem& floatItem) const >@@ -227,8 +271,8 @@ Position FloatingContext::toContainingBlock(const FloatingState::FloatItem& floa > if (&floatItem.containingBlock() == &m_floatingState.root()) > return position; > >- auto& containgBlockDisplayBox = floatItem.containingBlockDisplayBox(); >- return { position.x - containgBlockDisplayBox.left(), position.y - containgBlockDisplayBox.top() }; >+ auto& containingBlockDisplayBox = floatItem.containingBlockDisplayBox(); >+ return { position.x - containingBlockDisplayBox.left(), position.y - containingBlockDisplayBox.top() }; > } > > FloatingPair::FloatingPair(const FloatingState::FloatList& floats) >diff --git a/Source/WebCore/layout/FloatingContext.h b/Source/WebCore/layout/FloatingContext.h >index cdb4cc2e6a805938490d7446102ef16dbb66a4ba..d903a93da332c622bd5c7a3f4723f12fa95696a9 100644 >--- a/Source/WebCore/layout/FloatingContext.h >+++ b/Source/WebCore/layout/FloatingContext.h >@@ -49,7 +49,8 @@ public: > > FloatingState& floatingState() const { return m_floatingState; } > >- Position computePosition(const Box&) const; >+ Position positionForFloat(const Box&) const; >+ std::optional<LayoutUnit> verticalPositionWithClearance(const Box&) const; > > private: > LayoutContext& layoutContext() const { return m_floatingState.layoutContext(); } >diff --git a/Source/WebCore/layout/FloatingState.cpp b/Source/WebCore/layout/FloatingState.cpp >index be0ddd0f99410c90de440c56a59b65c78975f3d4..95a8c4df34095a56222da73a326e90dd462c03c2 100644 >--- a/Source/WebCore/layout/FloatingState.cpp >+++ b/Source/WebCore/layout/FloatingState.cpp >@@ -90,7 +90,7 @@ void FloatingState::append(const Box& layoutBox) > m_floats.append({ layoutBox, *this }); > } > >-std::optional<LayoutUnit> FloatingState::bottom(const Box& formattingContextRoot) const >+std::optional<LayoutUnit> FloatingState::bottom(const Box& formattingContextRoot, FloatStack stack) const > { > if (m_floats.isEmpty()) > return { }; >@@ -103,6 +103,10 @@ std::optional<LayoutUnit> FloatingState::bottom(const Box& formattingContextRoot > if (&formattingContextRoot != &floatItem.layoutBox().formattingContextRoot()) > continue; > >+ if ((stack == FloatStack::Left && !floatItem.layoutBox().isLeftFloatingPositioned()) >+ || (stack == FloatStack::Right && !floatItem.layoutBox().isRightFloatingPositioned())) >+ continue; >+ > auto floatsBottom = floatItem.displayBox().rectWithMargin().bottom(); > if (bottom) { > bottom = std::max(*bottom, floatsBottom); >diff --git a/Source/WebCore/layout/FloatingState.h b/Source/WebCore/layout/FloatingState.h >index 62cf25d9e3ac9886662d42adc6ddef1861060be6..54908459c80583bf533179c3b79a56164b30825a 100644 >--- a/Source/WebCore/layout/FloatingState.h >+++ b/Source/WebCore/layout/FloatingState.h >@@ -51,6 +51,9 @@ public: > void remove(const Box& layoutBox); > > bool isEmpty() const { return m_floats.isEmpty(); } >+ >+ std::optional<LayoutUnit> leftBottom(const Box& formattingContextRoot) const; >+ std::optional<LayoutUnit> rightBottom(const Box& formattingContextRoot) const; > std::optional<LayoutUnit> bottom(const Box& formattingContextRoot) const; > > class FloatItem { >@@ -81,11 +84,29 @@ private: > LayoutContext& layoutContext() const { return m_layoutContext; } > const Box& root() const { return *m_formattingContextRoot; } > >+ enum class FloatStack { Left, Right, Both }; >+ std::optional<LayoutUnit> bottom(const Box& formattingContextRoot, FloatStack) const; >+ > LayoutContext& m_layoutContext; > WeakPtr<Box> m_formattingContextRoot; > FloatList m_floats; > }; > >+inline std::optional<LayoutUnit> FloatingState::leftBottom(const Box& formattingContextRoot) const >+{ >+ return bottom(formattingContextRoot, FloatStack::Left); >+} >+ >+inline std::optional<LayoutUnit> FloatingState::rightBottom(const Box& formattingContextRoot) const >+{ >+ return bottom(formattingContextRoot, FloatStack::Right); >+} >+ >+inline std::optional<LayoutUnit> FloatingState::bottom(const Box& formattingContextRoot) const >+{ >+ return bottom(formattingContextRoot, FloatStack::Both); >+} >+ > } > } > #endif >diff --git a/Source/WebCore/layout/blockformatting/BlockFormattingContext.cpp b/Source/WebCore/layout/blockformatting/BlockFormattingContext.cpp >index 8cd6aa984503a79638d9a9dd1ede1638ab388d11..b82ec058629a3e797bd412f221524b36084f0ce9 100644 >--- a/Source/WebCore/layout/blockformatting/BlockFormattingContext.cpp >+++ b/Source/WebCore/layout/blockformatting/BlockFormattingContext.cpp >@@ -110,8 +110,10 @@ void BlockFormattingContext::layout(LayoutContext& layoutContext, FormattingStat > LOG_WITH_STREAM(FormattingContextLayout, stream << "[Compute] -> [Height][Margin] -> for layoutBox(" << &layoutBox << ")"); > // Formatting root boxes are special-cased and they don't come here. > ASSERT(!layoutBox.establishesFormattingContext()); >- > computeHeightAndMargin(layoutContext, layoutBox, displayBox); >+ // Finalize position with clearance. >+ if (layoutBox.hasClearance()) >+ computeVerticalPositionWithClearance(floatingContext, layoutBox, displayBox); > if (!is<Container>(layoutBox)) > continue; > auto& container = downcast<Container>(layoutBox); >@@ -157,10 +159,17 @@ void BlockFormattingContext::computeStaticPosition(LayoutContext& layoutContext, > void BlockFormattingContext::computeFloatingPosition(FloatingContext& floatingContext, const Box& layoutBox, Display::Box& displayBox) const > { > ASSERT(layoutBox.isFloatingPositioned()); >- displayBox.setTopLeft(floatingContext.computePosition(layoutBox)); >+ displayBox.setTopLeft(floatingContext.positionForFloat(layoutBox)); > floatingContext.floatingState().append(layoutBox); > } > >+void BlockFormattingContext::computeVerticalPositionWithClearance(const FloatingContext& floatingContext, const Box& layoutBox, Display::Box& displayBox) const >+{ >+ ASSERT(layoutBox.hasClearance()); >+ if (auto verticalPositionWithClearance = floatingContext.verticalPositionWithClearance(layoutBox)) >+ displayBox.setTop(*verticalPositionWithClearance); >+} >+ > void BlockFormattingContext::computeInFlowPositionedPosition(LayoutContext& layoutContext, const Box& layoutBox, Display::Box& displayBox) const > { > displayBox.setTopLeft(Geometry::inFlowPositionedPosition(layoutContext, layoutBox)); >diff --git a/Source/WebCore/layout/blockformatting/BlockFormattingContext.h b/Source/WebCore/layout/blockformatting/BlockFormattingContext.h >index cf5a6ea2523cc95d3819b6d5b4bd14b6917e5d6b..41af11878e400c2b203b767608d66081ba8c8199 100644 >--- a/Source/WebCore/layout/blockformatting/BlockFormattingContext.h >+++ b/Source/WebCore/layout/blockformatting/BlockFormattingContext.h >@@ -57,6 +57,7 @@ private: > > void computeStaticPosition(LayoutContext&, const Box&, Display::Box&) const override; > void computeFloatingPosition(FloatingContext&, const Box&, Display::Box&) const; >+ void computeVerticalPositionWithClearance(const FloatingContext&, const Box&, Display::Box&) const; > void computeInFlowPositionedPosition(LayoutContext&, const Box&, Display::Box&) const override; > void computeInFlowWidthAndMargin(LayoutContext&, const Box&, Display::Box&) const; > void computeInFlowHeightAndMargin(LayoutContext&, const Box&, Display::Box&) const; >diff --git a/Source/WebCore/layout/layouttree/LayoutBox.cpp b/Source/WebCore/layout/layouttree/LayoutBox.cpp >index b6025696d6ab471729ea84487daf121543ef5d39..3bd0328c3dfcf5214553be0acc3cca3ad9eaa546 100644 >--- a/Source/WebCore/layout/layouttree/LayoutBox.cpp >+++ b/Source/WebCore/layout/layouttree/LayoutBox.cpp >@@ -114,6 +114,11 @@ bool Box::isRightFloatingPositioned() const > return m_style.floating() == Float::Right; > } > >+bool Box::hasClearance() const >+{ >+ return m_style.clear() != Clear::None; >+} >+ > const Container* Box::containingBlock() const > { > // The containing block in which the root element lives is a rectangle called the initial containing block. >diff --git a/Source/WebCore/layout/layouttree/LayoutBox.h b/Source/WebCore/layout/layouttree/LayoutBox.h >index f544515b36a1ac6ee314b7b66a273c5e1711b67e..21dc657c69ce768c554d5cc13b7759cc76f7002b 100644 >--- a/Source/WebCore/layout/layouttree/LayoutBox.h >+++ b/Source/WebCore/layout/layouttree/LayoutBox.h >@@ -62,6 +62,7 @@ public: > bool isFloatingPositioned() const; > bool isLeftFloatingPositioned() const; > bool isRightFloatingPositioned() const; >+ bool hasClearance() const; > > bool isFloatingOrOutOfFlowPositioned() const { return isFloatingPositioned() || isOutOfFlowPositioned(); } > >diff --git a/Tools/ChangeLog b/Tools/ChangeLog >index 76e7a2c2b7d3a579899622576d4eb39dc5dbf217..9676a6a114b3ab2f017ba5303e1ed5a8eea90151 100644 >--- a/Tools/ChangeLog >+++ b/Tools/ChangeLog >@@ -1,3 +1,12 @@ >+2018-08-12 Zalan Bujtas <zalan@apple.com> >+ >+ [LFC][Floating] Add basic clearance support >+ https://bugs.webkit.org/show_bug.cgi?id=188492 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * LayoutReloaded/misc/LFC-passing-tests.txt: >+ > 2018-08-12 Zalan Bujtas <zalan@apple.com> > > [LFC] Float prev/next sibling should prevent top/bottom margin collapsing with parent. >diff --git a/Tools/LayoutReloaded/misc/LFC-passing-tests.txt b/Tools/LayoutReloaded/misc/LFC-passing-tests.txt >index 45b2f6495a93a06f5938591833f36ee54942fa68..aba76f45f0f153644a27304b5d4f90135db0b6ab 100644 >--- a/Tools/LayoutReloaded/misc/LFC-passing-tests.txt >+++ b/Tools/LayoutReloaded/misc/LFC-passing-tests.txt >@@ -47,3 +47,4 @@ 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-left-and-right-with-clearance.html >diff --git a/LayoutTests/ChangeLog b/LayoutTests/ChangeLog >index 932161c1d720407e498e8055d8b75aa0c07eeb6d..77cffdea756048abf72c7447b71f2daa00e12d6f 100644 >--- a/LayoutTests/ChangeLog >+++ b/LayoutTests/ChangeLog >@@ -1,3 +1,13 @@ >+2018-08-12 Zalan Bujtas <zalan@apple.com> >+ >+ [LFC][Floating] Add basic clearance support >+ https://bugs.webkit.org/show_bug.cgi?id=188492 >+ >+ Reviewed by NOBODY (OOPS!). >+ >+ * fast/block/block-only/floating-left-and-right-with-clearance-expected.txt: Added. >+ * fast/block/block-only/floating-left-and-right-with-clearance.html: Added. >+ > 2018-08-12 Zalan Bujtas <zalan@apple.com> > > [LFC] Float prev/next sibling should prevent top/bottom margin collapsing with parent. >diff --git a/LayoutTests/fast/block/block-only/floating-left-and-right-with-clearance-expected.txt b/LayoutTests/fast/block/block-only/floating-left-and-right-with-clearance-expected.txt >new file mode 100644 >index 0000000000000000000000000000000000000000..5348d8716a665139da50f6132efe6beed8f1aafb >--- /dev/null >+++ b/LayoutTests/fast/block/block-only/floating-left-and-right-with-clearance-expected.txt >@@ -0,0 +1,19 @@ >+layer at (0,0) size 800x600 >+ RenderView at (0,0) size 800x600 >+layer at (0,0) size 800x518 >+ RenderBlock {HTML} at (0,0) size 800x518 >+ RenderBody {BODY} at (8,8) size 784x502 >+ RenderBlock {DIV} at (0,0) size 502x502 [border: (1px solid #000000)] >+ RenderBlock {DIV} at (1,1) size 12x12 [border: (1px solid #000000)] >+ RenderBlock (floating) {DIV} at (1,13) size 52x102 [border: (1px solid #000000)] >+ RenderBlock {DIV} at (1,13) size 500x115 [border: (1px solid #008000)] >+ RenderBlock {DIV} at (11,102) size 12x12 [border: (1px solid #000000)] >+ RenderBlock {DIV} at (1,178) size 12x12 [border: (1px solid #000000)] >+ RenderBlock (floating) {DIV} at (449,190) size 52x22 [border: (1px solid #000000)] >+ RenderBlock {DIV} at (1,275) size 12x12 [border: (1px solid #000000)] >+ RenderBlock (floating) {DIV} at (1,287) size 52x102 [border: (1px solid #000000)] >+ RenderBlock (floating) {DIV} at (449,287) size 52x112 [border: (1px solid #000000)] >+ RenderBlock {DIV} at (1,399) size 12x12 [border: (1px solid #000000)] >+layer at (9,213) size 500x35 >+ RenderBlock (relative positioned) {DIV} at (1,190) size 500x35 [border: (1px solid #008000)] >+ RenderBlock {DIV} at (1,22) size 12x12 [border: (1px solid #000000)] >diff --git a/LayoutTests/fast/block/block-only/floating-left-and-right-with-clearance.html b/LayoutTests/fast/block/block-only/floating-left-and-right-with-clearance.html >new file mode 100644 >index 0000000000000000000000000000000000000000..5bf1dc10548562bc662f5bd34ec3105ccc2db57b >--- /dev/null >+++ b/LayoutTests/fast/block/block-only/floating-left-and-right-with-clearance.html >@@ -0,0 +1,31 @@ >+<!DOCTYPE html> >+<html> >+<head> >+<style> >+div { >+ border: 1px solid black; >+} >+</style> >+</head> >+<body> >+<div style="width: 500px; height: 500px;"> >+ <div style="width: 10px; height: 10px;"></div> >+ <div style="float: left; width: 50px; height: 100px;"></div> >+ <div style="padding-left: 10px; border: 1px solid green"> >+ <div style="clear: left; width: 10px; height: 10px;"></div> >+ </div> >+ >+ <div style="width: 10px; height: 10px; margin-top: 50px;"></div> >+ <div style="float: right; width: 50px; height: 20px;"></div> >+ <div style="position: relative; top: 15px; 10px; border: 1px solid green"> >+ <div style="clear: right; width: 10px; height: 10px;"></div> >+ </div> >+ >+ >+ <div style="width: 10px; height: 10px; margin-top: 50px;"></div> >+ <div style="float: left; width: 50px; height: 100px;"></div> >+ <div style="float: right; width: 50px; height: 110px;"></div> >+ <div style="clear: both; width: 10px; height: 10px;"></div> >+</div> >+</body> >+</html> >\ No newline at end of file
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
Flags:
koivisto
:
review+
Actions:
View
|
Formatted Diff
|
Diff
Attachments on
bug 188492
: 346991