Protect some RenderFlowThread functions.
[WebKit-https.git] / Source / WebCore / rendering / RenderFlowThread.h
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 "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 RenderNamedFlowFragment;
45 class RenderStyle;
46 class RenderRegion;
47
48 typedef ListHashSet<RenderRegion*> RenderRegionList;
49 typedef Vector<RenderLayer*> RenderLayerList;
50 typedef HashMap<RenderNamedFlowFragment*, RenderLayerList> RegionToLayerListMap;
51 typedef HashMap<RenderLayer*, RenderNamedFlowFragment*> LayerToRegionMap;
52
53 // RenderFlowThread is used to collect all the render objects that participate in a
54 // flow thread. It will also help in doing the layout. However, it will not render
55 // directly to screen. Instead, RenderRegion objects will redirect their paint 
56 // and nodeAtPoint methods to this object. Each RenderRegion will actually be a viewPort
57 // of the RenderFlowThread.
58
59 class RenderFlowThread: public RenderBlockFlow {
60 public:
61     virtual ~RenderFlowThread() { }
62
63     virtual void removeFlowChildInfo(RenderObject*);
64 #ifndef NDEBUG
65     bool hasChildInfo(RenderObject* child) const { return child && child->isBox() && m_regionRangeMap.contains(toRenderBox(child)); }
66 #endif
67
68     virtual void addRegionToThread(RenderRegion*);
69     virtual void removeRegionFromThread(RenderRegion*);
70     const RenderRegionList& renderRegionList() const { return m_regionList; }
71
72     virtual void updateLogicalWidth() override final;
73     virtual void computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues&) const override;
74
75     virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) override;
76
77     bool hasRegions() const { return m_regionList.size(); }
78     virtual void regionChangedWritingMode(RenderRegion*) { }
79
80     void validateRegions();
81     void invalidateRegions();
82     bool hasValidRegionInfo() const { return !m_regionsInvalidated && !m_regionList.isEmpty(); }
83
84     static PassRef<RenderStyle> createFlowThreadStyle(RenderStyle* parentStyle);
85
86     virtual void styleDidChange(StyleDifference, const RenderStyle* oldStyle) override;
87
88     void repaintRectangleInRegions(const LayoutRect&, bool immediate) const;
89     
90     LayoutPoint adjustedPositionRelativeToOffsetParent(const RenderBoxModelObject&, const LayoutPoint&);
91
92     LayoutUnit pageLogicalTopForOffset(LayoutUnit);
93     LayoutUnit pageLogicalWidthForOffset(LayoutUnit);
94     LayoutUnit pageLogicalHeightForOffset(LayoutUnit);
95     LayoutUnit pageRemainingLogicalHeightForOffset(LayoutUnit, PageBoundaryRule = IncludePageBoundary);
96
97     virtual void setPageBreak(const RenderBlock*, LayoutUnit /*offset*/, LayoutUnit /*spaceShortage*/) { }
98     virtual void updateMinimumPageHeight(const RenderBlock*, LayoutUnit /*offset*/, LayoutUnit /*minHeight*/) { }
99
100     enum RegionAutoGenerationPolicy {
101         AllowRegionAutoGeneration,
102         DisallowRegionAutoGeneration,
103     };
104
105     RenderRegion* regionAtBlockOffset(const RenderBox*, LayoutUnit, bool extendLastRegion = false, RegionAutoGenerationPolicy = AllowRegionAutoGeneration);
106
107     RenderRegion* regionFromAbsolutePointAndBox(const IntPoint&, const RenderBox& flowedBox);
108
109     bool regionsHaveUniformLogicalWidth() const { return m_regionsHaveUniformLogicalWidth; }
110     bool regionsHaveUniformLogicalHeight() const { return m_regionsHaveUniformLogicalHeight; }
111
112     RenderRegion* mapFromFlowToRegion(TransformState&) const;
113
114     void removeRenderBoxRegionInfo(RenderBox*);
115     void logicalWidthChangedInRegionsForBlock(const RenderBlock*, bool&);
116
117     LayoutUnit contentLogicalWidthOfFirstRegion() const;
118     LayoutUnit contentLogicalHeightOfFirstRegion() const;
119     LayoutUnit contentLogicalLeftOfFirstRegion() const;
120     
121     RenderRegion* firstRegion() const;
122     RenderRegion* lastRegion() const;
123
124     bool previousRegionCountChanged() const { return m_previousRegionCount != m_regionList.size(); };
125     void updatePreviousRegionCount() { m_previousRegionCount = m_regionList.size(); };
126
127     void setRegionRangeForBox(const RenderBox*, RenderRegion*, RenderRegion*);
128     void getRegionRangeForBox(const RenderBox*, RenderRegion*& startRegion, RenderRegion*& endRegion) const;
129
130     // Check if the object is in region and the region is part of this flow thread.
131     bool objectInFlowRegion(const RenderObject*, const RenderRegion*) const;
132     
133     // Check if the object should be painted in this region and if the region is part of this flow thread.
134     bool objectShouldPaintInFlowRegion(const RenderObject*, const RenderRegion*) const;
135
136     void markAutoLogicalHeightRegionsForLayout();
137     void markRegionsForOverflowLayoutIfNeeded();
138
139     virtual bool addForcedRegionBreak(const RenderBlock*, LayoutUnit, RenderBox* breakChild, bool isBefore, LayoutUnit* offsetBreakAdjustment = 0);
140     void applyBreakAfterContent(LayoutUnit);
141
142     bool pageLogicalSizeChanged() const { return m_pageLogicalSizeChanged; }
143
144     bool hasAutoLogicalHeightRegions() const { ASSERT(isAutoLogicalHeightRegionsCountConsistent()); return m_autoLogicalHeightRegionsCount; }
145     void incrementAutoLogicalHeightRegions();
146     void decrementAutoLogicalHeightRegions();
147
148 #ifndef NDEBUG
149     bool isAutoLogicalHeightRegionsCountConsistent() const;
150 #endif
151
152     void collectLayerFragments(LayerFragments&, const LayoutRect& layerBoundingBox, const LayoutRect& dirtyRect);
153     LayoutRect fragmentsBoundingBox(const LayoutRect& layerBoundingBox);
154
155     // A flow thread goes through different states during layout.
156     enum LayoutPhase {
157         LayoutPhaseMeasureContent = 0, // The initial phase, used to measure content for the auto-height regions.
158         LayoutPhaseConstrained, // In this phase the regions are laid out using the sizes computed in the normal phase.
159         LayoutPhaseOverflow, // In this phase the layout overflow is propagated from the content to the regions.
160         LayoutPhaseFinal // In case scrollbars have resized the regions, content is laid out one last time to respect the change.
161     };
162     bool inMeasureContentLayoutPhase() const { return m_layoutPhase == LayoutPhaseMeasureContent; }
163     bool inConstrainedLayoutPhase() const { return m_layoutPhase == LayoutPhaseConstrained; }
164     bool inOverflowLayoutPhase() const { return m_layoutPhase == LayoutPhaseOverflow; }
165     bool inFinalLayoutPhase() const { return m_layoutPhase == LayoutPhaseFinal; }
166     void setLayoutPhase(LayoutPhase phase) { m_layoutPhase = phase; }
167
168     bool needsTwoPhasesLayout() const { return m_needsTwoPhasesLayout; }
169     void clearNeedsTwoPhasesLayout() { m_needsTwoPhasesLayout = false; }
170
171     // Whether any of the regions has a compositing descendant.
172     bool hasCompositingRegionDescendant() const;
173
174     void setNeedsLayerToRegionMappingsUpdate() { m_layersToRegionMappingsDirty = true; }
175     void updateAllLayerToRegionMappingsIfNeeded()
176     {
177         if (m_layersToRegionMappingsDirty)
178             updateAllLayerToRegionMappings();
179     }
180
181     const RenderLayerList* getLayerListForRegion(RenderNamedFlowFragment*);
182
183     RenderNamedFlowFragment* regionForCompositedLayer(RenderLayer&); // By means of getRegionRangeForBox or regionAtBlockOffset.
184     RenderNamedFlowFragment* cachedRegionForCompositedLayer(RenderLayer&);
185
186     virtual bool collectsGraphicsLayersUnderRegions() const;
187
188     void pushFlowThreadLayoutState(const RenderObject&);
189     void popFlowThreadLayoutState();
190     LayoutUnit offsetFromLogicalTopOfFirstRegion(const RenderBlock*) const;
191     void clearRenderBoxRegionInfoAndCustomStyle(const RenderBox*, const RenderRegion*, const RenderRegion*, const RenderRegion*, const RenderRegion*);
192
193     void addRegionsVisualEffectOverflow(const RenderBox*);
194     void addRegionsVisualOverflowFromTheme(const RenderBlock*);
195     void addRegionsOverflowFromChild(const RenderBox*, const RenderBox*, const LayoutSize&);
196     void addRegionsLayoutOverflow(const RenderBox*, const LayoutRect&);
197     void addRegionsVisualOverflow(const RenderBox*, const LayoutRect&);
198     void clearRegionsOverflow(const RenderBox*);
199
200     LayoutRect mapFromFlowThreadToLocal(const RenderBox*, const LayoutRect&) const;
201     LayoutRect mapFromLocalToFlowThread(const RenderBox*, const LayoutRect&) const;
202     
203     LayoutRect decorationsClipRectForBoxInRegion(const RenderBox&, RenderRegion&) const;
204     
205     void flipForWritingModeLocalCoordinates(LayoutRect&) const;
206
207     // Used to estimate the maximum height of the flow thread.
208     static LayoutUnit maxLogicalHeight() { return LayoutUnit::max() / 2; }
209     
210     bool regionInRange(const RenderRegion* targetRegion, const RenderRegion* startRegion, const RenderRegion* endRegion) const;
211
212 private:
213     virtual bool isRenderFlowThread() const override final { return true; }
214     virtual void layout() override final;
215
216     // Always create a RenderLayer for the RenderFlowThread so that we
217     // can easily avoid drawing the children directly.
218     virtual bool requiresLayer() const override final { return true; }
219
220 protected:
221     RenderFlowThread(Document&, PassRef<RenderStyle>);
222
223     virtual const char* renderName() const = 0;
224
225     // Overridden by columns/pages to set up an initial logical width of the page width even when
226     // no regions have been generated yet.
227     virtual LayoutUnit initialLogicalWidth() const { return 0; };
228
229     virtual void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags = ApplyContainerFlip, bool* wasFixed = 0) const override;
230
231     void updateRegionsFlowThreadPortionRect(const RenderRegion* = 0);
232     bool shouldRepaint(const LayoutRect&) const;
233
234     LayoutRect computeRegionClippingRect(const LayoutPoint&, const LayoutRect&, const LayoutRect&) const;
235
236     bool updateAllLayerToRegionMappings();
237
238     // Triggers a layers' update if a layer has moved from a region to another since the last update.
239     void updateLayerToRegionMappings(RenderLayer&, LayerToRegionMap&, RegionToLayerListMap&, bool& needsLayerUpdate);
240     RenderNamedFlowFragment* regionForCompositedLayer(RenderLayer*);
241     bool updateLayerToRegionMappings();
242     void updateRegionForRenderLayer(RenderLayer*, LayerToRegionMap&, RegionToLayerListMap&, bool& needsLayerUpdate);
243
244     void setDispatchRegionLayoutUpdateEvent(bool value) { m_dispatchRegionLayoutUpdateEvent = value; }
245     bool shouldDispatchRegionLayoutUpdateEvent() { return m_dispatchRegionLayoutUpdateEvent; }
246     
247     void setDispatchRegionOversetChangeEvent(bool value) { m_dispatchRegionOversetChangeEvent = value; }
248     bool shouldDispatchRegionOversetChangeEvent() const { return m_dispatchRegionOversetChangeEvent; }
249     
250     // Override if the flow thread implementation supports dispatching events when the flow layout is updated (e.g. for named flows)
251     virtual void dispatchRegionLayoutUpdateEvent() { m_dispatchRegionLayoutUpdateEvent = false; }
252     virtual void dispatchRegionOversetChangeEvent() { m_dispatchRegionOversetChangeEvent = false; }
253
254     void initializeRegionsComputedAutoHeight(RenderRegion* = 0);
255
256     virtual void autoGenerateRegionsToBlockOffset(LayoutUnit) { };
257
258     inline bool hasCachedOffsetFromLogicalTopOfFirstRegion(const RenderBox*) const;
259     inline LayoutUnit cachedOffsetFromLogicalTopOfFirstRegion(const RenderBox*) const;
260     inline void setOffsetFromLogicalTopOfFirstRegion(const RenderBox*, LayoutUnit);
261     inline void clearOffsetFromLogicalTopOfFirstRegion(const RenderBox*);
262
263     inline const RenderBox* currentActiveRenderBox() const;
264
265     RenderRegionList m_regionList;
266     unsigned short m_previousRegionCount;
267
268     class RenderRegionRange {
269     public:
270         RenderRegionRange()
271         {
272             setRange(0, 0);
273         }
274
275         RenderRegionRange(RenderRegion* start, RenderRegion* end)
276         {
277             setRange(start, end);
278         }
279         
280         void setRange(RenderRegion* start, RenderRegion* end)
281         {
282             m_startRegion = start;
283             m_endRegion = end;
284             m_rangeInvalidated = true;
285         }
286
287         RenderRegion* startRegion() const { return m_startRegion; }
288         RenderRegion* endRegion() const { return m_endRegion; }
289         bool rangeInvalidated() const { return m_rangeInvalidated; }
290         void clearRangeInvalidated() { m_rangeInvalidated = false; }
291
292     private:
293         RenderRegion* m_startRegion;
294         RenderRegion* m_endRegion;
295         bool m_rangeInvalidated;
296     };
297
298     typedef PODInterval<LayoutUnit, RenderRegion*> RegionInterval;
299     typedef PODIntervalTree<LayoutUnit, RenderRegion*> RegionIntervalTree;
300
301     class RegionSearchAdapter {
302     public:
303         RegionSearchAdapter(LayoutUnit offset)
304             : m_offset(offset)
305             , m_result(0)
306         {
307         }
308         
309         const LayoutUnit& lowValue() const { return m_offset; }
310         const LayoutUnit& highValue() const { return m_offset; }
311         void collectIfNeeded(const RegionInterval&);
312
313         RenderRegion* result() const { return m_result; }
314
315     private:
316         LayoutUnit m_offset;
317         RenderRegion* m_result;
318     };
319
320     // To easily find the region where a layer should be painted.
321     OwnPtr<LayerToRegionMap> m_layerToRegionMap;
322
323     // To easily find the list of layers that paint in a region.
324     OwnPtr<RegionToLayerListMap> m_regionToLayerListMap;
325
326     // Map a box to the list of regions in which the box is rendered.
327     typedef HashMap<const RenderBox*, RenderRegionRange> RenderRegionRangeMap;
328     RenderRegionRangeMap m_regionRangeMap;
329
330     // Map a box with a region break to the auto height region affected by that break. 
331     typedef HashMap<RenderBox*, RenderRegion*> RenderBoxToRegionMap;
332     RenderBoxToRegionMap m_breakBeforeToRegionMap;
333     RenderBoxToRegionMap m_breakAfterToRegionMap;
334
335     typedef ListHashSet<const RenderObject*> RenderObjectStack;
336     RenderObjectStack m_activeObjectsStack;
337
338     typedef HashMap<const RenderBox*, LayoutUnit> RenderBoxToOffsetMap;
339     RenderBoxToOffsetMap m_boxesToOffsetMap;
340
341     unsigned m_autoLogicalHeightRegionsCount;
342
343     RegionIntervalTree m_regionIntervalTree;
344
345     bool m_regionsInvalidated : 1;
346     bool m_regionsHaveUniformLogicalWidth : 1;
347     bool m_regionsHaveUniformLogicalHeight : 1;
348     bool m_dispatchRegionLayoutUpdateEvent : 1;
349     bool m_dispatchRegionOversetChangeEvent : 1;
350     bool m_pageLogicalSizeChanged : 1;
351     unsigned m_layoutPhase : 2;
352     bool m_needsTwoPhasesLayout : 1;
353     bool m_layersToRegionMappingsDirty : 1;
354 };
355
356 RENDER_OBJECT_TYPE_CASTS(RenderFlowThread, isRenderFlowThread())
357
358 class CurrentRenderFlowThreadMaintainer {
359     WTF_MAKE_NONCOPYABLE(CurrentRenderFlowThreadMaintainer);
360 public:
361     CurrentRenderFlowThreadMaintainer(RenderFlowThread*);
362     ~CurrentRenderFlowThreadMaintainer();
363 private:
364     RenderFlowThread* m_renderFlowThread;
365     RenderFlowThread* m_previousRenderFlowThread;
366 };
367
368 // This structure is used by PODIntervalTree for debugging.
369 #ifndef NDEBUG
370 template <> struct ValueToString<RenderRegion*> {
371     static String string(const RenderRegion* value) { return String::format("%p", value); }
372 };
373 #endif
374
375 } // namespace WebCore
376
377 #endif // RenderFlowThread_h