Move Source/WebCore/rendering/ code to std::unique_ptr
[WebKit-https.git] / Source / WebCore / rendering / FlowThreadController.cpp
1 /*
2  * Copyright (C) 2012 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 #include "config.h"
31 #include "FlowThreadController.h"
32
33 #include "NamedFlowCollection.h"
34 #include "RenderFlowThread.h"
35 #include "RenderLayer.h"
36 #include "RenderNamedFlowThread.h"
37 #include "StyleInheritedData.h"
38 #include "WebKitNamedFlow.h"
39 #include <wtf/text/AtomicString.h>
40
41 namespace WebCore {
42
43 FlowThreadController::FlowThreadController(RenderView* view)
44     : m_view(view)
45     , m_currentRenderFlowThread(0)
46     , m_isRenderNamedFlowThreadOrderDirty(false)
47     , m_flowThreadsWithAutoLogicalHeightRegions(0)
48 {
49 }
50
51 FlowThreadController::~FlowThreadController()
52 {
53 }
54
55 RenderNamedFlowThread& FlowThreadController::ensureRenderFlowThreadWithName(const AtomicString& name)
56 {
57     if (!m_renderNamedFlowThreadList)
58         m_renderNamedFlowThreadList = std::make_unique<RenderNamedFlowThreadList>();
59     else {
60         for (auto iter = m_renderNamedFlowThreadList->begin(), end = m_renderNamedFlowThreadList->end(); iter != end; ++iter) {
61             RenderNamedFlowThread* flowRenderer = *iter;
62             if (flowRenderer->flowThreadName() == name)
63                 return *flowRenderer;
64         }
65     }
66
67     NamedFlowCollection* namedFlows = m_view->document().namedFlows();
68
69     // Sanity check for the absence of a named flow in the "CREATED" state with the same name.
70     ASSERT(!namedFlows->flowByName(name));
71
72     auto flowRenderer = new RenderNamedFlowThread(m_view->document(), RenderFlowThread::createFlowThreadStyle(&m_view->style()), namedFlows->ensureFlowWithName(name));
73     flowRenderer->initializeStyle();
74     m_renderNamedFlowThreadList->add(flowRenderer);
75
76     // Keep the flow renderer as a child of RenderView.
77     m_view->addChild(flowRenderer);
78
79     setIsRenderNamedFlowThreadOrderDirty(true);
80
81     return *flowRenderer;
82 }
83
84 void FlowThreadController::styleDidChange()
85 {
86     RenderStyle& viewStyle = m_view->style();
87     for (auto iter = m_renderNamedFlowThreadList->begin(), end = m_renderNamedFlowThreadList->end(); iter != end; ++iter) {
88         RenderNamedFlowThread* flowRenderer = *iter;
89         flowRenderer->setStyle(RenderFlowThread::createFlowThreadStyle(&viewStyle));
90     }
91 }
92
93 void FlowThreadController::layoutRenderNamedFlowThreads()
94 {
95     updateFlowThreadsChainIfNecessary();
96
97     for (auto iter = m_renderNamedFlowThreadList->begin(), end = m_renderNamedFlowThreadList->end(); iter != end; ++iter) {
98         RenderNamedFlowThread* flowRenderer = *iter;
99         flowRenderer->layoutIfNeeded();
100     }
101 }
102
103 void FlowThreadController::registerNamedFlowContentElement(Element& contentElement, RenderNamedFlowThread& namedFlow)
104 {
105     ASSERT(!m_mapNamedFlowContentElement.contains(&contentElement));
106     ASSERT(!namedFlow.hasContentElement(contentElement));
107     m_mapNamedFlowContentElement.add(&contentElement, &namedFlow);
108     namedFlow.registerNamedFlowContentElement(contentElement);
109 }
110
111 void FlowThreadController::unregisterNamedFlowContentElement(Element& contentElement)
112 {
113     auto it = m_mapNamedFlowContentElement.find(&contentElement);
114     ASSERT(it != m_mapNamedFlowContentElement.end());
115     ASSERT(it->value);
116     ASSERT(it->value->hasContentElement(contentElement));
117     it->value->unregisterNamedFlowContentElement(contentElement);
118     m_mapNamedFlowContentElement.remove(&contentElement);
119 }
120
121 void FlowThreadController::updateFlowThreadsChainIfNecessary()
122 {
123     ASSERT(m_renderNamedFlowThreadList);
124     ASSERT(isAutoLogicalHeightRegionsCountConsistent());
125
126     // Remove the left-over flow threads.
127     RenderNamedFlowThreadList toRemoveList;
128     for (auto iter = m_renderNamedFlowThreadList->begin(), end = m_renderNamedFlowThreadList->end(); iter != end; ++iter) {
129         RenderNamedFlowThread* flowRenderer = *iter;
130         if (flowRenderer->isMarkedForDestruction())
131             toRemoveList.add(flowRenderer);
132     }
133
134     if (toRemoveList.size() > 0)
135         setIsRenderNamedFlowThreadOrderDirty(true);
136
137     for (auto iter = toRemoveList.begin(), end = toRemoveList.end(); iter != end; ++iter) {
138         RenderNamedFlowThread* flowRenderer = *iter;
139         m_renderNamedFlowThreadList->remove(flowRenderer);
140         flowRenderer->destroy();
141     }
142
143     if (isRenderNamedFlowThreadOrderDirty()) {
144         // Arrange the thread list according to dependencies.
145         RenderNamedFlowThreadList sortedList;
146         for (auto iter = m_renderNamedFlowThreadList->begin(), end = m_renderNamedFlowThreadList->end(); iter != end; ++iter) {
147             RenderNamedFlowThread* flowRenderer = *iter;
148             if (sortedList.contains(flowRenderer))
149                 continue;
150             flowRenderer->pushDependencies(sortedList);
151             sortedList.add(flowRenderer);
152         }
153         m_renderNamedFlowThreadList->swap(sortedList);
154         setIsRenderNamedFlowThreadOrderDirty(false);
155     }
156 }
157
158 bool FlowThreadController::updateFlowThreadsNeedingLayout()
159 {
160     bool needsTwoPassLayout = false;
161
162     for (auto iter = m_renderNamedFlowThreadList->begin(), end = m_renderNamedFlowThreadList->end(); iter != end; ++iter) {
163         RenderNamedFlowThread* flowRenderer = *iter;
164         ASSERT(!flowRenderer->needsTwoPhasesLayout());
165         ASSERT(flowRenderer->inMeasureContentLayoutPhase());
166         if (flowRenderer->needsLayout() && flowRenderer->hasAutoLogicalHeightRegions())
167             needsTwoPassLayout = true;
168     }
169
170     if (needsTwoPassLayout)
171         resetFlowThreadsWithAutoHeightRegions();
172
173     return needsTwoPassLayout;
174 }
175
176 bool FlowThreadController::updateFlowThreadsNeedingTwoStepLayout()
177 {
178     bool needsTwoPassLayout = false;
179
180     for (auto iter = m_renderNamedFlowThreadList->begin(), end = m_renderNamedFlowThreadList->end(); iter != end; ++iter) {
181         RenderNamedFlowThread* flowRenderer = *iter;
182         if (flowRenderer->needsTwoPhasesLayout()) {
183             needsTwoPassLayout = true;
184             break;
185         }
186     }
187
188     if (needsTwoPassLayout)
189         resetFlowThreadsWithAutoHeightRegions();
190
191     return needsTwoPassLayout;
192 }
193
194 void FlowThreadController::resetFlowThreadsWithAutoHeightRegions()
195 {
196     for (auto iter = m_renderNamedFlowThreadList->begin(), end = m_renderNamedFlowThreadList->end(); iter != end; ++iter) {
197         RenderNamedFlowThread* flowRenderer = *iter;
198         if (flowRenderer->hasAutoLogicalHeightRegions()) {
199             flowRenderer->markAutoLogicalHeightRegionsForLayout();
200             flowRenderer->invalidateRegions();
201         }
202     }
203 }
204
205 void FlowThreadController::updateFlowThreadsIntoConstrainedPhase()
206 {
207     // Walk the flow chain in reverse order to update the auto-height regions and compute correct sizes for the containing regions. Only after this we can
208     // set the flow in the constrained layout phase.
209     for (auto iter = m_renderNamedFlowThreadList->rbegin(), end = m_renderNamedFlowThreadList->rend(); iter != end; ++iter) {
210         RenderNamedFlowThread* flowRenderer = *iter;
211         ASSERT(!flowRenderer->hasRegions() || flowRenderer->hasValidRegionInfo());
212         flowRenderer->layoutIfNeeded();
213         if (flowRenderer->hasAutoLogicalHeightRegions()) {
214             ASSERT(flowRenderer->needsTwoPhasesLayout());
215             flowRenderer->markAutoLogicalHeightRegionsForLayout();
216         }
217         flowRenderer->setLayoutPhase(RenderFlowThread::LayoutPhaseConstrained);
218         flowRenderer->clearNeedsTwoPhasesLayout();
219     }
220 }
221
222 void FlowThreadController::updateFlowThreadsIntoOverflowPhase()
223 {
224     for (auto iter = m_renderNamedFlowThreadList->rbegin(), end = m_renderNamedFlowThreadList->rend(); iter != end; ++iter) {
225         RenderNamedFlowThread* flowRenderer = *iter;
226         ASSERT(!flowRenderer->hasRegions() || flowRenderer->hasValidRegionInfo());
227         ASSERT(!flowRenderer->needsTwoPhasesLayout());
228
229         // In the overflow computation phase the flow threads start in the constrained phase even though optimizations didn't set the state before.
230         flowRenderer->setLayoutPhase(RenderFlowThread::LayoutPhaseConstrained);
231
232         flowRenderer->layoutIfNeeded();
233         flowRenderer->markRegionsForOverflowLayoutIfNeeded();
234         flowRenderer->setLayoutPhase(RenderFlowThread::LayoutPhaseOverflow);
235     }
236 }
237
238 void FlowThreadController::updateFlowThreadsIntoMeasureContentPhase()
239 {
240     for (auto iter = m_renderNamedFlowThreadList->begin(), end = m_renderNamedFlowThreadList->end(); iter != end; ++iter) {
241         RenderNamedFlowThread* flowRenderer = *iter;
242         ASSERT(flowRenderer->inFinalLayoutPhase());
243
244         flowRenderer->dispatchNamedFlowEvents();
245         flowRenderer->setLayoutPhase(RenderFlowThread::LayoutPhaseMeasureContent);
246     }
247 }
248
249 void FlowThreadController::updateFlowThreadsIntoFinalPhase()
250 {
251     for (auto iter = m_renderNamedFlowThreadList->rbegin(), end = m_renderNamedFlowThreadList->rend(); iter != end; ++iter) {
252         RenderNamedFlowThread* flowRenderer = *iter;
253         flowRenderer->layoutIfNeeded();
254         if (flowRenderer->needsTwoPhasesLayout()) {
255             flowRenderer->markRegionsForOverflowLayoutIfNeeded();
256             flowRenderer->clearNeedsTwoPhasesLayout();
257         }
258         flowRenderer->setLayoutPhase(RenderFlowThread::LayoutPhaseFinal);
259     }
260 }
261
262 void FlowThreadController::updateFlowThreadsLayerToRegionMappingsIfNeeded()
263 {
264     for (auto iter = m_renderNamedFlowThreadList->begin(), end = m_renderNamedFlowThreadList->end(); iter != end; ++iter) {
265         RenderNamedFlowThread* flowRenderer = *iter;
266         flowRenderer->updateAllLayerToRegionMappingsIfNeeded();
267     }
268 }
269
270 void FlowThreadController::updateNamedFlowsLayerListsIfNeeded()
271 {
272     for (auto iter = m_renderNamedFlowThreadList->begin(), end = m_renderNamedFlowThreadList->end(); iter != end; ++iter) {
273         RenderNamedFlowThread* flowRenderer = *iter;
274         flowRenderer->layer()->updateLayerListsIfNeeded();
275     }
276 }
277
278 static inline bool compareZIndex(RenderLayer* first, RenderLayer* second)
279 {
280     return first->zIndex() < second->zIndex();
281 }
282
283 // Collect the fixed positioned layers that have the named flows as containing block
284 // These layers are painted and hit-tested starting from RenderView not from regions.
285 void FlowThreadController::collectFixedPositionedLayers(Vector<RenderLayer*>& fixedPosLayers) const
286 {
287     for (auto iter = m_renderNamedFlowThreadList->begin(), end = m_renderNamedFlowThreadList->end(); iter != end; ++iter) {
288         RenderNamedFlowThread* flowRenderer = *iter;
289
290         // If the named flow does not have any regions attached, a fixed element should not be
291         // displayed even if the fixed element is positioned/sized by the viewport.
292         if (!flowRenderer->hasRegions())
293             continue;
294
295         RenderLayer* flowThreadLayer = flowRenderer->layer();
296         if (Vector<RenderLayer*>* negZOrderList = flowThreadLayer->negZOrderList()) {
297             for (size_t i = 0, size = negZOrderList->size(); i < size; ++i) {
298                 RenderLayer* currLayer = negZOrderList->at(i);
299                 if (currLayer->renderer().style().position() != FixedPosition)
300                     continue;
301                 fixedPosLayers.append(currLayer);
302             }
303         }
304
305         if (Vector<RenderLayer*>* posZOrderList = flowThreadLayer->posZOrderList()) {
306             for (size_t i = 0, size = posZOrderList->size(); i < size; ++i) {
307                 RenderLayer* currLayer = posZOrderList->at(i);
308                 if (currLayer->renderer().style().position() != FixedPosition)
309                     continue;
310                 fixedPosLayers.append(currLayer);
311             }
312         }
313     }
314
315     std::stable_sort(fixedPosLayers.begin(), fixedPosLayers.end(), compareZIndex);
316 }
317
318 #ifndef NDEBUG
319 bool FlowThreadController::isAutoLogicalHeightRegionsCountConsistent() const
320 {
321     if (!hasRenderNamedFlowThreads())
322         return !hasFlowThreadsWithAutoLogicalHeightRegions();
323
324     for (auto iter = m_renderNamedFlowThreadList->begin(), end = m_renderNamedFlowThreadList->end(); iter != end; ++iter) {
325         if (!(*iter)->isAutoLogicalHeightRegionsCountConsistent())
326             return false;
327     }
328
329     return true;
330 }
331 #endif
332
333 } // namespace WebCore