Unreviewed, rolling out r234489.
[WebKit-https.git] / Source / WebCore / rendering / RenderFragmentedFlow.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 #pragma once
31
32 #include "LayerFragment.h"
33 #include "RenderBlockFlow.h"
34 #include "RenderFragmentContainer.h"
35 #include <wtf/ListHashSet.h>
36
37 namespace WebCore {
38
39 class CurrentRenderFragmentContainerMaintainer;
40 class RenderFragmentedFlow;
41 class RenderStyle;
42 class RenderFragmentContainer;
43 class RootInlineBox;
44
45 typedef ListHashSet<RenderFragmentContainer*> RenderFragmentContainerList;
46 typedef Vector<RenderLayer*> RenderLayerList;
47 typedef HashMap<const RootInlineBox*, RenderFragmentContainer*> ContainingFragmentMap;
48
49 // RenderFragmentedFlow 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, RenderFragmentContainer objects will redirect their paint 
52 // and nodeAtPoint methods to this object. Each RenderFragmentContainer will actually be a viewPort
53 // of the RenderFragmentedFlow.
54
55 class RenderFragmentedFlow: public RenderBlockFlow {
56     WTF_MAKE_ISO_ALLOCATED(RenderFragmentedFlow);
57 public:
58     virtual ~RenderFragmentedFlow() = default;
59
60     virtual void removeFlowChildInfo(RenderElement&);
61 #ifndef NDEBUG
62     bool hasChildInfo(RenderObject* child) const { return is<RenderBox>(child) && m_fragmentRangeMap.contains(downcast<RenderBox>(child)); }
63 #endif
64
65 #if !ASSERT_WITH_SECURITY_IMPLICATION_DISABLED
66     bool checkLinesConsistency(const RenderBlockFlow&) const;
67 #endif
68     
69     void deleteLines() override;
70
71     virtual void addFragmentToThread(RenderFragmentContainer*) = 0;
72     virtual void removeFragmentFromThread(RenderFragmentContainer*);
73     const RenderFragmentContainerList& renderFragmentContainerList() const { return m_fragmentList; }
74
75     void updateLogicalWidth() final;
76     LogicalExtentComputedValues computeLogicalHeight(LayoutUnit logicalHeight, LayoutUnit logicalTop) const override;
77
78     bool nodeAtPoint(const HitTestRequest&, HitTestResult&, const HitTestLocation& locationInContainer, const LayoutPoint& accumulatedOffset, HitTestAction) override;
79
80     bool hasFragments() const { return m_fragmentList.size(); }
81     virtual void fragmentChangedWritingMode(RenderFragmentContainer*) { }
82
83     void validateFragments();
84     void invalidateFragments(MarkingBehavior = MarkContainingBlockChain);
85     bool hasValidFragmentInfo() const { return !m_fragmentsInvalidated && !m_fragmentList.isEmpty(); }
86     
87     // Called when a descendant box's layout is finished and it has been positioned within its container.
88     virtual void fragmentedFlowDescendantBoxLaidOut(RenderBox*) { }
89
90     void styleDidChange(StyleDifference, const RenderStyle* oldStyle) override;
91
92     void repaintRectangleInFragments(const LayoutRect&) const;
93     
94     LayoutPoint adjustedPositionRelativeToOffsetParent(const RenderBoxModelObject&, const LayoutPoint&) const;
95
96     LayoutUnit pageLogicalTopForOffset(LayoutUnit) const;
97     LayoutUnit pageLogicalWidthForOffset(LayoutUnit) const;
98     LayoutUnit pageLogicalHeightForOffset(LayoutUnit) const;
99     LayoutUnit pageRemainingLogicalHeightForOffset(LayoutUnit, PageBoundaryRule = IncludePageBoundary) const;
100
101     virtual void setPageBreak(const RenderBlock*, LayoutUnit /*offset*/, LayoutUnit /*spaceShortage*/) { }
102     virtual void updateMinimumPageHeight(const RenderBlock*, LayoutUnit /*offset*/, LayoutUnit /*minHeight*/) { }
103
104     virtual RenderFragmentContainer* fragmentAtBlockOffset(const RenderBox*, LayoutUnit, bool extendLastFragment = false) const;
105
106     bool fragmentsHaveUniformLogicalWidth() const { return m_fragmentsHaveUniformLogicalWidth; }
107     bool fragmentsHaveUniformLogicalHeight() const { return m_fragmentsHaveUniformLogicalHeight; }
108
109     virtual RenderFragmentContainer* mapFromFlowToFragment(TransformState&) const;
110
111     void logicalWidthChangedInFragmentsForBlock(const RenderBlock*, bool&);
112
113     LayoutUnit contentLogicalWidthOfFirstFragment() const;
114     LayoutUnit contentLogicalHeightOfFirstFragment() const;
115     LayoutUnit contentLogicalLeftOfFirstFragment() const;
116     
117     RenderFragmentContainer* firstFragment() const;
118     RenderFragmentContainer* lastFragment() const;
119
120     virtual void setFragmentRangeForBox(const RenderBox&, RenderFragmentContainer*, RenderFragmentContainer*);
121     bool getFragmentRangeForBox(const RenderBox*, RenderFragmentContainer*& startFragment, RenderFragmentContainer*& endFragment) const;
122     bool computedFragmentRangeForBox(const RenderBox*, RenderFragmentContainer*& startFragment, RenderFragmentContainer*& endFragment) const;
123     bool hasCachedFragmentRangeForBox(const RenderBox&) const;
124
125     // Check if the object is in fragment and the fragment is part of this flow thread.
126     bool objectInFlowFragment(const RenderObject*, const RenderFragmentContainer*) const;
127     
128     // Check if the object should be painted in this fragment and if the fragment is part of this flow thread.
129     bool objectShouldFragmentInFlowFragment(const RenderObject*, const RenderFragmentContainer*) const;
130
131     void markFragmentsForOverflowLayoutIfNeeded();
132
133     virtual bool addForcedFragmentBreak(const RenderBlock*, LayoutUnit, RenderBox* breakChild, bool isBefore, LayoutUnit* offsetBreakAdjustment = 0);
134     virtual void applyBreakAfterContent(LayoutUnit) { }
135
136     virtual bool isPageLogicalHeightKnown() const { return true; }
137     bool pageLogicalSizeChanged() const { return m_pageLogicalSizeChanged; }
138
139     void collectLayerFragments(LayerFragments&, const LayoutRect& layerBoundingBox, const LayoutRect& dirtyRect);
140     LayoutRect fragmentsBoundingBox(const LayoutRect& layerBoundingBox);
141
142     LayoutUnit offsetFromLogicalTopOfFirstFragment(const RenderBlock*) const;
143     void clearRenderBoxFragmentInfoAndCustomStyle(const RenderBox&, const RenderFragmentContainer*, const RenderFragmentContainer*, const RenderFragmentContainer*, const RenderFragmentContainer*);
144
145     void addFragmentsVisualEffectOverflow(const RenderBox*);
146     void addFragmentsVisualOverflowFromTheme(const RenderBlock*);
147     void addFragmentsOverflowFromChild(const RenderBox*, const RenderBox*, const LayoutSize&);
148     void addFragmentsLayoutOverflow(const RenderBox*, const LayoutRect&);
149     void addFragmentsVisualOverflow(const RenderBox*, const LayoutRect&);
150     void clearFragmentsOverflow(const RenderBox*);
151
152     LayoutRect mapFromFragmentedFlowToLocal(const RenderBox*, const LayoutRect&) const;
153     LayoutRect mapFromLocalToFragmentedFlow(const RenderBox*, const LayoutRect&) const;
154
155     void flipForWritingModeLocalCoordinates(LayoutRect&) const;
156
157     // Used to estimate the maximum height of the flow thread.
158     static LayoutUnit maxLogicalHeight() { return LayoutUnit::max() / 2; }
159
160     bool fragmentInRange(const RenderFragmentContainer* targetFragment, const RenderFragmentContainer* startFragment, const RenderFragmentContainer* endFragment) const;
161
162     virtual bool absoluteQuadsForBox(Vector<FloatQuad>&, bool*, const RenderBox*, float, float) const { return false; }
163
164     void layout() override;
165
166     void setCurrentFragmentMaintainer(CurrentRenderFragmentContainerMaintainer* currentFragmentMaintainer) { m_currentFragmentMaintainer = currentFragmentMaintainer; }
167     RenderFragmentContainer* currentFragment() const;
168
169     ContainingFragmentMap& containingFragmentMap();
170
171     bool cachedEnclosingFragmentedFlowNeedsUpdate() const override { return false; }
172
173     // FIXME: Eventually as column and fragment flow threads start nesting, this may end up changing.
174     virtual bool shouldCheckColumnBreaks() const { return false; }
175
176 private:
177     // Always create a RenderLayer for the RenderFragmentedFlow so that we
178     // can easily avoid drawing the children directly.
179     bool requiresLayer() const final { return true; }
180
181 protected:
182     RenderFragmentedFlow(Document&, RenderStyle&&);
183
184     RenderFragmentedFlow* locateEnclosingFragmentedFlow() const override { return const_cast<RenderFragmentedFlow*>(this); }
185
186     const char* renderName() const override = 0;
187
188     // Overridden by columns/pages to set up an initial logical width of the page width even when
189     // no fragments have been generated yet.
190     virtual LayoutUnit initialLogicalWidth() const { return 0; };
191     
192     void clearLinesToFragmentMap();
193     void willBeDestroyed() override;
194
195     void mapLocalToContainer(const RenderLayerModelObject* repaintContainer, TransformState&, MapCoordinatesFlags, bool* wasFixed) const override;
196
197     void updateFragmentsFragmentedFlowPortionRect();
198     bool shouldRepaint(const LayoutRect&) const;
199
200     bool getFragmentRangeForBoxFromCachedInfo(const RenderBox*, RenderFragmentContainer*& startFragment, RenderFragmentContainer*& endFragment) const;
201
202     void removeRenderBoxFragmentInfo(RenderBox&);
203     void removeLineFragmentInfo(const RenderBlockFlow&);
204
205     RenderFragmentContainerList m_fragmentList;
206
207     class RenderFragmentContainerRange {
208     public:
209         RenderFragmentContainerRange() = default;
210         RenderFragmentContainerRange(RenderFragmentContainer* start, RenderFragmentContainer* end)
211         {
212             setRange(start, end);
213         }
214         
215         void setRange(RenderFragmentContainer* start, RenderFragmentContainer* end)
216         {
217             m_startFragment = makeWeakPtr(start);
218             m_endFragment = makeWeakPtr(end);
219             m_rangeInvalidated = true;
220         }
221
222         RenderFragmentContainer* startFragment() const { return m_startFragment.get(); }
223         RenderFragmentContainer* endFragment() const { return m_endFragment.get(); }
224         bool rangeInvalidated() const { return m_rangeInvalidated; }
225         void clearRangeInvalidated() { m_rangeInvalidated = false; }
226
227     private:
228         WeakPtr<RenderFragmentContainer> m_startFragment;
229         WeakPtr<RenderFragmentContainer> m_endFragment;
230         bool m_rangeInvalidated;
231     };
232
233     typedef PODInterval<LayoutUnit, WeakPtr<RenderFragmentContainer>> FragmentInterval;
234     typedef PODIntervalTree<LayoutUnit, WeakPtr<RenderFragmentContainer>> FragmentIntervalTree;
235
236     class FragmentSearchAdapter {
237     public:
238         FragmentSearchAdapter(LayoutUnit offset)
239             : m_offset(offset)
240         {
241         }
242         
243         const LayoutUnit& lowValue() const { return m_offset; }
244         const LayoutUnit& highValue() const { return m_offset; }
245         void collectIfNeeded(const FragmentInterval&);
246
247         RenderFragmentContainer* result() const { return m_result.get(); }
248
249     private:
250         LayoutUnit m_offset;
251         WeakPtr<RenderFragmentContainer> m_result;
252     };
253
254     // Map a line to its containing fragment.
255     std::unique_ptr<ContainingFragmentMap> m_lineToFragmentMap;
256
257     // Map a box to the list of fragments in which the box is rendered.
258     typedef HashMap<const RenderBox*, RenderFragmentContainerRange> RenderFragmentContainerRangeMap;
259     RenderFragmentContainerRangeMap m_fragmentRangeMap;
260
261     // Map a box with a fragment break to the auto height fragment affected by that break. 
262     typedef HashMap<RenderBox*, RenderFragmentContainer*> RenderBoxToFragmentMap;
263     RenderBoxToFragmentMap m_breakBeforeToFragmentMap;
264     RenderBoxToFragmentMap m_breakAfterToFragmentMap;
265
266     FragmentIntervalTree m_fragmentIntervalTree;
267
268     CurrentRenderFragmentContainerMaintainer* m_currentFragmentMaintainer;
269
270     bool m_fragmentsInvalidated : 1;
271     bool m_fragmentsHaveUniformLogicalWidth : 1;
272     bool m_fragmentsHaveUniformLogicalHeight : 1;
273     bool m_pageLogicalSizeChanged : 1;
274 };
275
276 } // namespace WebCore
277
278 // This structure is used by PODIntervalTree for debugging.
279 #ifndef NDEBUG
280 namespace WTF {
281
282 template <> struct ValueToString<WebCore::RenderFragmentContainer*> {
283     static String string(const WebCore::RenderFragmentContainer* value) { return String::format("%p", value); }
284 };
285
286 template <> struct ValueToString<WeakPtr<WebCore::RenderFragmentContainer>> {
287     static String string(const WeakPtr<WebCore::RenderFragmentContainer> value) { return value.get() ? ValueToString<WebCore::RenderFragmentContainer*>::string(value.get()) : String(); }
288 };
289
290 } // namespace WTF
291 #endif
292
293 SPECIALIZE_TYPE_TRAITS_RENDER_OBJECT(RenderFragmentedFlow, isRenderFragmentedFlow())