1 | /* |
2 | * Copyright (C) 2000 Lars Knoll (knoll@kde.org) |
3 | * Copyright (C) 2003, 2004, 2006, 2007, 2008, 2009, 2010, 2011 Apple Inc. All right reserved. |
4 | * Copyright (C) 2010 Google Inc. All rights reserved. |
5 | * Copyright (C) 2013 ChangSeok Oh <shivamidow@gmail.com> |
6 | * Copyright (C) 2013 Adobe Systems Incorporated. All rights reserved. |
7 | * |
8 | * Redistribution and use in source and binary forms, with or without |
9 | * modification, are permitted provided that the following conditions |
10 | * are met: |
11 | * |
12 | * 1. Redistributions of source code must retain the above |
13 | * copyright notice, this list of conditions and the following |
14 | * disclaimer. |
15 | * 2. Redistributions in binary form must reproduce the above |
16 | * copyright notice, this list of conditions and the following |
17 | * disclaimer in the documentation and/or other materials |
18 | * provided with the distribution. |
19 | * |
20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
21 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
22 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
23 | * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
24 | * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, |
25 | * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
26 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR |
27 | * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
28 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
29 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
30 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED |
31 | * OF THE POSSIBILITY OF SUCH DAMAGE. |
32 | */ |
33 | |
34 | #pragma once |
35 | |
36 | #include "LayoutRect.h" |
37 | #include "RenderBlockFlow.h" |
38 | #include <wtf/RefCounted.h> |
39 | |
40 | namespace WebCore { |
41 | |
42 | class FloatWithRect : public RefCounted<FloatWithRect> { |
43 | WTF_MAKE_FAST_ALLOCATED; |
44 | public: |
45 | static Ref<FloatWithRect> create(RenderBox& renderer) |
46 | { |
47 | return adoptRef(*new FloatWithRect(renderer)); |
48 | } |
49 | |
50 | RenderBox& renderer() const { return m_renderer; } |
51 | LayoutRect rect() const { return m_rect; } |
52 | bool everHadLayout() const { return m_everHadLayout; } |
53 | |
54 | void adjustRect(const LayoutRect& rect) { m_rect = rect; } |
55 | |
56 | private: |
57 | FloatWithRect(RenderBox& renderer) |
58 | : m_renderer(renderer) |
59 | , m_rect(LayoutRect(renderer.x() - renderer.marginLeft(), renderer.y() - renderer.marginTop(), renderer.width() + renderer.horizontalMarginExtent(), renderer.height() + renderer.verticalMarginExtent())) |
60 | , m_everHadLayout(renderer.everHadLayout()) |
61 | { |
62 | } |
63 | |
64 | RenderBox& m_renderer; |
65 | LayoutRect m_rect; |
66 | bool m_everHadLayout { false }; |
67 | }; |
68 | |
69 | // Like LayoutState for layout(), LineLayoutState keeps track of global information |
70 | // during an entire linebox tree layout pass (aka layoutInlineChildren). |
71 | class LineLayoutState { |
72 | public: |
73 | class FloatList { |
74 | public: |
75 | void append(Ref<FloatWithRect>&& floatWithRect) |
76 | { |
77 | m_floats.add(floatWithRect.copyRef()); |
78 | m_floatWithRectMap.add(&floatWithRect->renderer(), WTFMove(floatWithRect)); |
79 | } |
80 | void setLastFloat(FloatingObject* lastFloat) { m_lastFloat = lastFloat; } |
81 | FloatingObject* lastFloat() const { return m_lastFloat; } |
82 | |
83 | void setLastCleanFloat(RenderBox& floatBox) { m_lastCleanFloat = &floatBox; } |
84 | RenderBox* lastCleanFloat() const { return m_lastCleanFloat; } |
85 | |
86 | FloatWithRect* floatWithRect(RenderBox& floatBox) const { return m_floatWithRectMap.get(&floatBox); } |
87 | |
88 | using Iterator = ListHashSet<Ref<FloatWithRect>>::iterator; |
89 | Iterator begin() { return m_floats.begin(); } |
90 | Iterator end() { return m_floats.end(); } |
91 | Iterator find(FloatWithRect& floatBoxWithRect) { return m_floats.find(floatBoxWithRect); } |
92 | bool isEmpty() const { return m_floats.isEmpty(); } |
93 | |
94 | private: |
95 | ListHashSet<Ref<FloatWithRect>> m_floats; |
96 | HashMap<RenderBox*, Ref<FloatWithRect>> m_floatWithRectMap; |
97 | FloatingObject* m_lastFloat { nullptr }; |
98 | RenderBox* m_lastCleanFloat { nullptr }; |
99 | }; |
100 | |
101 | LineLayoutState(const RenderBlockFlow& blockFlow, bool fullLayout, LayoutUnit& repaintLogicalTop, LayoutUnit& repaintLogicalBottom, RenderFragmentedFlow* fragmentedFlow) |
102 | : m_fragmentedFlow(fragmentedFlow) |
103 | , m_repaintLogicalTop(repaintLogicalTop) |
104 | , m_repaintLogicalBottom(repaintLogicalBottom) |
105 | , m_marginInfo(blockFlow, blockFlow.borderAndPaddingBefore(), blockFlow.borderAndPaddingAfter() + blockFlow.scrollbarLogicalHeight()) |
106 | , m_endLineMatched(false) |
107 | , m_checkForFloatsFromLastLine(false) |
108 | , m_isFullLayout(fullLayout) |
109 | , m_usesRepaintBounds(false) |
110 | { |
111 | } |
112 | |
113 | LineInfo& lineInfo() { return m_lineInfo; } |
114 | const LineInfo& lineInfo() const { return m_lineInfo; } |
115 | |
116 | LayoutUnit endLineLogicalTop() const { return m_endLineLogicalTop; } |
117 | void setEndLineLogicalTop(LayoutUnit logicalTop) { m_endLineLogicalTop = logicalTop; } |
118 | |
119 | RootInlineBox* endLine() const { return m_endLine; } |
120 | void setEndLine(RootInlineBox* line) { m_endLine = line; } |
121 | |
122 | LayoutUnit adjustedLogicalLineTop() const { return m_adjustedLogicalLineTop; } |
123 | void setAdjustedLogicalLineTop(LayoutUnit value) { m_adjustedLogicalLineTop = value; } |
124 | |
125 | RenderFragmentedFlow* fragmentedFlow() const { return m_fragmentedFlow; } |
126 | void setFragmentedFlow(RenderFragmentedFlow* thread) { m_fragmentedFlow = thread; } |
127 | |
128 | bool endLineMatched() const { return m_endLineMatched; } |
129 | void setEndLineMatched(bool endLineMatched) { m_endLineMatched = endLineMatched; } |
130 | |
131 | bool checkForFloatsFromLastLine() const { return m_checkForFloatsFromLastLine; } |
132 | void setCheckForFloatsFromLastLine(bool check) { m_checkForFloatsFromLastLine = check; } |
133 | |
134 | void markForFullLayout() { m_isFullLayout = true; } |
135 | bool isFullLayout() const { return m_isFullLayout; } |
136 | |
137 | bool usesRepaintBounds() const { return m_usesRepaintBounds; } |
138 | |
139 | void setRepaintRange(LayoutUnit logicalHeight) |
140 | { |
141 | m_usesRepaintBounds = true; |
142 | m_repaintLogicalTop = m_repaintLogicalBottom = logicalHeight; |
143 | } |
144 | |
145 | void updateRepaintRangeFromBox(RootInlineBox* box, LayoutUnit = 0_lu) |
146 | { |
147 | m_usesRepaintBounds = true; |
148 | m_repaintLogicalTop = std::min(m_repaintLogicalTop, box->logicalTopVisualOverflow() + std::min<LayoutUnit>(paginationDelta, 0)); |
149 | m_repaintLogicalBottom = std::max(m_repaintLogicalBottom, box->logicalBottomVisualOverflow() + std::max<LayoutUnit>(paginationDelta, 0)); |
150 | } |
151 | |
152 | RenderBlockFlow::MarginInfo& marginInfo() { return m_marginInfo; } |
153 | |
154 | FloatList& floatList() { return m_floatList; } |
155 | |
156 | private: |
157 | LineInfo m_lineInfo; |
158 | LayoutUnit m_endLineLogicalTop; |
159 | RootInlineBox* m_endLine { nullptr }; |
160 | |
161 | LayoutUnit m_adjustedLogicalLineTop; |
162 | |
163 | RenderFragmentedFlow* m_fragmentedFlow { nullptr }; |
164 | |
165 | FloatList m_floatList; |
166 | // FIXME: Should this be a range object instead of two ints? |
167 | LayoutUnit& m_repaintLogicalTop; |
168 | LayoutUnit& m_repaintLogicalBottom; |
169 | |
170 | RenderBlockFlow::MarginInfo m_marginInfo; |
171 | |
172 | bool m_endLineMatched : 1; |
173 | bool m_checkForFloatsFromLastLine : 1; |
174 | bool m_isFullLayout : 1; |
175 | bool m_usesRepaintBounds : 1; |
176 | }; |
177 | |
178 | } // namespace WebCore |
179 | |