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
40namespace WebCore {
41
42class FloatWithRect : public RefCounted<FloatWithRect> {
43 WTF_MAKE_FAST_ALLOCATED;
44public:
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
56private:
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).
71class LineLayoutState {
72public:
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 paginationDelta = 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
156private:
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