a82ff8ad2b862bd15cdee75cf69cb2210077b386
[WebKit-https.git] / Source / WebCore / layout / floats / FloatingState.cpp
1 /*
2  * Copyright (C) 2018 Apple Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "FloatingState.h"
28
29 #if ENABLE(LAYOUT_FORMATTING_CONTEXT)
30
31 #include "FormattingContext.h"
32 #include "LayoutBox.h"
33 #include "LayoutContainer.h"
34 #include "LayoutContext.h"
35 #include <wtf/IsoMallocInlines.h>
36
37 namespace WebCore {
38 namespace Layout {
39
40 WTF_MAKE_ISO_ALLOCATED_IMPL(FloatingState);
41
42 FloatingState::FloatItem::FloatItem(const Box& layoutBox, const FloatingState& floatingState)
43     : m_layoutBox(makeWeakPtr(const_cast<Box&>(layoutBox)))
44     , m_containingBlock(makeWeakPtr(const_cast<Container&>(*layoutBox.containingBlock())))
45     , m_absoluteDisplayBox(FormattingContext::mapBoxToAncestor(floatingState.layoutContext(), layoutBox, downcast<Container>(floatingState.root())))
46     , m_containingBlockAbsoluteDisplayBox(FormattingContext::mapBoxToAncestor(floatingState.layoutContext(), *m_containingBlock, downcast<Container>(floatingState.root())))
47 {
48 }
49
50 FloatingState::FloatingState(LayoutContext& layoutContext, const Box& formattingContextRoot)
51     : m_layoutContext(layoutContext)
52     , m_formattingContextRoot(makeWeakPtr(const_cast<Box&>(formattingContextRoot)))
53 {
54 }
55
56 #ifndef NDEBUG
57 static bool belongsToThisFloatingContext(const Box& layoutBox, const Box& floatingStateRoot)
58 {
59     auto& formattingContextRoot = layoutBox.formattingContextRoot();
60     if (&formattingContextRoot == &floatingStateRoot)
61         return true;
62
63     // Maybe the layout box belongs to an inline formatting context that inherits the floating state from the parent (block) formatting context. 
64     if (!formattingContextRoot.establishesInlineFormattingContext())
65         return false;
66
67     return &formattingContextRoot.formattingContextRoot() == &floatingStateRoot;
68 }
69 #endif
70
71 void FloatingState::remove(const Box& layoutBox)
72 {
73     for (size_t index = 0; index < m_floats.size(); ++index) {
74         if (&m_floats[index].layoutBox() == &layoutBox) {
75             m_floats.remove(index);
76             return;
77         }
78     }
79     ASSERT_NOT_REACHED();
80 }
81
82 void FloatingState::append(const Box& layoutBox)
83 {
84     ASSERT(is<Container>(*m_formattingContextRoot));
85     ASSERT(belongsToThisFloatingContext(layoutBox, *m_formattingContextRoot));
86
87     // Floating state should hold boxes with computed position/size.
88     ASSERT(m_layoutContext.displayBoxForLayoutBox(layoutBox));
89     ASSERT(is<Container>(*m_formattingContextRoot));
90
91     m_floats.append({ layoutBox, *this });
92 }
93
94 std::optional<LayoutUnit> FloatingState::bottom(const Box& formattingContextRoot, Clear type) const
95 {
96     if (m_floats.isEmpty())
97         return { };
98
99     // TODO: Currently this is only called once for each formatting context root with floats per layout.
100     // Cache the value if we end up calling it more frequently (and update it at append/remove).
101     std::optional<LayoutUnit> bottom;
102     for (auto& floatItem : m_floats) {
103         // Ignore floats from other formatting contexts when the floating state is inherited.
104         if (&formattingContextRoot != &floatItem.layoutBox().formattingContextRoot())
105             continue;
106
107         if ((type == Clear::Left && !floatItem.layoutBox().isLeftFloatingPositioned())
108             || (type == Clear::Right && !floatItem.layoutBox().isRightFloatingPositioned()))
109             continue;
110
111         auto floatsBottom = floatItem.displayBox().rectWithMargin().bottom();
112         if (bottom) {
113             bottom = std::max(*bottom, floatsBottom);
114             continue;
115         }
116         bottom = floatsBottom;
117     }
118     return bottom;
119 }
120
121 }
122 }
123 #endif