Move Source/WebCore/rendering/ code to std::unique_ptr
[WebKit-https.git] / Source / WebCore / rendering / FlowThreadController.cpp
index 013e4a2..d90f3a7 100644 (file)
  */
 
 #include "config.h"
-
 #include "FlowThreadController.h"
 
 #include "NamedFlowCollection.h"
 #include "RenderFlowThread.h"
-#include "RenderFlowThreadContainer.h"
+#include "RenderLayer.h"
 #include "RenderNamedFlowThread.h"
 #include "StyleInheritedData.h"
 #include "WebKitNamedFlow.h"
 
 namespace WebCore {
 
-PassOwnPtr<FlowThreadController> FlowThreadController::create(RenderView* view)
-{
-    return adoptPtr(new FlowThreadController(view));
-}
-
 FlowThreadController::FlowThreadController(RenderView* view)
     : m_view(view)
     , m_currentRenderFlowThread(0)
-    , m_flowThreadContainer(0)
     , m_isRenderNamedFlowThreadOrderDirty(false)
+    , m_flowThreadsWithAutoLogicalHeightRegions(0)
 {
 }
 
@@ -58,57 +52,98 @@ FlowThreadController::~FlowThreadController()
 {
 }
 
-RenderNamedFlowThread* FlowThreadController::ensureRenderFlowThreadWithName(const AtomicString& name)
+RenderNamedFlowThread& FlowThreadController::ensureRenderFlowThreadWithName(const AtomicString& name)
 {
-    if (!m_flowThreadContainer) {
-        m_flowThreadContainer = new (m_view->renderArena()) RenderFlowThreadContainer(m_view->document());
-        m_flowThreadContainer->setStyle(RenderFlowThread::createFlowThreadStyle(m_view->style()));
-        m_view->addChild(m_flowThreadContainer);
-    }
     if (!m_renderNamedFlowThreadList)
-        m_renderNamedFlowThreadList = adoptPtr(new RenderNamedFlowThreadList());
+        m_renderNamedFlowThreadList = std::make_unique<RenderNamedFlowThreadList>();
     else {
-        for (RenderNamedFlowThreadList::iterator iter = m_renderNamedFlowThreadList->begin(); iter != m_renderNamedFlowThreadList->end(); ++iter) {
+        for (auto iter = m_renderNamedFlowThreadList->begin(), end = m_renderNamedFlowThreadList->end(); iter != end; ++iter) {
             RenderNamedFlowThread* flowRenderer = *iter;
             if (flowRenderer->flowThreadName() == name)
-                return flowRenderer;
+                return *flowRenderer;
         }
     }
 
-    NamedFlowCollection* namedFlows = m_view->document()->namedFlows();
+    NamedFlowCollection* namedFlows = m_view->document().namedFlows();
 
     // Sanity check for the absence of a named flow in the "CREATED" state with the same name.
     ASSERT(!namedFlows->flowByName(name));
 
-    RenderNamedFlowThread* flowRenderer = new (m_view->renderArena()) RenderNamedFlowThread(m_view->document(), namedFlows->ensureFlowWithName(name));
-    flowRenderer->setStyle(RenderFlowThread::createFlowThreadStyle(m_view->style()));
+    auto flowRenderer = new RenderNamedFlowThread(m_view->document(), RenderFlowThread::createFlowThreadStyle(&m_view->style()), namedFlows->ensureFlowWithName(name));
+    flowRenderer->initializeStyle();
     m_renderNamedFlowThreadList->add(flowRenderer);
 
-    // Keep the flow renderer as a child of RenderFlowThreadContainer.
-    m_flowThreadContainer->addChild(flowRenderer);
+    // Keep the flow renderer as a child of RenderView.
+    m_view->addChild(flowRenderer);
 
     setIsRenderNamedFlowThreadOrderDirty(true);
 
-    return flowRenderer;
+    return *flowRenderer;
 }
 
 void FlowThreadController::styleDidChange()
 {
-    RenderStyle* viewStyle = m_view->style();
-    for (RenderNamedFlowThreadList::iterator iter = m_renderNamedFlowThreadList->begin(); iter != m_renderNamedFlowThreadList->end(); ++iter) {
+    RenderStyle& viewStyle = m_view->style();
+    for (auto iter = m_renderNamedFlowThreadList->begin(), end = m_renderNamedFlowThreadList->end(); iter != end; ++iter) {
         RenderNamedFlowThread* flowRenderer = *iter;
-        flowRenderer->setStyle(RenderFlowThread::createFlowThreadStyle(viewStyle));
+        flowRenderer->setStyle(RenderFlowThread::createFlowThreadStyle(&viewStyle));
     }
 }
 
 void FlowThreadController::layoutRenderNamedFlowThreads()
 {
+    updateFlowThreadsChainIfNecessary();
+
+    for (auto iter = m_renderNamedFlowThreadList->begin(), end = m_renderNamedFlowThreadList->end(); iter != end; ++iter) {
+        RenderNamedFlowThread* flowRenderer = *iter;
+        flowRenderer->layoutIfNeeded();
+    }
+}
+
+void FlowThreadController::registerNamedFlowContentElement(Element& contentElement, RenderNamedFlowThread& namedFlow)
+{
+    ASSERT(!m_mapNamedFlowContentElement.contains(&contentElement));
+    ASSERT(!namedFlow.hasContentElement(contentElement));
+    m_mapNamedFlowContentElement.add(&contentElement, &namedFlow);
+    namedFlow.registerNamedFlowContentElement(contentElement);
+}
+
+void FlowThreadController::unregisterNamedFlowContentElement(Element& contentElement)
+{
+    auto it = m_mapNamedFlowContentElement.find(&contentElement);
+    ASSERT(it != m_mapNamedFlowContentElement.end());
+    ASSERT(it->value);
+    ASSERT(it->value->hasContentElement(contentElement));
+    it->value->unregisterNamedFlowContentElement(contentElement);
+    m_mapNamedFlowContentElement.remove(&contentElement);
+}
+
+void FlowThreadController::updateFlowThreadsChainIfNecessary()
+{
     ASSERT(m_renderNamedFlowThreadList);
+    ASSERT(isAutoLogicalHeightRegionsCountConsistent());
+
+    // Remove the left-over flow threads.
+    RenderNamedFlowThreadList toRemoveList;
+    for (auto iter = m_renderNamedFlowThreadList->begin(), end = m_renderNamedFlowThreadList->end(); iter != end; ++iter) {
+        RenderNamedFlowThread* flowRenderer = *iter;
+        if (flowRenderer->isMarkedForDestruction())
+            toRemoveList.add(flowRenderer);
+    }
+
+    if (toRemoveList.size() > 0)
+        setIsRenderNamedFlowThreadOrderDirty(true);
+
+    for (auto iter = toRemoveList.begin(), end = toRemoveList.end(); iter != end; ++iter) {
+        RenderNamedFlowThread* flowRenderer = *iter;
+        m_renderNamedFlowThreadList->remove(flowRenderer);
+        flowRenderer->destroy();
+    }
 
     if (isRenderNamedFlowThreadOrderDirty()) {
         // Arrange the thread list according to dependencies.
         RenderNamedFlowThreadList sortedList;
-        for (RenderNamedFlowThreadList::iterator iter = m_renderNamedFlowThreadList->begin(); iter != m_renderNamedFlowThreadList->end(); ++iter) {
+        for (auto iter = m_renderNamedFlowThreadList->begin(), end = m_renderNamedFlowThreadList->end(); iter != end; ++iter) {
             RenderNamedFlowThread* flowRenderer = *iter;
             if (sortedList.contains(flowRenderer))
                 continue;
@@ -118,38 +153,181 @@ void FlowThreadController::layoutRenderNamedFlowThreads()
         m_renderNamedFlowThreadList->swap(sortedList);
         setIsRenderNamedFlowThreadOrderDirty(false);
     }
+}
+
+bool FlowThreadController::updateFlowThreadsNeedingLayout()
+{
+    bool needsTwoPassLayout = false;
+
+    for (auto iter = m_renderNamedFlowThreadList->begin(), end = m_renderNamedFlowThreadList->end(); iter != end; ++iter) {
+        RenderNamedFlowThread* flowRenderer = *iter;
+        ASSERT(!flowRenderer->needsTwoPhasesLayout());
+        ASSERT(flowRenderer->inMeasureContentLayoutPhase());
+        if (flowRenderer->needsLayout() && flowRenderer->hasAutoLogicalHeightRegions())
+            needsTwoPassLayout = true;
+    }
+
+    if (needsTwoPassLayout)
+        resetFlowThreadsWithAutoHeightRegions();
+
+    return needsTwoPassLayout;
+}
+
+bool FlowThreadController::updateFlowThreadsNeedingTwoStepLayout()
+{
+    bool needsTwoPassLayout = false;
+
+    for (auto iter = m_renderNamedFlowThreadList->begin(), end = m_renderNamedFlowThreadList->end(); iter != end; ++iter) {
+        RenderNamedFlowThread* flowRenderer = *iter;
+        if (flowRenderer->needsTwoPhasesLayout()) {
+            needsTwoPassLayout = true;
+            break;
+        }
+    }
+
+    if (needsTwoPassLayout)
+        resetFlowThreadsWithAutoHeightRegions();
+
+    return needsTwoPassLayout;
+}
+
+void FlowThreadController::resetFlowThreadsWithAutoHeightRegions()
+{
+    for (auto iter = m_renderNamedFlowThreadList->begin(), end = m_renderNamedFlowThreadList->end(); iter != end; ++iter) {
+        RenderNamedFlowThread* flowRenderer = *iter;
+        if (flowRenderer->hasAutoLogicalHeightRegions()) {
+            flowRenderer->markAutoLogicalHeightRegionsForLayout();
+            flowRenderer->invalidateRegions();
+        }
+    }
+}
+
+void FlowThreadController::updateFlowThreadsIntoConstrainedPhase()
+{
+    // 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
+    // set the flow in the constrained layout phase.
+    for (auto iter = m_renderNamedFlowThreadList->rbegin(), end = m_renderNamedFlowThreadList->rend(); iter != end; ++iter) {
+        RenderNamedFlowThread* flowRenderer = *iter;
+        ASSERT(!flowRenderer->hasRegions() || flowRenderer->hasValidRegionInfo());
+        flowRenderer->layoutIfNeeded();
+        if (flowRenderer->hasAutoLogicalHeightRegions()) {
+            ASSERT(flowRenderer->needsTwoPhasesLayout());
+            flowRenderer->markAutoLogicalHeightRegionsForLayout();
+        }
+        flowRenderer->setLayoutPhase(RenderFlowThread::LayoutPhaseConstrained);
+        flowRenderer->clearNeedsTwoPhasesLayout();
+    }
+}
 
-    for (RenderNamedFlowThreadList::iterator iter = m_renderNamedFlowThreadList->begin(); iter != m_renderNamedFlowThreadList->end(); ++iter) {
+void FlowThreadController::updateFlowThreadsIntoOverflowPhase()
+{
+    for (auto iter = m_renderNamedFlowThreadList->rbegin(), end = m_renderNamedFlowThreadList->rend(); iter != end; ++iter) {
         RenderNamedFlowThread* flowRenderer = *iter;
+        ASSERT(!flowRenderer->hasRegions() || flowRenderer->hasValidRegionInfo());
+        ASSERT(!flowRenderer->needsTwoPhasesLayout());
+
+        // In the overflow computation phase the flow threads start in the constrained phase even though optimizations didn't set the state before.
+        flowRenderer->setLayoutPhase(RenderFlowThread::LayoutPhaseConstrained);
+
         flowRenderer->layoutIfNeeded();
+        flowRenderer->markRegionsForOverflowLayoutIfNeeded();
+        flowRenderer->setLayoutPhase(RenderFlowThread::LayoutPhaseOverflow);
     }
 }
 
-void FlowThreadController::registerNamedFlowContentNode(Node* contentNode, RenderNamedFlowThread* namedFlow)
+void FlowThreadController::updateFlowThreadsIntoMeasureContentPhase()
 {
-    ASSERT(contentNode && contentNode->isElementNode());
-    ASSERT(namedFlow);
-    ASSERT(!m_mapNamedFlowContentNodes.contains(contentNode));
-    ASSERT(!namedFlow->hasContentNode(contentNode));
-    m_mapNamedFlowContentNodes.add(contentNode, namedFlow);
-    namedFlow->registerNamedFlowContentNode(contentNode);
+    for (auto iter = m_renderNamedFlowThreadList->begin(), end = m_renderNamedFlowThreadList->end(); iter != end; ++iter) {
+        RenderNamedFlowThread* flowRenderer = *iter;
+        ASSERT(flowRenderer->inFinalLayoutPhase());
+
+        flowRenderer->dispatchNamedFlowEvents();
+        flowRenderer->setLayoutPhase(RenderFlowThread::LayoutPhaseMeasureContent);
+    }
 }
 
-void FlowThreadController::unregisterNamedFlowContentNode(Node* contentNode)
+void FlowThreadController::updateFlowThreadsIntoFinalPhase()
 {
-    ASSERT(contentNode && contentNode->isElementNode());
-    HashMap<Node*, RenderNamedFlowThread*>::iterator it = m_mapNamedFlowContentNodes.find(contentNode);
-    ASSERT(it != m_mapNamedFlowContentNodes.end());
-    ASSERT(it->second);
-    ASSERT(it->second->hasContentNode(contentNode));
-    it->second->unregisterNamedFlowContentNode(contentNode);
-    m_mapNamedFlowContentNodes.remove(contentNode);
+    for (auto iter = m_renderNamedFlowThreadList->rbegin(), end = m_renderNamedFlowThreadList->rend(); iter != end; ++iter) {
+        RenderNamedFlowThread* flowRenderer = *iter;
+        flowRenderer->layoutIfNeeded();
+        if (flowRenderer->needsTwoPhasesLayout()) {
+            flowRenderer->markRegionsForOverflowLayoutIfNeeded();
+            flowRenderer->clearNeedsTwoPhasesLayout();
+        }
+        flowRenderer->setLayoutPhase(RenderFlowThread::LayoutPhaseFinal);
+    }
 }
 
-void FlowThreadController::removeFlowThread(RenderNamedFlowThread* flowThread)
+void FlowThreadController::updateFlowThreadsLayerToRegionMappingsIfNeeded()
 {
-    m_renderNamedFlowThreadList->remove(flowThread);
-    setIsRenderNamedFlowThreadOrderDirty(true);
+    for (auto iter = m_renderNamedFlowThreadList->begin(), end = m_renderNamedFlowThreadList->end(); iter != end; ++iter) {
+        RenderNamedFlowThread* flowRenderer = *iter;
+        flowRenderer->updateAllLayerToRegionMappingsIfNeeded();
+    }
+}
+
+void FlowThreadController::updateNamedFlowsLayerListsIfNeeded()
+{
+    for (auto iter = m_renderNamedFlowThreadList->begin(), end = m_renderNamedFlowThreadList->end(); iter != end; ++iter) {
+        RenderNamedFlowThread* flowRenderer = *iter;
+        flowRenderer->layer()->updateLayerListsIfNeeded();
+    }
+}
+
+static inline bool compareZIndex(RenderLayer* first, RenderLayer* second)
+{
+    return first->zIndex() < second->zIndex();
+}
+
+// Collect the fixed positioned layers that have the named flows as containing block
+// These layers are painted and hit-tested starting from RenderView not from regions.
+void FlowThreadController::collectFixedPositionedLayers(Vector<RenderLayer*>& fixedPosLayers) const
+{
+    for (auto iter = m_renderNamedFlowThreadList->begin(), end = m_renderNamedFlowThreadList->end(); iter != end; ++iter) {
+        RenderNamedFlowThread* flowRenderer = *iter;
+
+        // If the named flow does not have any regions attached, a fixed element should not be
+        // displayed even if the fixed element is positioned/sized by the viewport.
+        if (!flowRenderer->hasRegions())
+            continue;
+
+        RenderLayer* flowThreadLayer = flowRenderer->layer();
+        if (Vector<RenderLayer*>* negZOrderList = flowThreadLayer->negZOrderList()) {
+            for (size_t i = 0, size = negZOrderList->size(); i < size; ++i) {
+                RenderLayer* currLayer = negZOrderList->at(i);
+                if (currLayer->renderer().style().position() != FixedPosition)
+                    continue;
+                fixedPosLayers.append(currLayer);
+            }
+        }
+
+        if (Vector<RenderLayer*>* posZOrderList = flowThreadLayer->posZOrderList()) {
+            for (size_t i = 0, size = posZOrderList->size(); i < size; ++i) {
+                RenderLayer* currLayer = posZOrderList->at(i);
+                if (currLayer->renderer().style().position() != FixedPosition)
+                    continue;
+                fixedPosLayers.append(currLayer);
+            }
+        }
+    }
+
+    std::stable_sort(fixedPosLayers.begin(), fixedPosLayers.end(), compareZIndex);
+}
+
+#ifndef NDEBUG
+bool FlowThreadController::isAutoLogicalHeightRegionsCountConsistent() const
+{
+    if (!hasRenderNamedFlowThreads())
+        return !hasFlowThreadsWithAutoLogicalHeightRegions();
+
+    for (auto iter = m_renderNamedFlowThreadList->begin(), end = m_renderNamedFlowThreadList->end(); iter != end; ++iter) {
+        if (!(*iter)->isAutoLogicalHeightRegionsCountConsistent())
+            return false;
+    }
+
+    return true;
 }
+#endif
 
 } // namespace WebCore