• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 blink {
40 
41 struct LayerFragment;
42 typedef Vector<LayerFragment, 1> LayerFragments;
43 class RenderFlowThread;
44 class RenderMultiColumnSet;
45 class RenderRegion;
46 
47 typedef ListHashSet<RenderMultiColumnSet*> RenderMultiColumnSetList;
48 
49 // RenderFlowThread is used to collect all the render objects that participate in a
50 // flow thread. It will also help in doing the layout. However, it will not render
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();
~RenderFlowThread()58     virtual ~RenderFlowThread() { };
59 
isRenderFlowThread()60     virtual bool isRenderFlowThread() const OVERRIDE FINAL { return true; }
isRenderMultiColumnFlowThread()61     virtual bool isRenderMultiColumnFlowThread() const { return false; }
isRenderPagedFlowThread()62     virtual bool isRenderPagedFlowThread() const { return false; }
63 
64     virtual void layout() OVERRIDE;
65 
66     // Always create a RenderLayer for the RenderFlowThread so that we
67     // can easily avoid drawing the children directly.
layerTypeRequired()68     virtual LayerType layerTypeRequired() const OVERRIDE FINAL { return NormalLayer; }
69 
70     virtual bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) OVERRIDE FINAL;
71 
72     virtual void addRegionToThread(RenderMultiColumnSet*) = 0;
73     virtual void removeRegionFromThread(RenderMultiColumnSet*);
74 
75     virtual void computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop, LogicalExtentComputedValues&) const OVERRIDE;
76 
hasRegions()77     bool hasRegions() const { return m_multiColumnSetList.size(); }
78 
79     void validateRegions();
80     void invalidateRegions();
hasValidRegionInfo()81     bool hasValidRegionInfo() const { return !m_regionsInvalidated && !m_multiColumnSetList.isEmpty(); }
82 
83     void paintInvalidationRectangleInRegions(const LayoutRect&) const;
84 
85     LayoutUnit pageLogicalHeightForOffset(LayoutUnit);
86     LayoutUnit pageRemainingLogicalHeightForOffset(LayoutUnit, PageBoundaryRule = IncludePageBoundary);
87 
setPageBreak(LayoutUnit,LayoutUnit)88     virtual void setPageBreak(LayoutUnit /*offset*/, LayoutUnit /*spaceShortage*/) { }
updateMinimumPageHeight(LayoutUnit,LayoutUnit)89     virtual void updateMinimumPageHeight(LayoutUnit /*offset*/, LayoutUnit /*minHeight*/) { }
90 
regionsHaveUniformLogicalHeight()91     bool regionsHaveUniformLogicalHeight() const { return m_regionsHaveUniformLogicalHeight; }
92 
93     // FIXME: These 2 functions should return a RenderMultiColumnSet.
94     RenderRegion* firstRegion() const;
95     RenderRegion* lastRegion() const;
96 
97     virtual bool addForcedRegionBreak(LayoutUnit, RenderObject* breakChild, bool isBefore, LayoutUnit* offsetBreakAdjustment = 0) { return false; }
98 
isPageLogicalHeightKnown()99     virtual bool isPageLogicalHeightKnown() const { return true; }
pageLogicalSizeChanged()100     bool pageLogicalSizeChanged() const { return m_pageLogicalSizeChanged; }
101 
102     void collectLayerFragments(LayerFragments&, const LayoutRect& layerBoundingBox, const LayoutRect& dirtyRect);
103     LayoutRect fragmentsBoundingBox(const LayoutRect& layerBoundingBox);
104 
105     void pushFlowThreadLayoutState(const RenderObject&);
106     void popFlowThreadLayoutState();
107     LayoutUnit offsetFromLogicalTopOfFirstRegion(const RenderBlock*) const;
108 
109     // Used to estimate the maximum height of the flow thread.
maxLogicalHeight()110     static LayoutUnit maxLogicalHeight() { return LayoutUnit::max() / 2; }
111 
112 protected:
113     virtual const char* renderName() const = 0;
114 
115     void updateRegionsFlowThreadPortionRect();
116     bool shouldIssuePaintInvalidations(const LayoutRect&) const;
117 
118     virtual RenderMultiColumnSet* columnSetAtBlockOffset(LayoutUnit) const = 0;
119 
120     bool cachedOffsetFromLogicalTopOfFirstRegion(const RenderBox*, LayoutUnit&) const;
121     void setOffsetFromLogicalTopOfFirstRegion(const RenderBox*, LayoutUnit);
122     void clearOffsetFromLogicalTopOfFirstRegion(const RenderBox*);
123 
124     const RenderBox* currentStatePusherRenderBox() const;
125 
126     RenderMultiColumnSetList m_multiColumnSetList;
127 
128     class RenderMultiColumnSetRange {
129     public:
RenderMultiColumnSetRange()130         RenderMultiColumnSetRange()
131         {
132             setRange(0, 0);
133         }
134 
RenderMultiColumnSetRange(RenderMultiColumnSet * start,RenderMultiColumnSet * end)135         RenderMultiColumnSetRange(RenderMultiColumnSet* start, RenderMultiColumnSet* end)
136         {
137             setRange(start, end);
138         }
139 
setRange(RenderMultiColumnSet * start,RenderMultiColumnSet * end)140         void setRange(RenderMultiColumnSet* start, RenderMultiColumnSet* end)
141         {
142             m_startColumnSet = start;
143             m_endColumnSet = end;
144         }
145 
startColumnSet()146         RenderMultiColumnSet* startColumnSet() const { return m_startColumnSet; }
endColumnSet()147         RenderMultiColumnSet* endColumnSet() const { return m_endColumnSet; }
148 
149     private:
150         RenderMultiColumnSet* m_startColumnSet;
151         RenderMultiColumnSet* m_endColumnSet;
152     };
153 
154     typedef PODInterval<LayoutUnit, RenderMultiColumnSet*> MultiColumnSetInterval;
155     typedef PODIntervalTree<LayoutUnit, RenderMultiColumnSet*> MultiColumnSetIntervalTree;
156 
157     class RegionSearchAdapter {
158     public:
RegionSearchAdapter(LayoutUnit offset)159         RegionSearchAdapter(LayoutUnit offset)
160             : m_offset(offset)
161             , m_result(0)
162         {
163         }
164 
lowValue()165         const LayoutUnit& lowValue() const { return m_offset; }
highValue()166         const LayoutUnit& highValue() const { return m_offset; }
167         void collectIfNeeded(const MultiColumnSetInterval&);
168 
result()169         RenderRegion* result() const { return m_result; }
170 
171     private:
172         LayoutUnit m_offset;
173         RenderRegion* m_result;
174     };
175 
176     // Stack of objects that pushed a LayoutState object on the RenderView. The
177     // objects on the stack are the ones that are curently in the process of being
178     // laid out.
179     ListHashSet<const RenderObject*> m_statePusherObjectsStack;
180     typedef HashMap<const RenderBox*, LayoutUnit> RenderBoxToOffsetMap;
181     RenderBoxToOffsetMap m_boxesToOffsetMap;
182 
183     MultiColumnSetIntervalTree m_multiColumnSetIntervalTree;
184 
185     bool m_regionsInvalidated : 1;
186     bool m_regionsHaveUniformLogicalHeight : 1;
187     bool m_pageLogicalSizeChanged : 1;
188 };
189 
190 DEFINE_RENDER_OBJECT_TYPE_CASTS(RenderFlowThread, isRenderFlowThread());
191 
192 class CurrentRenderFlowThreadMaintainer {
193     WTF_MAKE_NONCOPYABLE(CurrentRenderFlowThreadMaintainer);
194 public:
195     CurrentRenderFlowThreadMaintainer(RenderFlowThread*);
196     ~CurrentRenderFlowThreadMaintainer();
197 private:
198     RenderFlowThread* m_renderFlowThread;
199     RenderFlowThread* m_previousRenderFlowThread;
200 };
201 
202 // These structures are used by PODIntervalTree for debugging.
203 #ifndef NDEBUG
204 template <> struct ValueToString<LayoutUnit> {
205     static String string(const LayoutUnit value) { return String::number(value.toFloat()); }
206 };
207 
208 template <> struct ValueToString<RenderMultiColumnSet*> {
209     static String string(const RenderMultiColumnSet* value) { return String::format("%p", value); }
210 };
211 #endif
212 
213 } // namespace blink
214 
215 #endif // RenderFlowThread_h
216