text: /*
   * Copyright (C) 2003, 2009, 2012 Apple Inc. All rights reserved.
   * Copyright (C) 2013 Intel Corporation. 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.
   */
  
  #ifndef SKY_ENGINE_CORE_RENDERING_RENDERLAYERSTACKINGNODE_H_
  #define SKY_ENGINE_CORE_RENDERING_RENDERLAYERSTACKINGNODE_H_
  
  #include "sky/engine/core/rendering/RenderLayerModelObject.h"
  #include "sky/engine/wtf/Noncopyable.h"
  #include "sky/engine/wtf/OwnPtr.h"
  #include "sky/engine/wtf/Vector.h"
  
  namespace blink {
  
  class RenderLayer;
  class RenderStyle;
  
  class RenderLayerStackingNode {
      WTF_MAKE_NONCOPYABLE(RenderLayerStackingNode);
  public:
      explicit RenderLayerStackingNode(RenderLayer*);
      ~RenderLayerStackingNode();
  
      unsigned zIndex() const { return renderer()->style()->zIndex(); }
  
      // A stacking context is a layer that has a non-auto z-index.
      bool isStackingContext() const { return !renderer()->style()->hasAutoZIndex(); }
  
      // Update our normal and z-index lists.
      void updateLayerListsIfNeeded();
  
      bool zOrderListsDirty() const { return m_zOrderListsDirty; }
      void dirtyZOrderLists();
      void updateZOrderLists();
      void clearZOrderLists();
      void dirtyStackingContextZOrderLists();
  
      bool hasPositiveZOrderList() const { return zOrderList() && zOrderList()->size(); }
  
      // FIXME: should check for dirtiness here?
      bool isNormalFlowOnly() const { return m_isNormalFlowOnly; }
      void updateIsNormalFlowOnly();
      bool normalFlowListDirty() const { return m_normalFlowListDirty; }
      void dirtyNormalFlowList();
  
      void updateStackingNodesAfterStyleChange(const RenderStyle* oldStyle);
  
      RenderLayerStackingNode* ancestorStackingContextNode() const;
  
      // Gets the enclosing stacking context for this node, possibly the node
      // itself, if it is a stacking context.
      RenderLayerStackingNode* enclosingStackingContextNode() { return isStackingContext() ? this : ancestorStackingContextNode(); }
  
      RenderLayer* layer() const { return m_layer; }
  
  #if ENABLE(ASSERT)
      bool layerListMutationAllowed() const { return m_layerListMutationAllowed; }
      void setLayerListMutationAllowed(bool flag) { m_layerListMutationAllowed = flag; }
  #endif
  
  private:
      friend class RenderLayerStackingNodeIterator;
      friend class RenderLayerStackingNodeReverseIterator;
      friend class RenderTreeAsText;
  
      Vector<RenderLayerStackingNode*>* zOrderList() const
      {
          ASSERT(!m_zOrderListsDirty);
          ASSERT(isStackingContext() || !m_zOrderList);
          return m_zOrderList.get();
      }
  
      Vector<RenderLayerStackingNode*>* normalFlowList() const
      {
          ASSERT(!m_normalFlowListDirty);
          return m_normalFlowList.get();
      }
  
      void rebuildZOrderLists();
      void collectLayers(OwnPtr<Vector<RenderLayerStackingNode*> >& zOrderList);
  
  #if ENABLE(ASSERT)
      bool isInStackingParentZOrderLists() const;
      bool isInStackingParentNormalFlowList() const;
      void updateStackingParentForZOrderLists(RenderLayerStackingNode* stackingParent);
      void updateStackingParentForNormalFlowList(RenderLayerStackingNode* stackingParent);
      void setStackingParent(RenderLayerStackingNode* stackingParent) { m_stackingParent = stackingParent; }
  #endif
  
      bool shouldBeNormalFlowOnly() const;
  
      void updateNormalFlowList();
  
      bool isDirtyStackingContext() const { return m_zOrderListsDirty && isStackingContext(); }
  
      // FIXME: Investigate changing this to Renderbox.
      RenderLayerModelObject* renderer() const;
  
      RenderLayer* m_layer;
  
      // m_zOrderList holds a sorted list of all the descendant nodes within
      // that have z-indices of 0 or greater (auto will count as 0).
      OwnPtr<Vector<RenderLayerStackingNode*> > m_zOrderList;
  
      // This list contains child nodes that cannot create stacking contexts.
      OwnPtr<Vector<RenderLayerStackingNode*> > m_normalFlowList;
  
      unsigned m_zOrderListsDirty : 1;
      unsigned m_normalFlowListDirty: 1;
      unsigned m_isNormalFlowOnly : 1;
  
  #if ENABLE(ASSERT)
      unsigned m_layerListMutationAllowed : 1;
      RenderLayerStackingNode* m_stackingParent;
  #endif
  };
  
  inline void RenderLayerStackingNode::clearZOrderLists()
  {
      ASSERT(!isStackingContext());
  
  #if ENABLE(ASSERT)
      updateStackingParentForZOrderLists(0);
  #endif
  
      m_zOrderList.clear();
  }
  
  inline void RenderLayerStackingNode::updateZOrderLists()
  {
      if (!m_zOrderListsDirty)
          return;
  
      if (!isStackingContext()) {
          clearZOrderLists();
          m_zOrderListsDirty = false;
          return;
      }
  
      rebuildZOrderLists();
  }
  
  #if ENABLE(ASSERT)
  class LayerListMutationDetector {
  public:
      explicit LayerListMutationDetector(RenderLayerStackingNode* stackingNode)
          : m_stackingNode(stackingNode)
          , m_previousMutationAllowedState(stackingNode->layerListMutationAllowed())
      {
          m_stackingNode->setLayerListMutationAllowed(false);
      }
  
      ~LayerListMutationDetector()
      {
          m_stackingNode->setLayerListMutationAllowed(m_previousMutationAllowedState);
      }
  
  private:
      RenderLayerStackingNode* m_stackingNode;
      bool m_previousMutationAllowedState;
  };
  #endif
  
  } // namespace blink
  
  #endif  // SKY_ENGINE_CORE_RENDERING_RENDERLAYERSTACKINGNODE_H_
  