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