/* * Copyright (C) 2012 Adobe Systems Incorporated. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above * copyright notice, this list of conditions and the following * disclaimer. * 2. Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include "config.h" #include "FlowThreadController.h" #include "RenderFlowThread.h" #include "RenderFlowThreadContainer.h" #include "RenderNamedFlowThread.h" #include "StyleInheritedData.h" #include "WebKitNamedFlow.h" #include "WebKitNamedFlowCollection.h" #include namespace WebCore { PassOwnPtr 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) { } FlowThreadController::~FlowThreadController() { } 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()); else { for (RenderNamedFlowThreadList::iterator iter = m_renderNamedFlowThreadList->begin(); iter != m_renderNamedFlowThreadList->end(); ++iter) { RenderNamedFlowThread* flowRenderer = *iter; if (flowRenderer->flowThreadName() == name) return flowRenderer; } } WebKitNamedFlowCollection* 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())); m_renderNamedFlowThreadList->add(flowRenderer); // Keep the flow renderer as a child of RenderFlowThreadContainer. m_flowThreadContainer->addChild(flowRenderer); setIsRenderNamedFlowThreadOrderDirty(true); return flowRenderer; } void FlowThreadController::styleDidChange() { RenderStyle* viewStyle = m_view->style(); for (RenderNamedFlowThreadList::iterator iter = m_renderNamedFlowThreadList->begin(); iter != m_renderNamedFlowThreadList->end(); ++iter) { RenderNamedFlowThread* flowRenderer = *iter; flowRenderer->setStyle(RenderFlowThread::createFlowThreadStyle(viewStyle)); } } void FlowThreadController::layoutRenderNamedFlowThreads() { ASSERT(m_renderNamedFlowThreadList); if (isRenderNamedFlowThreadOrderDirty()) { // Arrange the thread list according to dependencies. RenderNamedFlowThreadList sortedList; for (RenderNamedFlowThreadList::iterator iter = m_renderNamedFlowThreadList->begin(); iter != m_renderNamedFlowThreadList->end(); ++iter) { RenderNamedFlowThread* flowRenderer = *iter; if (sortedList.contains(flowRenderer)) continue; flowRenderer->pushDependencies(sortedList); sortedList.add(flowRenderer); } m_renderNamedFlowThreadList->swap(sortedList); setIsRenderNamedFlowThreadOrderDirty(false); } for (RenderNamedFlowThreadList::iterator iter = m_renderNamedFlowThreadList->begin(); iter != m_renderNamedFlowThreadList->end(); ++iter) { RenderNamedFlowThread* flowRenderer = *iter; flowRenderer->layoutIfNeeded(); } } void FlowThreadController::registerNamedFlowContentNode(Node* contentNode, RenderNamedFlowThread* namedFlow) { ASSERT(contentNode && contentNode->isElementNode()); ASSERT(namedFlow); ASSERT(!m_mapNamedFlowContentNodes.contains(contentNode)); ASSERT(!namedFlow->hasContentNode(contentNode)); m_mapNamedFlowContentNodes.add(contentNode, namedFlow); namedFlow->registerNamedFlowContentNode(contentNode); } void FlowThreadController::unregisterNamedFlowContentNode(Node* contentNode) { ASSERT(contentNode && contentNode->isElementNode()); HashMap::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); } void FlowThreadController::removeFlowThread(RenderNamedFlowThread* flowThread) { m_renderNamedFlowThreadList->remove(flowThread); setIsRenderNamedFlowThreadOrderDirty(true); } } // namespace WebCore