flutter_flutter/sky/engine/core/rendering/RenderLayerStackingNode.cpp
Michael Goderbauer 08961f8ec5 Format all c-like sources with clang-format (#4088)
* format

* license script adaptions

* updated licenses

* review comments
2017-09-12 15:36:20 -07:00

267 lines
8.4 KiB
C++

/*
* Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011, 2012 Apple Inc.
* All rights reserved.
*
* Portions are Copyright (C) 1998 Netscape Communications Corporation.
*
* Other contributors:
* Robert O'Callahan <roc+@cs.cmu.edu>
* David Baron <dbaron@fas.harvard.edu>
* Christian Biesinger <cbiesinger@web.de>
* Randall Jesup <rjesup@wgate.com>
* Roland Mainz <roland.mainz@informatik.med.uni-giessen.de>
* Josh Soref <timeless@mac.com>
* Boris Zbarsky <bzbarsky@mit.edu>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Alternatively, the contents of this file may be used under the terms
* of either the Mozilla Public License Version 1.1, found at
* http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
* License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
* (the "GPL"), in which case the provisions of the MPL or the GPL are
* applicable instead of those above. If you wish to allow use of your
* version of this file only under the terms of one of those two
* licenses (the MPL or the GPL) and not to allow others to use your
* version of this file under the LGPL, indicate your decision by
* deletingthe provisions above and replace them with the notice and
* other provisions required by the MPL or the GPL, as the case may be.
* If you do not delete the provisions above, a recipient may use your
* version of this file under any of the LGPL, the MPL or the GPL.
*/
#include "flutter/sky/engine/core/rendering/RenderLayerStackingNode.h"
#include "flutter/sky/engine/core/rendering/RenderLayer.h"
#include "flutter/sky/engine/core/rendering/RenderView.h"
#include "flutter/sky/engine/public/platform/Platform.h"
namespace blink {
// FIXME: This should not require RenderLayer. There is currently a cycle where
// in order to determine if we shoulBeNormalFlowOnly() we have to ask the render
// layer about some of its state.
RenderLayerStackingNode::RenderLayerStackingNode(RenderLayer* layer)
: m_layer(layer),
m_normalFlowListDirty(true)
#if ENABLE(ASSERT)
,
m_layerListMutationAllowed(true),
m_stackingParent(0)
#endif
{
m_isNormalFlowOnly = shouldBeNormalFlowOnly();
// Non-stacking contexts should have empty z-order lists. As this is already
// the case, there is no need to dirty / recompute these lists.
m_zOrderListsDirty = isStackingContext();
}
RenderLayerStackingNode::~RenderLayerStackingNode() {
#if ENABLE(ASSERT)
if (!renderer()->documentBeingDestroyed()) {
ASSERT(!isInStackingParentZOrderLists());
ASSERT(!isInStackingParentNormalFlowList());
updateStackingParentForZOrderLists(0);
updateStackingParentForNormalFlowList(0);
}
#endif
}
// Helper for the sorting of layers by z-index.
static inline bool compareZIndex(RenderLayerStackingNode* first,
RenderLayerStackingNode* second) {
return first->zIndex() < second->zIndex();
}
void RenderLayerStackingNode::dirtyZOrderLists() {
ASSERT(m_layerListMutationAllowed);
ASSERT(isStackingContext());
#if ENABLE(ASSERT)
updateStackingParentForZOrderLists(0);
#endif
if (m_zOrderList)
m_zOrderList->clear();
m_zOrderListsDirty = true;
}
void RenderLayerStackingNode::dirtyStackingContextZOrderLists() {
if (RenderLayerStackingNode* stackingNode = ancestorStackingContextNode())
stackingNode->dirtyZOrderLists();
}
void RenderLayerStackingNode::dirtyNormalFlowList() {
ASSERT(m_layerListMutationAllowed);
#if ENABLE(ASSERT)
updateStackingParentForNormalFlowList(0);
#endif
if (m_normalFlowList)
m_normalFlowList->clear();
m_normalFlowListDirty = true;
}
void RenderLayerStackingNode::rebuildZOrderLists() {
ASSERT(m_layerListMutationAllowed);
ASSERT(isDirtyStackingContext());
for (RenderLayer* child = layer()->firstChild(); child;
child = child->nextSibling())
child->stackingNode()->collectLayers(m_zOrderList);
if (m_zOrderList)
std::stable_sort(m_zOrderList->begin(), m_zOrderList->end(), compareZIndex);
#if ENABLE(ASSERT)
updateStackingParentForZOrderLists(this);
#endif
m_zOrderListsDirty = false;
}
void RenderLayerStackingNode::updateNormalFlowList() {
if (!m_normalFlowListDirty)
return;
ASSERT(m_layerListMutationAllowed);
for (RenderLayer* child = layer()->firstChild(); child;
child = child->nextSibling()) {
if (child->stackingNode()->isNormalFlowOnly()) {
if (!m_normalFlowList)
m_normalFlowList = adoptPtr(new Vector<RenderLayerStackingNode*>);
m_normalFlowList->append(child->stackingNode());
}
}
#if ENABLE(ASSERT)
updateStackingParentForNormalFlowList(this);
#endif
m_normalFlowListDirty = false;
}
void RenderLayerStackingNode::collectLayers(
OwnPtr<Vector<RenderLayerStackingNode*>>& buffer) {
if (!isNormalFlowOnly()) {
if (!buffer)
buffer = adoptPtr(new Vector<RenderLayerStackingNode*>);
buffer->append(this);
}
if (!isStackingContext()) {
for (RenderLayer* child = layer()->firstChild(); child;
child = child->nextSibling())
child->stackingNode()->collectLayers(buffer);
}
}
#if ENABLE(ASSERT)
bool RenderLayerStackingNode::isInStackingParentZOrderLists() const {
if (!m_stackingParent || m_stackingParent->zOrderListsDirty())
return false;
if (m_stackingParent->zOrderList() &&
m_stackingParent->zOrderList()->find(this) != kNotFound)
return true;
return false;
}
bool RenderLayerStackingNode::isInStackingParentNormalFlowList() const {
if (!m_stackingParent || m_stackingParent->normalFlowListDirty())
return false;
return (m_stackingParent->normalFlowList() &&
m_stackingParent->normalFlowList()->find(this) != kNotFound);
}
void RenderLayerStackingNode::updateStackingParentForZOrderLists(
RenderLayerStackingNode* stackingParent) {
if (m_zOrderList) {
for (size_t i = 0; i < m_zOrderList->size(); ++i)
m_zOrderList->at(i)->setStackingParent(stackingParent);
}
}
void RenderLayerStackingNode::updateStackingParentForNormalFlowList(
RenderLayerStackingNode* stackingParent) {
if (m_normalFlowList) {
for (size_t i = 0; i < m_normalFlowList->size(); ++i)
m_normalFlowList->at(i)->setStackingParent(stackingParent);
}
}
#endif
void RenderLayerStackingNode::updateLayerListsIfNeeded() {
updateZOrderLists();
updateNormalFlowList();
}
void RenderLayerStackingNode::updateStackingNodesAfterStyleChange(
const RenderStyle* oldStyle) {
bool wasStackingContext = oldStyle ? !oldStyle->hasAutoZIndex() : false;
unsigned oldZIndex = oldStyle ? oldStyle->zIndex() : 0;
bool isStackingContext = this->isStackingContext();
if (isStackingContext == wasStackingContext && oldZIndex == zIndex())
return;
dirtyStackingContextZOrderLists();
if (isStackingContext)
dirtyZOrderLists();
else
clearZOrderLists();
}
// FIXME: Rename shouldBeNormalFlowOnly to something more accurate now that CSS
// 2.1 defines the term "normal flow".
bool RenderLayerStackingNode::shouldBeNormalFlowOnly() const {
return !isStackingContext() && !renderer()->isPositioned();
}
void RenderLayerStackingNode::updateIsNormalFlowOnly() {
bool isNormalFlowOnly = shouldBeNormalFlowOnly();
if (isNormalFlowOnly == this->isNormalFlowOnly())
return;
m_isNormalFlowOnly = isNormalFlowOnly;
if (RenderLayer* p = layer()->parent())
p->stackingNode()->dirtyNormalFlowList();
dirtyStackingContextZOrderLists();
}
RenderLayerStackingNode* RenderLayerStackingNode::ancestorStackingContextNode()
const {
for (RenderLayer* ancestor = layer()->parent(); ancestor;
ancestor = ancestor->parent()) {
RenderLayerStackingNode* stackingNode = ancestor->stackingNode();
if (stackingNode->isStackingContext())
return stackingNode;
}
return 0;
}
RenderBox* RenderLayerStackingNode::renderer() const {
return m_layer->renderer();
}
} // namespace blink