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
39namespace blink {
40
41struct LayerFragment;
42typedef Vector<LayerFragment, 1> LayerFragments;
43class RenderFlowThread;
44class RenderMultiColumnSet;
45class RenderRegion;
46
47typedef 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
55class RenderFlowThread: public RenderBlockFlow {
56public:
57    RenderFlowThread();
58    virtual ~RenderFlowThread() { };
59
60    virtual bool isRenderFlowThread() const OVERRIDE FINAL { return true; }
61    virtual bool isRenderMultiColumnFlowThread() const { return false; }
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.
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
77    bool hasRegions() const { return m_multiColumnSetList.size(); }
78
79    void validateRegions();
80    void invalidateRegions();
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
88    virtual void setPageBreak(LayoutUnit /*offset*/, LayoutUnit /*spaceShortage*/) { }
89    virtual void updateMinimumPageHeight(LayoutUnit /*offset*/, LayoutUnit /*minHeight*/) { }
90
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
99    virtual bool isPageLogicalHeightKnown() const { return true; }
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.
110    static LayoutUnit maxLogicalHeight() { return LayoutUnit::max() / 2; }
111
112protected:
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:
130        RenderMultiColumnSetRange()
131        {
132            setRange(0, 0);
133        }
134
135        RenderMultiColumnSetRange(RenderMultiColumnSet* start, RenderMultiColumnSet* end)
136        {
137            setRange(start, end);
138        }
139
140        void setRange(RenderMultiColumnSet* start, RenderMultiColumnSet* end)
141        {
142            m_startColumnSet = start;
143            m_endColumnSet = end;
144        }
145
146        RenderMultiColumnSet* startColumnSet() const { return m_startColumnSet; }
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:
159        RegionSearchAdapter(LayoutUnit offset)
160            : m_offset(offset)
161            , m_result(0)
162        {
163        }
164
165        const LayoutUnit& lowValue() const { return m_offset; }
166        const LayoutUnit& highValue() const { return m_offset; }
167        void collectIfNeeded(const MultiColumnSetInterval&);
168
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
190DEFINE_RENDER_OBJECT_TYPE_CASTS(RenderFlowThread, isRenderFlowThread());
191
192class CurrentRenderFlowThreadMaintainer {
193    WTF_MAKE_NONCOPYABLE(CurrentRenderFlowThreadMaintainer);
194public:
195    CurrentRenderFlowThreadMaintainer(RenderFlowThread*);
196    ~CurrentRenderFlowThreadMaintainer();
197private:
198    RenderFlowThread* m_renderFlowThread;
199    RenderFlowThread* m_previousRenderFlowThread;
200};
201
202// These structures are used by PODIntervalTree for debugging.
203#ifndef NDEBUG
204template <> struct ValueToString<LayoutUnit> {
205    static String string(const LayoutUnit value) { return String::number(value.toFloat()); }
206};
207
208template <> 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