OLD | NEW |
| (Empty) |
1 /* | |
2 * Copyright (C) 2011 Adobe Systems Incorporated. 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 * | |
8 * 1. Redistributions of source code must retain the above | |
9 * copyright notice, this list of conditions and the following | |
10 * disclaimer. | |
11 * 2. Redistributions in binary form must reproduce the above | |
12 * copyright notice, this list of conditions and the following | |
13 * disclaimer in the documentation and/or other materials | |
14 * provided with the distribution. | |
15 * | |
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY | |
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR | |
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE | |
20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, | |
21 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | |
22 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | |
23 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR | |
25 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF | |
26 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
27 * SUCH DAMAGE. | |
28 */ | |
29 | |
30 #ifndef RenderFlowThread_h | |
31 #define RenderFlowThread_h | |
32 | |
33 | |
34 #include "core/rendering/RenderBlockFlow.h" | |
35 #include "wtf/HashCountedSet.h" | |
36 #include "wtf/ListHashSet.h" | |
37 #include "wtf/PassRefPtr.h" | |
38 | |
39 namespace WebCore { | |
40 | |
41 struct LayerFragment; | |
42 typedef Vector<LayerFragment, 1> LayerFragments; | |
43 class RenderFlowThread; | |
44 class RenderStyle; | |
45 class RenderRegion; | |
46 | |
47 typedef ListHashSet<RenderRegion*> RenderRegionList; | |
48 | |
49 // RenderFlowThread is used to collect all the render objects that participate i
n a | |
50 // flow thread. It will also help in doing the layout. However, it will not rend
er | |
51 // directly to screen. Instead, RenderRegion objects will redirect their paint | |
52 // and nodeAtPoint methods to this object. Each RenderRegion will actually be a
viewPort | |
53 // of the RenderFlowThread. | |
54 | |
55 class RenderFlowThread: public RenderBlockFlow { | |
56 public: | |
57 RenderFlowThread(); | |
58 virtual ~RenderFlowThread() { }; | |
59 | |
60 virtual bool isRenderFlowThread() const OVERRIDE FINAL { return true; } | |
61 | |
62 virtual void layout() OVERRIDE FINAL; | |
63 | |
64 // Always create a RenderLayer for the RenderFlowThread so that we | |
65 // can easily avoid drawing the children directly. | |
66 virtual LayerType layerTypeRequired() const OVERRIDE FINAL { return NormalLa
yer; } | |
67 | |
68 virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTes
tLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAct
ion) OVERRIDE FINAL; | |
69 | |
70 void removeFlowChildInfo(RenderObject*); | |
71 #ifndef NDEBUG | |
72 bool hasChildInfo(RenderObject* child) const { return child && child->isBox(
) && m_regionRangeMap.contains(toRenderBox(child)); } | |
73 #endif | |
74 | |
75 virtual void addRegionToThread(RenderRegion*); | |
76 virtual void removeRegionFromThread(RenderRegion*); | |
77 const RenderRegionList& renderRegionList() const { return m_regionList; } | |
78 | |
79 virtual void updateLogicalWidth() OVERRIDE FINAL; | |
80 virtual void computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logic
alTop, LogicalExtentComputedValues&) const OVERRIDE; | |
81 | |
82 void paintFlowThreadPortionInRegion(PaintInfo&, RenderRegion*, const LayoutR
ect& flowThreadPortionRect, const LayoutRect& flowThreadPortionOverflowRect, con
st LayoutPoint&) const; | |
83 bool hitTestFlowThreadPortionInRegion(RenderRegion*, const LayoutRect& flowT
hreadPortionRect, const LayoutRect& flowThreadPortionOverflowRect, const HitTest
Request&, HitTestResult&, const HitTestLocation& locationInContainer, const Layo
utPoint& accumulatedOffset) const; | |
84 | |
85 bool hasRegions() const { return m_regionList.size(); } | |
86 // Check if the content is flown into at least a region with region styling
rules. | |
87 bool hasRegionsWithStyling() const { return m_hasRegionsWithStyling; } | |
88 void checkRegionsWithStyling(); | |
89 virtual void regionChangedWritingMode(RenderRegion*) { } | |
90 | |
91 void validateRegions(); | |
92 void invalidateRegions(); | |
93 bool hasValidRegionInfo() const { return !m_regionsInvalidated && !m_regionL
ist.isEmpty(); } | |
94 | |
95 static PassRefPtr<RenderStyle> createFlowThreadStyle(RenderStyle* parentStyl
e); | |
96 | |
97 virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) OV
ERRIDE; | |
98 | |
99 void repaintRectangleInRegions(const LayoutRect&) const; | |
100 | |
101 LayoutPoint adjustedPositionRelativeToOffsetParent(const RenderBoxModelObjec
t&, const LayoutPoint&); | |
102 | |
103 LayoutUnit pageLogicalTopForOffset(LayoutUnit); | |
104 LayoutUnit pageLogicalWidthForOffset(LayoutUnit); | |
105 LayoutUnit pageLogicalHeightForOffset(LayoutUnit); | |
106 LayoutUnit pageRemainingLogicalHeightForOffset(LayoutUnit, PageBoundaryRule
= IncludePageBoundary); | |
107 | |
108 virtual void setPageBreak(LayoutUnit /*offset*/, LayoutUnit /*spaceShortage*
/) { } | |
109 virtual void updateMinimumPageHeight(LayoutUnit /*offset*/, LayoutUnit /*min
Height*/) { } | |
110 | |
111 enum RegionAutoGenerationPolicy { | |
112 AllowRegionAutoGeneration, | |
113 DisallowRegionAutoGeneration, | |
114 }; | |
115 RenderRegion* regionAtBlockOffset(LayoutUnit, bool extendLastRegion = false,
RegionAutoGenerationPolicy = AllowRegionAutoGeneration); | |
116 | |
117 RenderRegion* regionFromAbsolutePointAndBox(IntPoint, const RenderBox* flowe
dBox); | |
118 | |
119 bool regionsHaveUniformLogicalWidth() const { return m_regionsHaveUniformLog
icalWidth; } | |
120 bool regionsHaveUniformLogicalHeight() const { return m_regionsHaveUniformLo
gicalHeight; } | |
121 | |
122 RenderRegion* mapFromFlowToRegion(TransformState&) const; | |
123 | |
124 void removeRenderBoxRegionInfo(RenderBox*); | |
125 bool logicalWidthChangedInRegionsForBlock(const RenderBlock*); | |
126 | |
127 LayoutUnit contentLogicalWidthOfFirstRegion() const; | |
128 LayoutUnit contentLogicalHeightOfFirstRegion() const; | |
129 LayoutUnit contentLogicalLeftOfFirstRegion() const; | |
130 | |
131 RenderRegion* firstRegion() const; | |
132 RenderRegion* lastRegion() const; | |
133 | |
134 bool previousRegionCountChanged() const { return m_previousRegionCount != m_
regionList.size(); } | |
135 void updatePreviousRegionCount() { m_previousRegionCount = m_regionList.size
(); } | |
136 | |
137 void setRegionRangeForBox(const RenderBox*, LayoutUnit offsetFromLogicalTopO
fFirstPage); | |
138 void getRegionRangeForBox(const RenderBox*, RenderRegion*& startRegion, Rend
erRegion*& endRegion) const; | |
139 | |
140 void clearRenderObjectCustomStyle(const RenderObject*, | |
141 const RenderRegion* oldStartRegion = 0, const RenderRegion* oldEndRegion
= 0, | |
142 const RenderRegion* newStartRegion = 0, const RenderRegion* newEndRegion
= 0); | |
143 | |
144 // Check if the object is in region and the region is part of this flow thre
ad. | |
145 bool objectInFlowRegion(const RenderObject*, const RenderRegion*) const; | |
146 | |
147 void markAutoLogicalHeightRegionsForLayout(); | |
148 | |
149 bool addForcedRegionBreak(LayoutUnit, RenderObject* breakChild, bool isBefor
e, LayoutUnit* offsetBreakAdjustment = 0); | |
150 void applyBreakAfterContent(LayoutUnit); | |
151 | |
152 bool pageLogicalSizeChanged() const { return m_pageLogicalSizeChanged; } | |
153 | |
154 bool hasAutoLogicalHeightRegions() const { ASSERT(isAutoLogicalHeightRegions
CountConsistent()); return m_autoLogicalHeightRegionsCount; } | |
155 void incrementAutoLogicalHeightRegions(); | |
156 void decrementAutoLogicalHeightRegions(); | |
157 | |
158 #ifndef NDEBUG | |
159 bool isAutoLogicalHeightRegionsCountConsistent() const; | |
160 #endif | |
161 | |
162 void collectLayerFragments(LayerFragments&, const LayoutRect& layerBoundingB
ox, const LayoutRect& dirtyRect); | |
163 LayoutRect fragmentsBoundingBox(const LayoutRect& layerBoundingBox); | |
164 | |
165 void setInConstrainedLayoutPhase(bool value) { m_inConstrainedLayoutPhase =
value; } | |
166 bool inConstrainedLayoutPhase() const { return m_inConstrainedLayoutPhase; } | |
167 | |
168 bool needsTwoPhasesLayout() const { return m_needsTwoPhasesLayout; } | |
169 void clearNeedsTwoPhasesLayout() { m_needsTwoPhasesLayout = false; } | |
170 | |
171 void pushFlowThreadLayoutState(const RenderObject*); | |
172 void popFlowThreadLayoutState(); | |
173 LayoutUnit offsetFromLogicalTopOfFirstRegion(const RenderBlock*) const; | |
174 | |
175 // Used to estimate the maximum height of the flow thread. | |
176 static LayoutUnit maxLogicalHeight() { return LayoutUnit::max() / 2; } | |
177 | |
178 protected: | |
179 virtual const char* renderName() const = 0; | |
180 | |
181 // Overridden by columns/pages to set up an initial logical width of the pag
e width even when | |
182 // no regions have been generated yet. | |
183 virtual LayoutUnit initialLogicalWidth() const { return 0; }; | |
184 | |
185 virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContai
ner, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed =
0) const OVERRIDE FINAL; | |
186 | |
187 void updateRegionsFlowThreadPortionRect(const RenderRegion* = 0); | |
188 bool shouldRepaint(const LayoutRect&) const; | |
189 bool regionInRange(const RenderRegion* targetRegion, const RenderRegion* sta
rtRegion, const RenderRegion* endRegion) const; | |
190 | |
191 LayoutRect computeRegionClippingRect(const LayoutPoint&, const LayoutRect&,
const LayoutRect&) const; | |
192 | |
193 void setDispatchRegionLayoutUpdateEvent(bool value) { m_dispatchRegionLayout
UpdateEvent = value; } | |
194 bool shouldDispatchRegionLayoutUpdateEvent() { return m_dispatchRegionLayout
UpdateEvent; } | |
195 | |
196 void setDispatchRegionOversetChangeEvent(bool value) { m_dispatchRegionOvers
etChangeEvent = value; } | |
197 bool shouldDispatchRegionOversetChangeEvent() const { return m_dispatchRegio
nOversetChangeEvent; } | |
198 | |
199 // Override if the flow thread implementation supports dispatching events wh
en the flow layout is updated (e.g. for named flows) | |
200 virtual void dispatchRegionLayoutUpdateEvent() { m_dispatchRegionLayoutUpdat
eEvent = false; } | |
201 virtual void dispatchRegionOversetChangeEvent() { m_dispatchRegionOversetCha
ngeEvent = false; } | |
202 | |
203 void initializeRegionsComputedAutoHeight(RenderRegion* = 0); | |
204 | |
205 virtual void autoGenerateRegionsToBlockOffset(LayoutUnit) { }; | |
206 | |
207 bool cachedOffsetFromLogicalTopOfFirstRegion(const RenderBox*, LayoutUnit&)
const; | |
208 void setOffsetFromLogicalTopOfFirstRegion(const RenderBox*, LayoutUnit); | |
209 void clearOffsetFromLogicalTopOfFirstRegion(const RenderBox*); | |
210 | |
211 const RenderBox* currentStatePusherRenderBox() const; | |
212 | |
213 RenderRegionList m_regionList; | |
214 unsigned short m_previousRegionCount; | |
215 | |
216 class RenderRegionRange { | |
217 public: | |
218 RenderRegionRange() | |
219 { | |
220 setRange(0, 0); | |
221 } | |
222 | |
223 RenderRegionRange(RenderRegion* start, RenderRegion* end) | |
224 { | |
225 setRange(start, end); | |
226 } | |
227 | |
228 void setRange(RenderRegion* start, RenderRegion* end) | |
229 { | |
230 m_startRegion = start; | |
231 m_endRegion = end; | |
232 } | |
233 | |
234 RenderRegion* startRegion() const { return m_startRegion; } | |
235 RenderRegion* endRegion() const { return m_endRegion; } | |
236 | |
237 private: | |
238 RenderRegion* m_startRegion; | |
239 RenderRegion* m_endRegion; | |
240 }; | |
241 | |
242 typedef PODInterval<LayoutUnit, RenderRegion*> RegionInterval; | |
243 typedef PODIntervalTree<LayoutUnit, RenderRegion*> RegionIntervalTree; | |
244 | |
245 class RegionSearchAdapter { | |
246 public: | |
247 RegionSearchAdapter(LayoutUnit offset) | |
248 : m_offset(offset) | |
249 , m_result(0) | |
250 { | |
251 } | |
252 | |
253 const LayoutUnit& lowValue() const { return m_offset; } | |
254 const LayoutUnit& highValue() const { return m_offset; } | |
255 void collectIfNeeded(const RegionInterval&); | |
256 | |
257 RenderRegion* result() const { return m_result; } | |
258 | |
259 private: | |
260 LayoutUnit m_offset; | |
261 RenderRegion* m_result; | |
262 }; | |
263 | |
264 // A maps from RenderBox | |
265 typedef HashMap<const RenderBox*, RenderRegionRange> RenderRegionRangeMap; | |
266 RenderRegionRangeMap m_regionRangeMap; | |
267 | |
268 typedef HashMap<RenderObject*, RenderRegion*> RenderObjectToRegionMap; | |
269 RenderObjectToRegionMap m_breakBeforeToRegionMap; | |
270 RenderObjectToRegionMap m_breakAfterToRegionMap; | |
271 | |
272 // Stack of objects that pushed a LayoutState object on the RenderView. The | |
273 // objects on the stack are the ones that are curently in the process of bei
ng | |
274 // laid out. | |
275 ListHashSet<const RenderObject*> m_statePusherObjectsStack; | |
276 typedef HashMap<const RenderBox*, LayoutUnit> RenderBoxToOffsetMap; | |
277 RenderBoxToOffsetMap m_boxesToOffsetMap; | |
278 | |
279 unsigned m_autoLogicalHeightRegionsCount; | |
280 | |
281 RegionIntervalTree m_regionIntervalTree; | |
282 | |
283 bool m_regionsInvalidated : 1; | |
284 bool m_regionsHaveUniformLogicalWidth : 1; | |
285 bool m_regionsHaveUniformLogicalHeight : 1; | |
286 bool m_hasRegionsWithStyling : 1; | |
287 bool m_dispatchRegionLayoutUpdateEvent : 1; | |
288 bool m_dispatchRegionOversetChangeEvent : 1; | |
289 bool m_pageLogicalSizeChanged : 1; | |
290 bool m_inConstrainedLayoutPhase : 1; | |
291 bool m_needsTwoPhasesLayout : 1; | |
292 | |
293 private: | |
294 virtual bool supportsPartialLayout() const OVERRIDE FINAL { return false; } | |
295 | |
296 }; | |
297 | |
298 DEFINE_RENDER_OBJECT_TYPE_CASTS(RenderFlowThread, isRenderFlowThread()); | |
299 | |
300 class CurrentRenderFlowThreadMaintainer { | |
301 WTF_MAKE_NONCOPYABLE(CurrentRenderFlowThreadMaintainer); | |
302 public: | |
303 CurrentRenderFlowThreadMaintainer(RenderFlowThread*); | |
304 ~CurrentRenderFlowThreadMaintainer(); | |
305 private: | |
306 RenderFlowThread* m_renderFlowThread; | |
307 RenderFlowThread* m_previousRenderFlowThread; | |
308 }; | |
309 | |
310 // These structures are used by PODIntervalTree for debugging. | |
311 #ifndef NDEBUG | |
312 template <> struct ValueToString<LayoutUnit> { | |
313 static String string(const LayoutUnit value) { return String::number(value.t
oFloat()); } | |
314 }; | |
315 | |
316 template <> struct ValueToString<RenderRegion*> { | |
317 static String string(const RenderRegion* value) { return String::format("%p"
, value); } | |
318 }; | |
319 #endif | |
320 | |
321 } // namespace WebCore | |
322 | |
323 #endif // RenderFlowThread_h | |
OLD | NEW |