WebKit Bugzilla
Attachment 347801 Details for
Bug 188846
: [LFC][Floating] Move files to a dedicated directory.
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Patch
bug-188846-20180822090745.patch (text/plain), 74.08 KB, created by
zalan
on 2018-08-22 09:07:48 PDT
(
hide
)
Description:
Patch
Filename:
MIME Type:
Creator:
zalan
Created:
2018-08-22 09:07:48 PDT
Size:
74.08 KB
patch
obsolete
>Subversion Revision: 235170 >diff --git a/Source/WebCore/ChangeLog b/Source/WebCore/ChangeLog >index da856726e25dd12db8cb29765e1f4f2f68c6ae9c..3002a5db6a2b143344c014182f824b02dcc45488 100644 >--- a/Source/WebCore/ChangeLog >+++ b/Source/WebCore/ChangeLog >@@ -1,3 +1,64 @@ >+2018-08-22 Zalan Bujtas <zalan@apple.com> >+ >+ [LFC][Floating] Move files to a dedicated directory. >+ https://bugs.webkit.org/show_bug.cgi?id=188846 >+ >+ Reviewed by Simon Fraser. >+ >+ layout/Float* -> layout/floatformatting >+ >+ * WebCore.xcodeproj/project.pbxproj: >+ * layout/floatformatting/FloatingContext.cpp: Renamed from Source/WebCore/layout/FloatingContext.cpp. >+ (WebCore::Layout::FloatingPair::isEmpty const): >+ (WebCore::Layout::FloatingPair::verticalPosition const): >+ (WebCore::Layout::Iterator::operator* const): >+ (WebCore::Layout::begin): >+ (WebCore::Layout::end): >+ (WebCore::Layout::FloatingContext::FloatingContext): >+ (WebCore::Layout::FloatingContext::positionForFloat const): >+ (WebCore::Layout::FloatingContext::verticalPositionWithClearance const): >+ (WebCore::Layout::FloatingContext::floatingPosition const): >+ (WebCore::Layout::FloatingContext::initialVerticalPosition const): >+ (WebCore::Layout::FloatingContext::alignWithContainingBlock const): >+ (WebCore::Layout::FloatingContext::alignWithFloatings const): >+ (WebCore::Layout::FloatingContext::toContainingBlock const): >+ (WebCore::Layout::FloatingPair::FloatingPair): >+ (WebCore::Layout::FloatingPair::left const): >+ (WebCore::Layout::FloatingPair::right const): >+ (WebCore::Layout::FloatingPair::intersects const): >+ (WebCore::Layout::FloatingPair::operator == const): >+ (WebCore::Layout::FloatingPair::bottom const): >+ (WebCore::Layout::Iterator::Iterator): >+ (WebCore::Layout::previousFloatingIndex): >+ (WebCore::Layout::Iterator::operator++): >+ (WebCore::Layout::Iterator::set): >+ (WebCore::Layout::Iterator::operator== const): >+ (WebCore::Layout::Iterator::operator!= const): >+ * layout/floatformatting/FloatingContext.h: Renamed from Source/WebCore/layout/FloatingContext.h. >+ (WebCore::Layout::FloatingContext::floatingState const): >+ (WebCore::Layout::FloatingContext::layoutContext const): >+ * layout/floatformatting/FloatingState.cpp: Renamed from Source/WebCore/layout/FloatingState.cpp. >+ (WebCore::Layout::FloatingState::FloatItem::FloatItem): >+ (WebCore::Layout::FloatingState::FloatingState): >+ (WebCore::Layout::belongsToThisFloatingContext): >+ (WebCore::Layout::FloatingState::remove): >+ (WebCore::Layout::FloatingState::append): >+ (WebCore::Layout::FloatingState::bottom const): >+ * layout/floatformatting/FloatingState.h: Renamed from Source/WebCore/layout/FloatingState.h. >+ (WebCore::Layout::FloatingState::create): >+ (WebCore::Layout::FloatingState::isEmpty const): >+ (WebCore::Layout::FloatingState::FloatItem::layoutBox const): >+ (WebCore::Layout::FloatingState::FloatItem::containingBlock const): >+ (WebCore::Layout::FloatingState::FloatItem::displayBox const): >+ (WebCore::Layout::FloatingState::FloatItem::containingBlockDisplayBox const): >+ (WebCore::Layout::FloatingState::floats const): >+ (WebCore::Layout::FloatingState::last const): >+ (WebCore::Layout::FloatingState::layoutContext const): >+ (WebCore::Layout::FloatingState::root const): >+ (WebCore::Layout::FloatingState::leftBottom const): >+ (WebCore::Layout::FloatingState::rightBottom const): >+ (WebCore::Layout::FloatingState::bottom const): >+ > 2018-08-22 Zalan Bujtas <zalan@apple.com> > > Add changes missing from r234925. >diff --git a/Source/WebCore/Sources.txt b/Source/WebCore/Sources.txt >index f0ef78610dd046b367272c05aac6744585c938a2..2d11405ed1a05b78e41776edd67fbd9679b46bfe 100644 >--- a/Source/WebCore/Sources.txt >+++ b/Source/WebCore/Sources.txt >@@ -1217,8 +1217,6 @@ inspector/agents/worker/WorkerDebuggerAgent.cpp > inspector/agents/worker/WorkerNetworkAgent.cpp > inspector/agents/worker/WorkerRuntimeAgent.cpp > >-layout/FloatingContext.cpp >-layout/FloatingState.cpp > layout/FormattingContext.cpp > layout/FormattingContextGeometry.cpp > layout/FormattingState.cpp >@@ -1230,6 +1228,8 @@ layout/blockformatting/BlockFormattingState.cpp > layout/blockformatting/BlockMarginCollapse.cpp > layout/blockformatting/BlockInvalidation.cpp > layout/displaytree/DisplayBox.cpp >+layout/floats/FloatingContext.cpp >+layout/floats/FloatingState.cpp > layout/inlineformatting/InlineFormattingContext.cpp > layout/inlineformatting/InlineFormattingState.cpp > layout/inlineformatting/InlineInvalidation.cpp >diff --git a/Source/WebCore/WebCore.xcodeproj/project.pbxproj b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >index 1d64b32f4a1320823a5867d0a5f1dd41a4b8e6b3..115622de4db402d6cf4108f0ac611c3d2b65315f 100644 >--- a/Source/WebCore/WebCore.xcodeproj/project.pbxproj >+++ b/Source/WebCore/WebCore.xcodeproj/project.pbxproj >@@ -15665,12 +15665,9 @@ > children = ( > 115CFA99208BC09A001E6991 /* blockformatting */, > 1199FA58208E3C4C002358CC /* displaytree */, >+ 6FCFC055212DACC2007695D2 /* floats */, > 115CFA9A208BC140001E6991 /* inlineformatting */, > 115CFA90208B9441001E6991 /* layouttree */, >- 115CFA85208B9066001E6991 /* FloatingContext.cpp */, >- 115CFA84208B9066001E6991 /* FloatingContext.h */, >- 115CFA81208B8EDA001E6991 /* FloatingState.cpp */, >- 115CFA80208B8EDA001E6991 /* FloatingState.h */, > 115CFA69208AF7D0001E6991 /* FormattingContext.cpp */, > 115CFA68208AF7D0001E6991 /* FormattingContext.h */, > 6FBB860520B464B600DAD938 /* FormattingContextGeometry.cpp */, >@@ -19471,6 +19468,17 @@ > path = simple; > sourceTree = "<group>"; > }; >+ 6FCFC055212DACC2007695D2 /* floats */ = { >+ isa = PBXGroup; >+ children = ( >+ 115CFA85208B9066001E6991 /* FloatingContext.cpp */, >+ 115CFA84208B9066001E6991 /* FloatingContext.h */, >+ 115CFA81208B8EDA001E6991 /* FloatingState.cpp */, >+ 115CFA80208B8EDA001E6991 /* FloatingState.h */, >+ ); >+ path = floats; >+ sourceTree = "<group>"; >+ }; > 6FE7DDDD20EC6E8B008B5B4E /* textlayout */ = { > isa = PBXGroup; > children = ( >diff --git a/Source/WebCore/layout/FloatingContext.cpp b/Source/WebCore/layout/FloatingContext.cpp >deleted file mode 100644 >index 4feaea27be180c5c10f4ed9258b0abf42c38a77a..0000000000000000000000000000000000000000 >--- a/Source/WebCore/layout/FloatingContext.cpp >+++ /dev/null >@@ -1,516 +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 "FloatingContext.h" >- >-#if ENABLE(LAYOUT_FORMATTING_CONTEXT) >- >-#include "DisplayBox.h" >-#include "LayoutBox.h" >-#include "LayoutContainer.h" >-#include "LayoutContext.h" >-#include <wtf/IsoMallocInlines.h> >- >-namespace WebCore { >-namespace Layout { >- >-WTF_MAKE_ISO_ALLOCATED_IMPL(FloatingContext); >- >-// Finding the top/left position for a new floating(F) >-// ____ ____ _____ _______ >-// | || L2 || | <-----1---->| | >-// | ||____|| L3 | | R1 | >-// | L1 | |_____| | | >-// |____| <-------------2--------->| | >-// | | >-// |_______| >-// >-// 1. Compute the initial vertical position for (F) -> (1) >-// 2. Find the corresponding floating pair (L3-R1) >-// 3. Align (F) horizontally with (L3-R1) depending whether (F) is left/right positioned >-// 4. Intersect (F) with (L3-R1) >-// 5. If (F) does not fit, find the next floating pair (L1-R1) >-// 6. Repeat until either (F) fits/no more floats. >-// Note that all coordinates are in the coordinate system of the formatting root. >-// The formatting root here is always the one that establishes the floating context (see inherited floating context). >-// (It simply means that the float box's formatting root is not necessarily the same as the FormattingContext's root.) >- >-class Iterator; >- >-class FloatingPair { >-public: >- bool isEmpty() const { return !m_leftIndex && !m_rightIndex; } >- const Display::Box* left() const; >- const Display::Box* right() const; >- bool intersects(const Display::Box::Rect&) const; >- LayoutUnit verticalPosition() const { return m_verticalPosition; } >- LayoutUnit bottom() const; >- bool operator==(const FloatingPair&) const; >- >-private: >- friend class Iterator; >- FloatingPair(const FloatingState::FloatList&); >- >- const FloatingState::FloatList& m_floats; >- >- std::optional<unsigned> m_leftIndex; >- std::optional<unsigned> m_rightIndex; >- LayoutUnit m_verticalPosition; >-}; >- >-class Iterator { >-public: >- Iterator(const FloatingState::FloatList&, std::optional<LayoutUnit> verticalPosition); >- >- const FloatingPair& operator*() const { return m_current; } >- Iterator& operator++(); >- bool operator==(const Iterator&) const; >- bool operator!=(const Iterator&) const; >- >-private: >- void set(LayoutUnit verticalPosition); >- >- const FloatingState::FloatList& m_floats; >- FloatingPair m_current; >-}; >- >-static Iterator begin(const FloatingState& floatingState, LayoutUnit initialVerticalPosition) >-{ >- // Start with the inner-most floating pair for the initial vertical position. >- return Iterator(floatingState.floats(), initialVerticalPosition); >-} >- >-static Iterator end(const FloatingState& floatingState) >-{ >- return Iterator(floatingState.floats(), std::nullopt); >-} >- >-FloatingContext::FloatingContext(FloatingState& floatingState) >- : m_floatingState(floatingState) >-{ >-} >- >-Position FloatingContext::positionForFloat(const Box& layoutBox) const >-{ >- ASSERT(layoutBox.isFloatingPositioned()); >- FloatingState::FloatItem floatItem = { layoutBox, m_floatingState }; >- >- Position floatPosition; >- if (m_floatingState.isEmpty()) { >- // No float box on the context yet -> align it with the containing block's left/right edge. >- auto& displayBox = floatItem.displayBox(); >- floatPosition = { alignWithContainingBlock(floatItem) + displayBox.marginLeft(), displayBox.top() }; >- } else { >- // Find the top most position where the float box fits. >- floatPosition = floatingPosition(floatItem); >- } >- >- return toContainingBlock(floatItem, floatPosition); >-} >- >-std::optional<LayoutUnit> FloatingContext::verticalPositionWithClearance(const Box& layoutBox) const >-{ >- ASSERT(layoutBox.hasFloatClear()); >- 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& layoutContext = this->layoutContext(); >- auto& displayBox = *layoutContext.displayBoxForLayoutBox(layoutBox); >- auto rootRelativeTop = FormattingContext::mapTopLeftToAncestor(layoutContext, layoutBox, downcast<Container>(m_floatingState.root())).y; >- auto clearance = *floatBottom - rootRelativeTop; >- if (clearance <= 0) >- return { }; >- >- // Clearance inhibits margin collapsing. Let's reset the relevant adjoining margins. >- if (auto* previousInFlowSibling = layoutBox.previousInFlowSibling()) { >- auto& previousInFlowDisplayBox = *layoutContext.displayBoxForLayoutBox(*previousInFlowSibling); >- >- // Since the previous inflow sibling has already been laid out, its margin is collapsed by now. >- ASSERT(!previousInFlowDisplayBox.marginBottom()); >- auto collapsedMargin = displayBox.marginTop(); >- >- // Reset previous bottom and current top margins to non-collapsing. >- previousInFlowDisplayBox.setVerticalMargin({ previousInFlowDisplayBox.marginTop(), previousInFlowDisplayBox.nonCollapsedMarginBottom() }); >- displayBox.setVerticalMargin({ displayBox.nonCollapsedMarginTop(), displayBox.marginBottom() }); >- >- auto nonCollapsedMargin = previousInFlowDisplayBox.marginBottom() + displayBox.marginTop(); >- auto marginOffset = nonCollapsedMargin - collapsedMargin; >- // Move the box to the position where it would be with non-collapsed margins. >- rootRelativeTop += 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 -= marginOffset; >- } >- // Now adjust the box's position with the clearance. >- rootRelativeTop += clearance; >- ASSERT(*floatBottom == rootRelativeTop); >- >- // The return vertical position is in the containing block's coordinate system. >- auto containingBlockRootRelativeTop = FormattingContext::mapTopLeftToAncestor(layoutContext, *layoutBox.containingBlock(), downcast<Container>(m_floatingState.root())).y; >- return rootRelativeTop - containingBlockRootRelativeTop; >- }; >- >- 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); >- auto& displayBox = floatItem.displayBox(); >- auto marginBoxSize = displayBox.marginBox().size(); >- >- auto end = Layout::end(m_floatingState); >- auto top = initialVerticalPosition; >- auto bottomMost = top; >- for (auto iterator = begin(m_floatingState, initialVerticalPosition); iterator != end; ++iterator) { >- ASSERT(!(*iterator).isEmpty()); >- >- auto floats = *iterator; >- top = floats.verticalPosition(); >- >- // Move the box horizontally so that it aligns with the current floating pair. >- auto left = alignWithFloatings(floats, floatItem); >- // Check if the box fits at this vertical position. >- if (!floats.intersects({ top, left, marginBoxSize.width(), marginBoxSize.height() })) >- return { left + displayBox.marginLeft(), top + displayBox.marginTop() }; >- >- bottomMost = floats.bottom(); >- // Move to the next floating pair. >- } >- >- // Passed all the floats and still does not fit? >- return { alignWithContainingBlock(floatItem) + displayBox.marginLeft(), bottomMost + displayBox.marginTop() }; >-} >- >-LayoutUnit FloatingContext::initialVerticalPosition(const FloatingState::FloatItem& floatItem) const >-{ >- // Incoming floating cannot be placed higher than existing floats. >- // Take the static position (where the box would go if it wasn't floating) and adjust it with the last floating. >- auto marginBoxTop = floatItem.displayBox().rectWithMargin().top(); >- >- if (auto lastFloat = m_floatingState.last()) >- return std::max(marginBoxTop, lastFloat->displayBox().rectWithMargin().top()); >- >- return marginBoxTop; >-} >- >-LayoutUnit FloatingContext::alignWithContainingBlock(const FloatingState::FloatItem& floatItem) const >-{ >- // 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& containingBlockDisplayBox = floatItem.containingBlockDisplayBox(); >- auto containingBlockContentBoxLeft = containingBlockDisplayBox.left() + containingBlockDisplayBox.contentBoxLeft(); >- >- if (floatItem.layoutBox().isLeftFloatingPositioned()) >- return containingBlockContentBoxLeft; >- >- return containingBlockContentBoxLeft + containingBlockDisplayBox.contentBoxWidth() - floatItem.displayBox().marginBox().width(); >-} >- >-LayoutUnit FloatingContext::alignWithFloatings(const FloatingPair& floatingPair, const FloatingState::FloatItem& floatItem) const >-{ >- // Compute the horizontal position for the new floating by taking both the contining block and the current left/right floats into account. >- auto& containingBlockDisplayBox = floatItem.containingBlockDisplayBox(); >- auto containingBlockContentBoxLeft = containingBlockDisplayBox.left() + containingBlockDisplayBox.contentBoxLeft(); >- auto containingBlockContentBoxRight = containingBlockDisplayBox.left() + containingBlockDisplayBox.contentBoxRight(); >- auto marginBoxWidth = floatItem.displayBox().marginBox().width(); >- >- auto leftAlignedBoxLeft = containingBlockContentBoxLeft; >- auto rightAlignedBoxLeft = containingBlockContentBoxRight - marginBoxWidth; >- >- if (floatingPair.isEmpty()) { >- ASSERT_NOT_REACHED(); >- return floatItem.layoutBox().isLeftFloatingPositioned() ? leftAlignedBoxLeft : rightAlignedBoxLeft; >- } >- >- if (floatItem.layoutBox().isLeftFloatingPositioned()) { >- if (auto* leftDisplayBox = floatingPair.left()) { >- auto leftFloatingBoxRight = leftDisplayBox->rectWithMargin().right(); >- return std::min(std::max(leftAlignedBoxLeft, leftFloatingBoxRight), rightAlignedBoxLeft); >- } >- >- return leftAlignedBoxLeft; >- } >- >- ASSERT(floatItem.layoutBox().isRightFloatingPositioned()); >- >- if (auto* rightDisplayBox = floatingPair.right()) { >- auto rightFloatingBoxLeft = rightDisplayBox->rectWithMargin().left(); >- return std::max(std::min(rightAlignedBoxLeft, rightFloatingBoxLeft - marginBoxWidth), leftAlignedBoxLeft); >- } >- >- return rightAlignedBoxLeft; >-} >- >-// FIXME: find a better place for this. >-Position FloatingContext::toContainingBlock(const FloatingState::FloatItem& floatItem, Position position) const >-{ >- // From formatting root coordinate system back to containing block's. >- if (&floatItem.containingBlock() == &m_floatingState.root()) >- return position; >- >- auto& containingBlockDisplayBox = floatItem.containingBlockDisplayBox(); >- return { position.x - containingBlockDisplayBox.left(), position.y - containingBlockDisplayBox.top() }; >-} >- >-FloatingPair::FloatingPair(const FloatingState::FloatList& floats) >- : m_floats(floats) >-{ >-} >- >-const Display::Box* FloatingPair::left() const >-{ >- if (!m_leftIndex) >- return nullptr; >- >- ASSERT(m_floats[*m_leftIndex].layoutBox().isLeftFloatingPositioned()); >- return &m_floats[*m_leftIndex].displayBox(); >-} >- >-const Display::Box* FloatingPair::right() const >-{ >- if (!m_rightIndex) >- return nullptr; >- >- ASSERT(m_floats[*m_rightIndex].layoutBox().isRightFloatingPositioned()); >- return &m_floats[*m_rightIndex].displayBox(); >-} >- >-bool FloatingPair::intersects(const Display::Box::Rect& candidateRect) const >-{ >- auto intersects = [&](const Display::Box* floating, Float floatingType) { >- if (!floating) >- return false; >- >- auto marginRect = floating->rectWithMargin(); >- // Before intersecting, check if the candidate position is too far to the left/right. >- // The new float's containing block could push the candidate position beyond the current float horizontally. >- if ((floatingType == Float::Left && candidateRect.left() < marginRect.right()) >- || (floatingType == Float::Right && candidateRect.right() > marginRect.left())) >- return true; >- return marginRect.intersects(candidateRect); >- }; >- >- if (!m_leftIndex && !m_rightIndex) { >- ASSERT_NOT_REACHED(); >- return false; >- } >- >- if (intersects(left(), Float::Left)) >- return true; >- >- if (intersects(right(), Float::Right)) >- return true; >- >- return false; >-} >- >-bool FloatingPair::operator ==(const FloatingPair& other) const >-{ >- return m_leftIndex == other.m_leftIndex && m_rightIndex == other.m_rightIndex; >-} >- >-LayoutUnit FloatingPair::bottom() const >-{ >- auto* left = this->left(); >- auto* right = this->right(); >- ASSERT(left || right); >- >- auto leftBottom = left ? std::optional<LayoutUnit>(left->rectWithMargin().bottom()) : std::nullopt; >- auto rightBottom = right ? std::optional<LayoutUnit>(right->rectWithMargin().bottom()) : std::nullopt; >- >- if (leftBottom && rightBottom) >- return std::max(*leftBottom, *rightBottom); >- >- if (leftBottom) >- return *leftBottom; >- >- return *rightBottom; >-} >- >-Iterator::Iterator(const FloatingState::FloatList& floats, std::optional<LayoutUnit> verticalPosition) >- : m_floats(floats) >- , m_current(floats) >-{ >- if (verticalPosition) >- set(*verticalPosition); >-} >- >-inline static std::optional<unsigned> previousFloatingIndex(Float floatingType, const FloatingState::FloatList& floats, unsigned currentIndex) >-{ >- RELEASE_ASSERT(currentIndex <= floats.size()); >- >- while (currentIndex) { >- auto& floating = floats[--currentIndex].layoutBox(); >- if ((floatingType == Float::Left && floating.isLeftFloatingPositioned()) || (floatingType == Float::Right && floating.isRightFloatingPositioned())) >- return currentIndex; >- } >- >- return { }; >-} >- >-Iterator& Iterator::operator++() >-{ >- if (m_current.isEmpty()) { >- ASSERT_NOT_REACHED(); >- return *this; >- } >- >- auto findPreviousFloatingWithLowerBottom = [&](Float floatingType, unsigned currentIndex) -> std::optional<unsigned> { >- >- RELEASE_ASSERT(currentIndex < m_floats.size()); >- >- // Last floating? There's certainly no previous floating at this point. >- if (!currentIndex) >- return { }; >- >- auto currentBottom = m_floats[currentIndex].displayBox().rectWithMargin().bottom(); >- >- std::optional<unsigned> index = currentIndex; >- while (true) { >- index = previousFloatingIndex(floatingType, m_floats, *index); >- if (!index) >- return { }; >- >- if (m_floats[*index].displayBox().rectWithMargin().bottom() > currentBottom) >- return index; >- } >- >- ASSERT_NOT_REACHED(); >- return { }; >- }; >- >- // 1. Take the current floating from left and right and check which one's bottom edge is positioned higher (they could be on the same vertical position too). >- // The current floats from left and right are considered the inner-most pair for the current vertical position. >- // 2. Move away from inner-most pair by picking one of the previous floats in the list(#1) >- // Ensure that the new floating's bottom edge is positioned lower than the current one -which essentially means skipping in-between floats that are positioned higher). >- // 3. Reset the vertical position and align it with the new left-right pair. These floats are now the inner-most boxes for the current vertical position. >- // As the result we have more horizontal space on the current vertical position. >- auto leftBottom = m_current.left() ? std::optional<LayoutUnit>(m_current.left()->bottom()) : std::nullopt; >- auto rightBottom = m_current.right() ? std::optional<LayoutUnit>(m_current.right()->bottom()) : std::nullopt; >- >- auto updateLeft = (leftBottom == rightBottom) || (!rightBottom || (leftBottom && leftBottom < rightBottom)); >- auto updateRight = (leftBottom == rightBottom) || (!leftBottom || (rightBottom && leftBottom > rightBottom)); >- >- if (updateLeft) { >- ASSERT(m_current.m_leftIndex); >- m_current.m_verticalPosition = *leftBottom; >- m_current.m_leftIndex = findPreviousFloatingWithLowerBottom(Float::Left, *m_current.m_leftIndex); >- } >- >- if (updateRight) { >- ASSERT(m_current.m_rightIndex); >- m_current.m_verticalPosition = *rightBottom; >- m_current.m_rightIndex = findPreviousFloatingWithLowerBottom(Float::Right, *m_current.m_rightIndex); >- } >- >- return *this; >-} >- >-void Iterator::set(LayoutUnit verticalPosition) >-{ >- // Move the iterator to the initial vertical position by starting at the inner-most floating pair (last floats on left/right). >- // 1. Check if the inner-most pair covers the vertical position. >- // 2. Move outwards from the inner-most pair until the vertical postion intersects. >- // (Note that verticalPosition has already been adjusted with the top of the last float.) >- >- m_current.m_verticalPosition = verticalPosition; >- // No floats at all? >- if (m_floats.isEmpty()) { >- ASSERT_NOT_REACHED(); >- >- m_current.m_leftIndex = { }; >- m_current.m_rightIndex = { }; >- return; >- } >- >- auto findFloatingBelow = [&](Float floatingType) -> std::optional<unsigned> { >- >- ASSERT(!m_floats.isEmpty()); >- >- auto index = floatingType == Float::Left ? m_current.m_leftIndex : m_current.m_rightIndex; >- // Start from the end if we don't have current yet. >- index = index.value_or(m_floats.size()); >- while (true) { >- index = previousFloatingIndex(floatingType, m_floats, *index); >- if (!index) >- return { }; >- >- auto bottom = m_floats[*index].displayBox().rectWithMargin().bottom(); >- // Is this floating intrusive on this position? >- if (bottom > verticalPosition) >- return index; >- } >- >- return { }; >- }; >- >- m_current.m_leftIndex = findFloatingBelow(Float::Left); >- m_current.m_rightIndex = findFloatingBelow(Float::Right); >- >- ASSERT(!m_current.m_leftIndex || (*m_current.m_leftIndex < m_floats.size() && m_floats[*m_current.m_leftIndex].layoutBox().isLeftFloatingPositioned())); >- ASSERT(!m_current.m_rightIndex || (*m_current.m_rightIndex < m_floats.size() && m_floats[*m_current.m_rightIndex].layoutBox().isRightFloatingPositioned())); >-} >- >-bool Iterator::operator==(const Iterator& other) const >-{ >- return m_current == other.m_current; >-} >- >-bool Iterator::operator!=(const Iterator& other) const >-{ >- return !(*this == other); >-} >- >-} >-} >-#endif >diff --git a/Source/WebCore/layout/FloatingContext.h b/Source/WebCore/layout/FloatingContext.h >deleted file mode 100644 >index d903a93da332c622bd5c7a3f4723f12fa95696a9..0000000000000000000000000000000000000000 >--- a/Source/WebCore/layout/FloatingContext.h >+++ /dev/null >@@ -1,70 +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. >- */ >- >-#pragma once >- >-#if ENABLE(LAYOUT_FORMATTING_CONTEXT) >- >-#include "FloatingState.h" >-#include "LayoutUnits.h" >-#include <wtf/IsoMalloc.h> >- >-namespace WebCore { >- >-namespace Layout { >- >-class Box; >-class Container; >-class FloatingPair; >-class LayoutContext; >- >-// FloatingContext is responsible for adjusting the position of a box in the current formatting context >-// by taking the floating boxes into account. >-class FloatingContext { >- WTF_MAKE_ISO_ALLOCATED(FloatingContext); >-public: >- FloatingContext(FloatingState&); >- >- FloatingState& floatingState() const { return m_floatingState; } >- >- Position positionForFloat(const Box&) const; >- std::optional<LayoutUnit> verticalPositionWithClearance(const Box&) const; >- >-private: >- LayoutContext& layoutContext() const { return m_floatingState.layoutContext(); } >- >- Position floatingPosition(const FloatingState::FloatItem&) const; >- >- LayoutUnit initialVerticalPosition(const FloatingState::FloatItem&) const; >- LayoutUnit alignWithContainingBlock(const FloatingState::FloatItem&) const; >- LayoutUnit alignWithFloatings(const FloatingPair&, const FloatingState::FloatItem&) const; >- Position toContainingBlock(const FloatingState::FloatItem&, Position) const; >- >- FloatingState& m_floatingState; >-}; >- >-} >-} >-#endif >diff --git a/Source/WebCore/layout/FloatingState.cpp b/Source/WebCore/layout/FloatingState.cpp >deleted file mode 100644 >index 41d3ecedcbf53a300c8f195b991d345b6fdbe008..0000000000000000000000000000000000000000 >--- a/Source/WebCore/layout/FloatingState.cpp >+++ /dev/null >@@ -1,122 +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 "FloatingState.h" >- >-#if ENABLE(LAYOUT_FORMATTING_CONTEXT) >- >-#include "FormattingContext.h" >-#include "LayoutBox.h" >-#include "LayoutContext.h" >-#include <wtf/IsoMallocInlines.h> >- >-namespace WebCore { >-namespace Layout { >- >-WTF_MAKE_ISO_ALLOCATED_IMPL(FloatingState); >- >-FloatingState::FloatItem::FloatItem(const Box& layoutBox, const FloatingState& floatingState) >- : m_layoutBox(makeWeakPtr(const_cast<Box&>(layoutBox))) >- , m_containingBlock(makeWeakPtr(const_cast<Container&>(*layoutBox.containingBlock()))) >- , m_absoluteDisplayBox(FormattingContext::mapBoxToAncestor(floatingState.layoutContext(), layoutBox, downcast<Container>(floatingState.root()))) >- , m_containingBlockAbsoluteDisplayBox(FormattingContext::mapBoxToAncestor(floatingState.layoutContext(), *m_containingBlock, downcast<Container>(floatingState.root()))) >-{ >-} >- >-FloatingState::FloatingState(LayoutContext& layoutContext, const Box& formattingContextRoot) >- : m_layoutContext(layoutContext) >- , m_formattingContextRoot(makeWeakPtr(const_cast<Box&>(formattingContextRoot))) >-{ >-} >- >-#ifndef NDEBUG >-static bool belongsToThisFloatingContext(const Box& layoutBox, const Box& floatingStateRoot) >-{ >- auto& formattingContextRoot = layoutBox.formattingContextRoot(); >- if (&formattingContextRoot == &floatingStateRoot) >- return true; >- >- // Maybe the layout box belongs to an inline formatting context that inherits the floating state from the parent (block) formatting context. >- if (!formattingContextRoot.establishesInlineFormattingContext()) >- return false; >- >- return &formattingContextRoot.formattingContextRoot() == &floatingStateRoot; >-} >-#endif >- >-void FloatingState::remove(const Box& layoutBox) >-{ >- for (size_t index = 0; index < m_floats.size(); ++index) { >- if (&m_floats[index].layoutBox() == &layoutBox) { >- m_floats.remove(index); >- return; >- } >- } >- ASSERT_NOT_REACHED(); >-} >- >-void FloatingState::append(const Box& layoutBox) >-{ >- ASSERT(is<Container>(*m_formattingContextRoot)); >- ASSERT(belongsToThisFloatingContext(layoutBox, *m_formattingContextRoot)); >- >- // Floating state should hold boxes with computed position/size. >- ASSERT(m_layoutContext.displayBoxForLayoutBox(layoutBox)); >- ASSERT(is<Container>(*m_formattingContextRoot)); >- >- m_floats.append({ layoutBox, *this }); >-} >- >-std::optional<LayoutUnit> FloatingState::bottom(const Box& formattingContextRoot, Clear type) const >-{ >- if (m_floats.isEmpty()) >- return { }; >- >- // TODO: Currently this is only called once for each formatting context root with floats per layout. >- // Cache the value if we end up calling it more frequently (and update it at append/remove). >- std::optional<LayoutUnit> bottom; >- for (auto& floatItem : m_floats) { >- // Ignore floats from other formatting contexts when the floating state is inherited. >- if (&formattingContextRoot != &floatItem.layoutBox().formattingContextRoot()) >- continue; >- >- if ((type == Clear::Left && !floatItem.layoutBox().isLeftFloatingPositioned()) >- || (type == Clear::Right && !floatItem.layoutBox().isRightFloatingPositioned())) >- continue; >- >- auto floatsBottom = floatItem.displayBox().rectWithMargin().bottom(); >- if (bottom) { >- bottom = std::max(*bottom, floatsBottom); >- continue; >- } >- bottom = floatsBottom; >- } >- return bottom; >-} >- >-} >-} >-#endif >diff --git a/Source/WebCore/layout/FloatingState.h b/Source/WebCore/layout/FloatingState.h >deleted file mode 100644 >index 9a7e2b424f8c79e4423ad3692bdca69c2b172b77..0000000000000000000000000000000000000000 >--- a/Source/WebCore/layout/FloatingState.h >+++ /dev/null >@@ -1,111 +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. >- */ >- >-#pragma once >- >-#if ENABLE(LAYOUT_FORMATTING_CONTEXT) >- >-#include "DisplayBox.h" >-#include <wtf/IsoMalloc.h> >-#include <wtf/Ref.h> >-#include <wtf/WeakPtr.h> >- >-namespace WebCore { >- >-namespace Layout { >- >-class Box; >-class Container; >-class FormattingState; >-class LayoutContext; >- >-// FloatingState holds the floating boxes per formatting context. >-class FloatingState : public RefCounted<FloatingState> { >- WTF_MAKE_ISO_ALLOCATED(FloatingState); >-public: >- static Ref<FloatingState> create(LayoutContext& layoutContext, const Box& formattingContextRoot) { return adoptRef(*new FloatingState(layoutContext, formattingContextRoot)); } >- >- void append(const Box& layoutBox); >- 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 { >- public: >- FloatItem(const Box&, const FloatingState&); >- >- const Box& layoutBox() const { return *m_layoutBox; } >- const Container& containingBlock() const { return *m_containingBlock; } >- >- const Display::Box& displayBox() const { return m_absoluteDisplayBox; } >- const Display::Box& containingBlockDisplayBox() const { return m_containingBlockAbsoluteDisplayBox; } >- >- private: >- WeakPtr<Box> m_layoutBox; >- WeakPtr<Container> m_containingBlock; >- >- Display::Box m_absoluteDisplayBox; >- Display::Box m_containingBlockAbsoluteDisplayBox; >- }; >- using FloatList = Vector<FloatItem>; >- const FloatList& floats() const { return m_floats; } >- const FloatItem* last() const { return isEmpty() ? nullptr : &m_floats.last(); } >- >-private: >- friend class FloatingContext; >- FloatingState(LayoutContext&, const Box& formattingContextRoot); >- >- LayoutContext& layoutContext() const { return m_layoutContext; } >- const Box& root() const { return *m_formattingContextRoot; } >- >- std::optional<LayoutUnit> bottom(const Box& formattingContextRoot, Clear) const; >- >- LayoutContext& m_layoutContext; >- WeakPtr<Box> m_formattingContextRoot; >- FloatList m_floats; >-}; >- >-inline std::optional<LayoutUnit> FloatingState::leftBottom(const Box& formattingContextRoot) const >-{ >- return bottom(formattingContextRoot, Clear::Left); >-} >- >-inline std::optional<LayoutUnit> FloatingState::rightBottom(const Box& formattingContextRoot) const >-{ >- return bottom(formattingContextRoot, Clear::Right); >-} >- >-inline std::optional<LayoutUnit> FloatingState::bottom(const Box& formattingContextRoot) const >-{ >- return bottom(formattingContextRoot, Clear::Both); >-} >- >-} >-} >-#endif >diff --git a/Source/WebCore/layout/FormattingContextGeometry.cpp b/Source/WebCore/layout/FormattingContextGeometry.cpp >index c833b1813d27456ae12071dd0359c62bebb65bf4..cc6d80a290bd728707649b444b4558c6722d7a6f 100644 >--- a/Source/WebCore/layout/FormattingContextGeometry.cpp >+++ b/Source/WebCore/layout/FormattingContextGeometry.cpp >@@ -24,12 +24,13 @@ > */ > > #include "config.h" >-#include "FloatingState.h" > #include "FormattingContext.h" >-#include "FormattingState.h" > > #if ENABLE(LAYOUT_FORMATTING_CONTEXT) > >+#include "FloatingState.h" >+#include "FormattingState.h" >+ > namespace WebCore { > namespace Layout { > >diff --git a/Source/WebCore/layout/floats/FloatingContext.cpp b/Source/WebCore/layout/floats/FloatingContext.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..4feaea27be180c5c10f4ed9258b0abf42c38a77a >--- /dev/null >+++ b/Source/WebCore/layout/floats/FloatingContext.cpp >@@ -0,0 +1,516 @@ >+/* >+ * 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 "FloatingContext.h" >+ >+#if ENABLE(LAYOUT_FORMATTING_CONTEXT) >+ >+#include "DisplayBox.h" >+#include "LayoutBox.h" >+#include "LayoutContainer.h" >+#include "LayoutContext.h" >+#include <wtf/IsoMallocInlines.h> >+ >+namespace WebCore { >+namespace Layout { >+ >+WTF_MAKE_ISO_ALLOCATED_IMPL(FloatingContext); >+ >+// Finding the top/left position for a new floating(F) >+// ____ ____ _____ _______ >+// | || L2 || | <-----1---->| | >+// | ||____|| L3 | | R1 | >+// | L1 | |_____| | | >+// |____| <-------------2--------->| | >+// | | >+// |_______| >+// >+// 1. Compute the initial vertical position for (F) -> (1) >+// 2. Find the corresponding floating pair (L3-R1) >+// 3. Align (F) horizontally with (L3-R1) depending whether (F) is left/right positioned >+// 4. Intersect (F) with (L3-R1) >+// 5. If (F) does not fit, find the next floating pair (L1-R1) >+// 6. Repeat until either (F) fits/no more floats. >+// Note that all coordinates are in the coordinate system of the formatting root. >+// The formatting root here is always the one that establishes the floating context (see inherited floating context). >+// (It simply means that the float box's formatting root is not necessarily the same as the FormattingContext's root.) >+ >+class Iterator; >+ >+class FloatingPair { >+public: >+ bool isEmpty() const { return !m_leftIndex && !m_rightIndex; } >+ const Display::Box* left() const; >+ const Display::Box* right() const; >+ bool intersects(const Display::Box::Rect&) const; >+ LayoutUnit verticalPosition() const { return m_verticalPosition; } >+ LayoutUnit bottom() const; >+ bool operator==(const FloatingPair&) const; >+ >+private: >+ friend class Iterator; >+ FloatingPair(const FloatingState::FloatList&); >+ >+ const FloatingState::FloatList& m_floats; >+ >+ std::optional<unsigned> m_leftIndex; >+ std::optional<unsigned> m_rightIndex; >+ LayoutUnit m_verticalPosition; >+}; >+ >+class Iterator { >+public: >+ Iterator(const FloatingState::FloatList&, std::optional<LayoutUnit> verticalPosition); >+ >+ const FloatingPair& operator*() const { return m_current; } >+ Iterator& operator++(); >+ bool operator==(const Iterator&) const; >+ bool operator!=(const Iterator&) const; >+ >+private: >+ void set(LayoutUnit verticalPosition); >+ >+ const FloatingState::FloatList& m_floats; >+ FloatingPair m_current; >+}; >+ >+static Iterator begin(const FloatingState& floatingState, LayoutUnit initialVerticalPosition) >+{ >+ // Start with the inner-most floating pair for the initial vertical position. >+ return Iterator(floatingState.floats(), initialVerticalPosition); >+} >+ >+static Iterator end(const FloatingState& floatingState) >+{ >+ return Iterator(floatingState.floats(), std::nullopt); >+} >+ >+FloatingContext::FloatingContext(FloatingState& floatingState) >+ : m_floatingState(floatingState) >+{ >+} >+ >+Position FloatingContext::positionForFloat(const Box& layoutBox) const >+{ >+ ASSERT(layoutBox.isFloatingPositioned()); >+ FloatingState::FloatItem floatItem = { layoutBox, m_floatingState }; >+ >+ Position floatPosition; >+ if (m_floatingState.isEmpty()) { >+ // No float box on the context yet -> align it with the containing block's left/right edge. >+ auto& displayBox = floatItem.displayBox(); >+ floatPosition = { alignWithContainingBlock(floatItem) + displayBox.marginLeft(), displayBox.top() }; >+ } else { >+ // Find the top most position where the float box fits. >+ floatPosition = floatingPosition(floatItem); >+ } >+ >+ return toContainingBlock(floatItem, floatPosition); >+} >+ >+std::optional<LayoutUnit> FloatingContext::verticalPositionWithClearance(const Box& layoutBox) const >+{ >+ ASSERT(layoutBox.hasFloatClear()); >+ 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& layoutContext = this->layoutContext(); >+ auto& displayBox = *layoutContext.displayBoxForLayoutBox(layoutBox); >+ auto rootRelativeTop = FormattingContext::mapTopLeftToAncestor(layoutContext, layoutBox, downcast<Container>(m_floatingState.root())).y; >+ auto clearance = *floatBottom - rootRelativeTop; >+ if (clearance <= 0) >+ return { }; >+ >+ // Clearance inhibits margin collapsing. Let's reset the relevant adjoining margins. >+ if (auto* previousInFlowSibling = layoutBox.previousInFlowSibling()) { >+ auto& previousInFlowDisplayBox = *layoutContext.displayBoxForLayoutBox(*previousInFlowSibling); >+ >+ // Since the previous inflow sibling has already been laid out, its margin is collapsed by now. >+ ASSERT(!previousInFlowDisplayBox.marginBottom()); >+ auto collapsedMargin = displayBox.marginTop(); >+ >+ // Reset previous bottom and current top margins to non-collapsing. >+ previousInFlowDisplayBox.setVerticalMargin({ previousInFlowDisplayBox.marginTop(), previousInFlowDisplayBox.nonCollapsedMarginBottom() }); >+ displayBox.setVerticalMargin({ displayBox.nonCollapsedMarginTop(), displayBox.marginBottom() }); >+ >+ auto nonCollapsedMargin = previousInFlowDisplayBox.marginBottom() + displayBox.marginTop(); >+ auto marginOffset = nonCollapsedMargin - collapsedMargin; >+ // Move the box to the position where it would be with non-collapsed margins. >+ rootRelativeTop += 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 -= marginOffset; >+ } >+ // Now adjust the box's position with the clearance. >+ rootRelativeTop += clearance; >+ ASSERT(*floatBottom == rootRelativeTop); >+ >+ // The return vertical position is in the containing block's coordinate system. >+ auto containingBlockRootRelativeTop = FormattingContext::mapTopLeftToAncestor(layoutContext, *layoutBox.containingBlock(), downcast<Container>(m_floatingState.root())).y; >+ return rootRelativeTop - containingBlockRootRelativeTop; >+ }; >+ >+ 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); >+ auto& displayBox = floatItem.displayBox(); >+ auto marginBoxSize = displayBox.marginBox().size(); >+ >+ auto end = Layout::end(m_floatingState); >+ auto top = initialVerticalPosition; >+ auto bottomMost = top; >+ for (auto iterator = begin(m_floatingState, initialVerticalPosition); iterator != end; ++iterator) { >+ ASSERT(!(*iterator).isEmpty()); >+ >+ auto floats = *iterator; >+ top = floats.verticalPosition(); >+ >+ // Move the box horizontally so that it aligns with the current floating pair. >+ auto left = alignWithFloatings(floats, floatItem); >+ // Check if the box fits at this vertical position. >+ if (!floats.intersects({ top, left, marginBoxSize.width(), marginBoxSize.height() })) >+ return { left + displayBox.marginLeft(), top + displayBox.marginTop() }; >+ >+ bottomMost = floats.bottom(); >+ // Move to the next floating pair. >+ } >+ >+ // Passed all the floats and still does not fit? >+ return { alignWithContainingBlock(floatItem) + displayBox.marginLeft(), bottomMost + displayBox.marginTop() }; >+} >+ >+LayoutUnit FloatingContext::initialVerticalPosition(const FloatingState::FloatItem& floatItem) const >+{ >+ // Incoming floating cannot be placed higher than existing floats. >+ // Take the static position (where the box would go if it wasn't floating) and adjust it with the last floating. >+ auto marginBoxTop = floatItem.displayBox().rectWithMargin().top(); >+ >+ if (auto lastFloat = m_floatingState.last()) >+ return std::max(marginBoxTop, lastFloat->displayBox().rectWithMargin().top()); >+ >+ return marginBoxTop; >+} >+ >+LayoutUnit FloatingContext::alignWithContainingBlock(const FloatingState::FloatItem& floatItem) const >+{ >+ // 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& containingBlockDisplayBox = floatItem.containingBlockDisplayBox(); >+ auto containingBlockContentBoxLeft = containingBlockDisplayBox.left() + containingBlockDisplayBox.contentBoxLeft(); >+ >+ if (floatItem.layoutBox().isLeftFloatingPositioned()) >+ return containingBlockContentBoxLeft; >+ >+ return containingBlockContentBoxLeft + containingBlockDisplayBox.contentBoxWidth() - floatItem.displayBox().marginBox().width(); >+} >+ >+LayoutUnit FloatingContext::alignWithFloatings(const FloatingPair& floatingPair, const FloatingState::FloatItem& floatItem) const >+{ >+ // Compute the horizontal position for the new floating by taking both the contining block and the current left/right floats into account. >+ auto& containingBlockDisplayBox = floatItem.containingBlockDisplayBox(); >+ auto containingBlockContentBoxLeft = containingBlockDisplayBox.left() + containingBlockDisplayBox.contentBoxLeft(); >+ auto containingBlockContentBoxRight = containingBlockDisplayBox.left() + containingBlockDisplayBox.contentBoxRight(); >+ auto marginBoxWidth = floatItem.displayBox().marginBox().width(); >+ >+ auto leftAlignedBoxLeft = containingBlockContentBoxLeft; >+ auto rightAlignedBoxLeft = containingBlockContentBoxRight - marginBoxWidth; >+ >+ if (floatingPair.isEmpty()) { >+ ASSERT_NOT_REACHED(); >+ return floatItem.layoutBox().isLeftFloatingPositioned() ? leftAlignedBoxLeft : rightAlignedBoxLeft; >+ } >+ >+ if (floatItem.layoutBox().isLeftFloatingPositioned()) { >+ if (auto* leftDisplayBox = floatingPair.left()) { >+ auto leftFloatingBoxRight = leftDisplayBox->rectWithMargin().right(); >+ return std::min(std::max(leftAlignedBoxLeft, leftFloatingBoxRight), rightAlignedBoxLeft); >+ } >+ >+ return leftAlignedBoxLeft; >+ } >+ >+ ASSERT(floatItem.layoutBox().isRightFloatingPositioned()); >+ >+ if (auto* rightDisplayBox = floatingPair.right()) { >+ auto rightFloatingBoxLeft = rightDisplayBox->rectWithMargin().left(); >+ return std::max(std::min(rightAlignedBoxLeft, rightFloatingBoxLeft - marginBoxWidth), leftAlignedBoxLeft); >+ } >+ >+ return rightAlignedBoxLeft; >+} >+ >+// FIXME: find a better place for this. >+Position FloatingContext::toContainingBlock(const FloatingState::FloatItem& floatItem, Position position) const >+{ >+ // From formatting root coordinate system back to containing block's. >+ if (&floatItem.containingBlock() == &m_floatingState.root()) >+ return position; >+ >+ auto& containingBlockDisplayBox = floatItem.containingBlockDisplayBox(); >+ return { position.x - containingBlockDisplayBox.left(), position.y - containingBlockDisplayBox.top() }; >+} >+ >+FloatingPair::FloatingPair(const FloatingState::FloatList& floats) >+ : m_floats(floats) >+{ >+} >+ >+const Display::Box* FloatingPair::left() const >+{ >+ if (!m_leftIndex) >+ return nullptr; >+ >+ ASSERT(m_floats[*m_leftIndex].layoutBox().isLeftFloatingPositioned()); >+ return &m_floats[*m_leftIndex].displayBox(); >+} >+ >+const Display::Box* FloatingPair::right() const >+{ >+ if (!m_rightIndex) >+ return nullptr; >+ >+ ASSERT(m_floats[*m_rightIndex].layoutBox().isRightFloatingPositioned()); >+ return &m_floats[*m_rightIndex].displayBox(); >+} >+ >+bool FloatingPair::intersects(const Display::Box::Rect& candidateRect) const >+{ >+ auto intersects = [&](const Display::Box* floating, Float floatingType) { >+ if (!floating) >+ return false; >+ >+ auto marginRect = floating->rectWithMargin(); >+ // Before intersecting, check if the candidate position is too far to the left/right. >+ // The new float's containing block could push the candidate position beyond the current float horizontally. >+ if ((floatingType == Float::Left && candidateRect.left() < marginRect.right()) >+ || (floatingType == Float::Right && candidateRect.right() > marginRect.left())) >+ return true; >+ return marginRect.intersects(candidateRect); >+ }; >+ >+ if (!m_leftIndex && !m_rightIndex) { >+ ASSERT_NOT_REACHED(); >+ return false; >+ } >+ >+ if (intersects(left(), Float::Left)) >+ return true; >+ >+ if (intersects(right(), Float::Right)) >+ return true; >+ >+ return false; >+} >+ >+bool FloatingPair::operator ==(const FloatingPair& other) const >+{ >+ return m_leftIndex == other.m_leftIndex && m_rightIndex == other.m_rightIndex; >+} >+ >+LayoutUnit FloatingPair::bottom() const >+{ >+ auto* left = this->left(); >+ auto* right = this->right(); >+ ASSERT(left || right); >+ >+ auto leftBottom = left ? std::optional<LayoutUnit>(left->rectWithMargin().bottom()) : std::nullopt; >+ auto rightBottom = right ? std::optional<LayoutUnit>(right->rectWithMargin().bottom()) : std::nullopt; >+ >+ if (leftBottom && rightBottom) >+ return std::max(*leftBottom, *rightBottom); >+ >+ if (leftBottom) >+ return *leftBottom; >+ >+ return *rightBottom; >+} >+ >+Iterator::Iterator(const FloatingState::FloatList& floats, std::optional<LayoutUnit> verticalPosition) >+ : m_floats(floats) >+ , m_current(floats) >+{ >+ if (verticalPosition) >+ set(*verticalPosition); >+} >+ >+inline static std::optional<unsigned> previousFloatingIndex(Float floatingType, const FloatingState::FloatList& floats, unsigned currentIndex) >+{ >+ RELEASE_ASSERT(currentIndex <= floats.size()); >+ >+ while (currentIndex) { >+ auto& floating = floats[--currentIndex].layoutBox(); >+ if ((floatingType == Float::Left && floating.isLeftFloatingPositioned()) || (floatingType == Float::Right && floating.isRightFloatingPositioned())) >+ return currentIndex; >+ } >+ >+ return { }; >+} >+ >+Iterator& Iterator::operator++() >+{ >+ if (m_current.isEmpty()) { >+ ASSERT_NOT_REACHED(); >+ return *this; >+ } >+ >+ auto findPreviousFloatingWithLowerBottom = [&](Float floatingType, unsigned currentIndex) -> std::optional<unsigned> { >+ >+ RELEASE_ASSERT(currentIndex < m_floats.size()); >+ >+ // Last floating? There's certainly no previous floating at this point. >+ if (!currentIndex) >+ return { }; >+ >+ auto currentBottom = m_floats[currentIndex].displayBox().rectWithMargin().bottom(); >+ >+ std::optional<unsigned> index = currentIndex; >+ while (true) { >+ index = previousFloatingIndex(floatingType, m_floats, *index); >+ if (!index) >+ return { }; >+ >+ if (m_floats[*index].displayBox().rectWithMargin().bottom() > currentBottom) >+ return index; >+ } >+ >+ ASSERT_NOT_REACHED(); >+ return { }; >+ }; >+ >+ // 1. Take the current floating from left and right and check which one's bottom edge is positioned higher (they could be on the same vertical position too). >+ // The current floats from left and right are considered the inner-most pair for the current vertical position. >+ // 2. Move away from inner-most pair by picking one of the previous floats in the list(#1) >+ // Ensure that the new floating's bottom edge is positioned lower than the current one -which essentially means skipping in-between floats that are positioned higher). >+ // 3. Reset the vertical position and align it with the new left-right pair. These floats are now the inner-most boxes for the current vertical position. >+ // As the result we have more horizontal space on the current vertical position. >+ auto leftBottom = m_current.left() ? std::optional<LayoutUnit>(m_current.left()->bottom()) : std::nullopt; >+ auto rightBottom = m_current.right() ? std::optional<LayoutUnit>(m_current.right()->bottom()) : std::nullopt; >+ >+ auto updateLeft = (leftBottom == rightBottom) || (!rightBottom || (leftBottom && leftBottom < rightBottom)); >+ auto updateRight = (leftBottom == rightBottom) || (!leftBottom || (rightBottom && leftBottom > rightBottom)); >+ >+ if (updateLeft) { >+ ASSERT(m_current.m_leftIndex); >+ m_current.m_verticalPosition = *leftBottom; >+ m_current.m_leftIndex = findPreviousFloatingWithLowerBottom(Float::Left, *m_current.m_leftIndex); >+ } >+ >+ if (updateRight) { >+ ASSERT(m_current.m_rightIndex); >+ m_current.m_verticalPosition = *rightBottom; >+ m_current.m_rightIndex = findPreviousFloatingWithLowerBottom(Float::Right, *m_current.m_rightIndex); >+ } >+ >+ return *this; >+} >+ >+void Iterator::set(LayoutUnit verticalPosition) >+{ >+ // Move the iterator to the initial vertical position by starting at the inner-most floating pair (last floats on left/right). >+ // 1. Check if the inner-most pair covers the vertical position. >+ // 2. Move outwards from the inner-most pair until the vertical postion intersects. >+ // (Note that verticalPosition has already been adjusted with the top of the last float.) >+ >+ m_current.m_verticalPosition = verticalPosition; >+ // No floats at all? >+ if (m_floats.isEmpty()) { >+ ASSERT_NOT_REACHED(); >+ >+ m_current.m_leftIndex = { }; >+ m_current.m_rightIndex = { }; >+ return; >+ } >+ >+ auto findFloatingBelow = [&](Float floatingType) -> std::optional<unsigned> { >+ >+ ASSERT(!m_floats.isEmpty()); >+ >+ auto index = floatingType == Float::Left ? m_current.m_leftIndex : m_current.m_rightIndex; >+ // Start from the end if we don't have current yet. >+ index = index.value_or(m_floats.size()); >+ while (true) { >+ index = previousFloatingIndex(floatingType, m_floats, *index); >+ if (!index) >+ return { }; >+ >+ auto bottom = m_floats[*index].displayBox().rectWithMargin().bottom(); >+ // Is this floating intrusive on this position? >+ if (bottom > verticalPosition) >+ return index; >+ } >+ >+ return { }; >+ }; >+ >+ m_current.m_leftIndex = findFloatingBelow(Float::Left); >+ m_current.m_rightIndex = findFloatingBelow(Float::Right); >+ >+ ASSERT(!m_current.m_leftIndex || (*m_current.m_leftIndex < m_floats.size() && m_floats[*m_current.m_leftIndex].layoutBox().isLeftFloatingPositioned())); >+ ASSERT(!m_current.m_rightIndex || (*m_current.m_rightIndex < m_floats.size() && m_floats[*m_current.m_rightIndex].layoutBox().isRightFloatingPositioned())); >+} >+ >+bool Iterator::operator==(const Iterator& other) const >+{ >+ return m_current == other.m_current; >+} >+ >+bool Iterator::operator!=(const Iterator& other) const >+{ >+ return !(*this == other); >+} >+ >+} >+} >+#endif >diff --git a/Source/WebCore/layout/floats/FloatingContext.h b/Source/WebCore/layout/floats/FloatingContext.h >new file mode 100644 >index 0000000000000000000000000000000000000000..d903a93da332c622bd5c7a3f4723f12fa95696a9 >--- /dev/null >+++ b/Source/WebCore/layout/floats/FloatingContext.h >@@ -0,0 +1,70 @@ >+/* >+ * 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. >+ */ >+ >+#pragma once >+ >+#if ENABLE(LAYOUT_FORMATTING_CONTEXT) >+ >+#include "FloatingState.h" >+#include "LayoutUnits.h" >+#include <wtf/IsoMalloc.h> >+ >+namespace WebCore { >+ >+namespace Layout { >+ >+class Box; >+class Container; >+class FloatingPair; >+class LayoutContext; >+ >+// FloatingContext is responsible for adjusting the position of a box in the current formatting context >+// by taking the floating boxes into account. >+class FloatingContext { >+ WTF_MAKE_ISO_ALLOCATED(FloatingContext); >+public: >+ FloatingContext(FloatingState&); >+ >+ FloatingState& floatingState() const { return m_floatingState; } >+ >+ Position positionForFloat(const Box&) const; >+ std::optional<LayoutUnit> verticalPositionWithClearance(const Box&) const; >+ >+private: >+ LayoutContext& layoutContext() const { return m_floatingState.layoutContext(); } >+ >+ Position floatingPosition(const FloatingState::FloatItem&) const; >+ >+ LayoutUnit initialVerticalPosition(const FloatingState::FloatItem&) const; >+ LayoutUnit alignWithContainingBlock(const FloatingState::FloatItem&) const; >+ LayoutUnit alignWithFloatings(const FloatingPair&, const FloatingState::FloatItem&) const; >+ Position toContainingBlock(const FloatingState::FloatItem&, Position) const; >+ >+ FloatingState& m_floatingState; >+}; >+ >+} >+} >+#endif >diff --git a/Source/WebCore/layout/floats/FloatingState.cpp b/Source/WebCore/layout/floats/FloatingState.cpp >new file mode 100644 >index 0000000000000000000000000000000000000000..a82ff8ad2b862bd15cdee75cf69cb2210077b386 >--- /dev/null >+++ b/Source/WebCore/layout/floats/FloatingState.cpp >@@ -0,0 +1,123 @@ >+/* >+ * 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 "FloatingState.h" >+ >+#if ENABLE(LAYOUT_FORMATTING_CONTEXT) >+ >+#include "FormattingContext.h" >+#include "LayoutBox.h" >+#include "LayoutContainer.h" >+#include "LayoutContext.h" >+#include <wtf/IsoMallocInlines.h> >+ >+namespace WebCore { >+namespace Layout { >+ >+WTF_MAKE_ISO_ALLOCATED_IMPL(FloatingState); >+ >+FloatingState::FloatItem::FloatItem(const Box& layoutBox, const FloatingState& floatingState) >+ : m_layoutBox(makeWeakPtr(const_cast<Box&>(layoutBox))) >+ , m_containingBlock(makeWeakPtr(const_cast<Container&>(*layoutBox.containingBlock()))) >+ , m_absoluteDisplayBox(FormattingContext::mapBoxToAncestor(floatingState.layoutContext(), layoutBox, downcast<Container>(floatingState.root()))) >+ , m_containingBlockAbsoluteDisplayBox(FormattingContext::mapBoxToAncestor(floatingState.layoutContext(), *m_containingBlock, downcast<Container>(floatingState.root()))) >+{ >+} >+ >+FloatingState::FloatingState(LayoutContext& layoutContext, const Box& formattingContextRoot) >+ : m_layoutContext(layoutContext) >+ , m_formattingContextRoot(makeWeakPtr(const_cast<Box&>(formattingContextRoot))) >+{ >+} >+ >+#ifndef NDEBUG >+static bool belongsToThisFloatingContext(const Box& layoutBox, const Box& floatingStateRoot) >+{ >+ auto& formattingContextRoot = layoutBox.formattingContextRoot(); >+ if (&formattingContextRoot == &floatingStateRoot) >+ return true; >+ >+ // Maybe the layout box belongs to an inline formatting context that inherits the floating state from the parent (block) formatting context. >+ if (!formattingContextRoot.establishesInlineFormattingContext()) >+ return false; >+ >+ return &formattingContextRoot.formattingContextRoot() == &floatingStateRoot; >+} >+#endif >+ >+void FloatingState::remove(const Box& layoutBox) >+{ >+ for (size_t index = 0; index < m_floats.size(); ++index) { >+ if (&m_floats[index].layoutBox() == &layoutBox) { >+ m_floats.remove(index); >+ return; >+ } >+ } >+ ASSERT_NOT_REACHED(); >+} >+ >+void FloatingState::append(const Box& layoutBox) >+{ >+ ASSERT(is<Container>(*m_formattingContextRoot)); >+ ASSERT(belongsToThisFloatingContext(layoutBox, *m_formattingContextRoot)); >+ >+ // Floating state should hold boxes with computed position/size. >+ ASSERT(m_layoutContext.displayBoxForLayoutBox(layoutBox)); >+ ASSERT(is<Container>(*m_formattingContextRoot)); >+ >+ m_floats.append({ layoutBox, *this }); >+} >+ >+std::optional<LayoutUnit> FloatingState::bottom(const Box& formattingContextRoot, Clear type) const >+{ >+ if (m_floats.isEmpty()) >+ return { }; >+ >+ // TODO: Currently this is only called once for each formatting context root with floats per layout. >+ // Cache the value if we end up calling it more frequently (and update it at append/remove). >+ std::optional<LayoutUnit> bottom; >+ for (auto& floatItem : m_floats) { >+ // Ignore floats from other formatting contexts when the floating state is inherited. >+ if (&formattingContextRoot != &floatItem.layoutBox().formattingContextRoot()) >+ continue; >+ >+ if ((type == Clear::Left && !floatItem.layoutBox().isLeftFloatingPositioned()) >+ || (type == Clear::Right && !floatItem.layoutBox().isRightFloatingPositioned())) >+ continue; >+ >+ auto floatsBottom = floatItem.displayBox().rectWithMargin().bottom(); >+ if (bottom) { >+ bottom = std::max(*bottom, floatsBottom); >+ continue; >+ } >+ bottom = floatsBottom; >+ } >+ return bottom; >+} >+ >+} >+} >+#endif >diff --git a/Source/WebCore/layout/floats/FloatingState.h b/Source/WebCore/layout/floats/FloatingState.h >new file mode 100644 >index 0000000000000000000000000000000000000000..9a7e2b424f8c79e4423ad3692bdca69c2b172b77 >--- /dev/null >+++ b/Source/WebCore/layout/floats/FloatingState.h >@@ -0,0 +1,111 @@ >+/* >+ * 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. >+ */ >+ >+#pragma once >+ >+#if ENABLE(LAYOUT_FORMATTING_CONTEXT) >+ >+#include "DisplayBox.h" >+#include <wtf/IsoMalloc.h> >+#include <wtf/Ref.h> >+#include <wtf/WeakPtr.h> >+ >+namespace WebCore { >+ >+namespace Layout { >+ >+class Box; >+class Container; >+class FormattingState; >+class LayoutContext; >+ >+// FloatingState holds the floating boxes per formatting context. >+class FloatingState : public RefCounted<FloatingState> { >+ WTF_MAKE_ISO_ALLOCATED(FloatingState); >+public: >+ static Ref<FloatingState> create(LayoutContext& layoutContext, const Box& formattingContextRoot) { return adoptRef(*new FloatingState(layoutContext, formattingContextRoot)); } >+ >+ void append(const Box& layoutBox); >+ 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 { >+ public: >+ FloatItem(const Box&, const FloatingState&); >+ >+ const Box& layoutBox() const { return *m_layoutBox; } >+ const Container& containingBlock() const { return *m_containingBlock; } >+ >+ const Display::Box& displayBox() const { return m_absoluteDisplayBox; } >+ const Display::Box& containingBlockDisplayBox() const { return m_containingBlockAbsoluteDisplayBox; } >+ >+ private: >+ WeakPtr<Box> m_layoutBox; >+ WeakPtr<Container> m_containingBlock; >+ >+ Display::Box m_absoluteDisplayBox; >+ Display::Box m_containingBlockAbsoluteDisplayBox; >+ }; >+ using FloatList = Vector<FloatItem>; >+ const FloatList& floats() const { return m_floats; } >+ const FloatItem* last() const { return isEmpty() ? nullptr : &m_floats.last(); } >+ >+private: >+ friend class FloatingContext; >+ FloatingState(LayoutContext&, const Box& formattingContextRoot); >+ >+ LayoutContext& layoutContext() const { return m_layoutContext; } >+ const Box& root() const { return *m_formattingContextRoot; } >+ >+ std::optional<LayoutUnit> bottom(const Box& formattingContextRoot, Clear) const; >+ >+ LayoutContext& m_layoutContext; >+ WeakPtr<Box> m_formattingContextRoot; >+ FloatList m_floats; >+}; >+ >+inline std::optional<LayoutUnit> FloatingState::leftBottom(const Box& formattingContextRoot) const >+{ >+ return bottom(formattingContextRoot, Clear::Left); >+} >+ >+inline std::optional<LayoutUnit> FloatingState::rightBottom(const Box& formattingContextRoot) const >+{ >+ return bottom(formattingContextRoot, Clear::Right); >+} >+ >+inline std::optional<LayoutUnit> FloatingState::bottom(const Box& formattingContextRoot) const >+{ >+ return bottom(formattingContextRoot, Clear::Both); >+} >+ >+} >+} >+#endif
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 188846
:
347790
|
347791
|
347801
|
347806