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