Home | History | Annotate | Download | only in rendering
      1 /*
      2  * Copyright (C) 2003, 2009, 2012 Apple Inc. All rights reserved.
      3  * Copyright (C) 2013 Intel Corporation. All rights reserved.
      4  *
      5  * Portions are Copyright (C) 1998 Netscape Communications Corporation.
      6  *
      7  * Other contributors:
      8  *   Robert O'Callahan <roc+@cs.cmu.edu>
      9  *   David Baron <dbaron (at) fas.harvard.edu>
     10  *   Christian Biesinger <cbiesinger (at) web.de>
     11  *   Randall Jesup <rjesup (at) wgate.com>
     12  *   Roland Mainz <roland.mainz (at) informatik.med.uni-giessen.de>
     13  *   Josh Soref <timeless (at) mac.com>
     14  *   Boris Zbarsky <bzbarsky (at) mit.edu>
     15  *
     16  * This library is free software; you can redistribute it and/or
     17  * modify it under the terms of the GNU Lesser General Public
     18  * License as published by the Free Software Foundation; either
     19  * version 2.1 of the License, or (at your option) any later version.
     20  *
     21  * This library is distributed in the hope that it will be useful,
     22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     24  * Lesser General Public License for more details.
     25  *
     26  * You should have received a copy of the GNU Lesser General Public
     27  * License along with this library; if not, write to the Free Software
     28  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
     29  *
     30  * Alternatively, the contents of this file may be used under the terms
     31  * of either the Mozilla Public License Version 1.1, found at
     32  * http://www.mozilla.org/MPL/ (the "MPL") or the GNU General Public
     33  * License Version 2.0, found at http://www.fsf.org/copyleft/gpl.html
     34  * (the "GPL"), in which case the provisions of the MPL or the GPL are
     35  * applicable instead of those above.  If you wish to allow use of your
     36  * version of this file only under the terms of one of those two
     37  * licenses (the MPL or the GPL) and not to allow others to use your
     38  * version of this file under the LGPL, indicate your decision by
     39  * deletingthe provisions above and replace them with the notice and
     40  * other provisions required by the MPL or the GPL, as the case may be.
     41  * If you do not delete the provisions above, a recipient may use your
     42  * version of this file under any of the LGPL, the MPL or the GPL.
     43  */
     44 
     45 #ifndef RenderLayerStackingNode_h
     46 #define RenderLayerStackingNode_h
     47 
     48 #include "core/rendering/RenderLayerModelObject.h"
     49 #include "wtf/Noncopyable.h"
     50 #include "wtf/OwnPtr.h"
     51 #include "wtf/Vector.h"
     52 
     53 namespace WebCore {
     54 
     55 class RenderLayer;
     56 class RenderLayerCompositor;
     57 class RenderStyle;
     58 
     59 class RenderLayerStackingNode {
     60     WTF_MAKE_NONCOPYABLE(RenderLayerStackingNode);
     61 public:
     62     explicit RenderLayerStackingNode(RenderLayer*);
     63     ~RenderLayerStackingNode();
     64 
     65     int zIndex() const { return renderer()->style()->zIndex(); }
     66 
     67     // A stacking context is a layer that has a non-auto z-index.
     68     bool isStackingContext() const { return isStackingContext(renderer()->style()); }
     69 
     70     // A stacking container can have z-order lists. All stacking contexts are
     71     // stacking containers, but the converse is not true. Layers that use
     72     // composited scrolling are stacking containers, but they may not
     73     // necessarily be stacking contexts.
     74     bool isStackingContainer() const { return isStackingContext() || needsToBeStackingContainer(); }
     75 
     76     bool setNeedsToBeStackingContainer(bool);
     77 
     78     // Returns true if z ordering would not change if this layer were a stacking container.
     79     bool descendantsAreContiguousInStackingOrder() const;
     80     void setDescendantsAreContiguousInStackingOrderDirty(bool flag) { m_descendantsAreContiguousInStackingOrderDirty = flag; }
     81     void updateDescendantsAreContiguousInStackingOrder();
     82 
     83     // Update our normal and z-index lists.
     84     void updateLayerListsIfNeeded();
     85 
     86     bool zOrderListsDirty() const { return m_zOrderListsDirty; }
     87     void dirtyZOrderLists();
     88     void updateZOrderLists();
     89     void clearZOrderLists();
     90     void dirtyStackingContainerZOrderLists();
     91 
     92     bool hasPositiveZOrderList() const { return posZOrderList() && posZOrderList()->size(); }
     93     bool hasNegativeZOrderList() const { return negZOrderList() && negZOrderList()->size(); }
     94 
     95     bool isNormalFlowOnly() const { return m_isNormalFlowOnly; }
     96     void updateIsNormalFlowOnly();
     97     bool normalFlowListDirty() const { return m_normalFlowListDirty; }
     98     void dirtyNormalFlowList();
     99 
    100     enum PaintOrderListType {BeforePromote, AfterPromote};
    101     void computePaintOrderList(PaintOrderListType, Vector<RefPtr<Node> >&);
    102 
    103     void updateStackingNodesAfterStyleChange(const RenderStyle* oldStyle);
    104 
    105     RenderLayerStackingNode* ancestorStackingContainerNode() const;
    106     RenderLayerStackingNode* ancestorStackingNode() const;
    107 
    108     // Gets the enclosing stacking container for this node, possibly the node
    109     // itself, if it is a stacking container.
    110     RenderLayerStackingNode* enclosingStackingContainerNode() { return isStackingContainer() ? this : ancestorStackingContainerNode(); }
    111 
    112     RenderLayer* layer() const { return m_layer; }
    113 
    114 #if !ASSERT_DISABLED
    115     bool layerListMutationAllowed() const { return m_layerListMutationAllowed; }
    116     void setLayerListMutationAllowed(bool flag) { m_layerListMutationAllowed = flag; }
    117 #endif
    118 
    119 private:
    120     friend class RenderLayerStackingNodeIterator;
    121     friend class RenderLayerStackingNodeReverseIterator;
    122     friend class RenderTreeAsText;
    123 
    124     Vector<RenderLayerStackingNode*>* posZOrderList() const
    125     {
    126         ASSERT(!m_zOrderListsDirty);
    127         ASSERT(isStackingContainer() || !m_posZOrderList);
    128         return m_posZOrderList.get();
    129     }
    130 
    131     Vector<RenderLayerStackingNode*>* normalFlowList() const
    132     {
    133         ASSERT(!m_normalFlowListDirty);
    134         return m_normalFlowList.get();
    135     }
    136 
    137     Vector<RenderLayerStackingNode*>* negZOrderList() const
    138     {
    139         ASSERT(!m_zOrderListsDirty);
    140         ASSERT(isStackingContainer() || !m_negZOrderList);
    141         return m_negZOrderList.get();
    142     }
    143 
    144     enum CollectLayersBehavior {
    145         ForceLayerToStackingContainer,
    146         OverflowScrollCanBeStackingContainers,
    147         OnlyStackingContextsCanBeStackingContainers
    148     };
    149 
    150     bool isStackingContext(const RenderStyle*) const;
    151 
    152     void rebuildZOrderLists();
    153 
    154     // layerToForceAsStackingContainer allows us to build pre-promotion and
    155     // post-promotion layer lists, by allowing us to treat a layer as if it is a
    156     // stacking context, without adding a new member to RenderLayer or modifying
    157     // the style (which could cause extra allocations).
    158     void rebuildZOrderLists(OwnPtr<Vector<RenderLayerStackingNode*> >&, OwnPtr<Vector<RenderLayerStackingNode*> >&,
    159         const RenderLayerStackingNode* nodeToForceAsStackingContainer = 0,
    160         CollectLayersBehavior = OverflowScrollCanBeStackingContainers);
    161 
    162     void collectLayers(OwnPtr<Vector<RenderLayerStackingNode*> >&,
    163         OwnPtr<Vector<RenderLayerStackingNode*> >&, const RenderLayerStackingNode* nodeToForceAsStackingContainer = 0,
    164         CollectLayersBehavior = OverflowScrollCanBeStackingContainers);
    165 
    166 #if !ASSERT_DISABLED
    167     bool isInStackingParentZOrderLists() const;
    168     bool isInStackingParentNormalFlowList() const;
    169     void updateStackingParentForZOrderLists(RenderLayerStackingNode* stackingParent);
    170     void updateStackingParentForNormalFlowList(RenderLayerStackingNode* stackingParent);
    171     void setStackingParent(RenderLayerStackingNode* stackingParent) { m_stackingParent = stackingParent; }
    172 #endif
    173 
    174     bool shouldBeNormalFlowOnly() const;
    175     bool shouldBeNormalFlowOnlyIgnoringCompositedScrolling() const;
    176 
    177     void updateNormalFlowList();
    178     void dirtyNormalFlowListCanBePromotedToStackingContainer();
    179 
    180     void dirtySiblingStackingNodeCanBePromotedToStackingContainer();
    181 
    182     void collectBeforePromotionZOrderList(RenderLayerStackingNode*,
    183         OwnPtr<Vector<RenderLayerStackingNode*> >& posZOrderList, OwnPtr<Vector<RenderLayerStackingNode*> >& negZOrderList);
    184     void collectAfterPromotionZOrderList(RenderLayerStackingNode*,
    185         OwnPtr<Vector<RenderLayerStackingNode*> >& posZOrderList, OwnPtr<Vector<RenderLayerStackingNode*> >& negZOrderList);
    186 
    187     bool isDirtyStackingContainer() const { return m_zOrderListsDirty && isStackingContainer(); }
    188 
    189     bool needsToBeStackingContainer() const;
    190 
    191     RenderLayerCompositor* compositor() const;
    192     // FIXME: Investigate changing this to Renderbox.
    193     RenderLayerModelObject* renderer() const;
    194 
    195     RenderLayer* m_layer;
    196 
    197     // For stacking contexts, m_posZOrderList holds a sorted list of all the
    198     // descendant nodes within the stacking context that have z-indices of 0 or greater
    199     // (auto will count as 0). m_negZOrderList holds descendants within our stacking context with negative
    200     // z-indices.
    201     OwnPtr<Vector<RenderLayerStackingNode*> > m_posZOrderList;
    202     OwnPtr<Vector<RenderLayerStackingNode*> > m_negZOrderList;
    203 
    204     // This list contains child nodes that cannot create stacking contexts. For now it is just
    205     // overflow layers, but that may change in the future.
    206     OwnPtr<Vector<RenderLayerStackingNode*> > m_normalFlowList;
    207 
    208     // If this is true, then no non-descendant appears between any of our
    209     // descendants in stacking order. This is one of the requirements of being
    210     // able to safely become a stacking context.
    211     unsigned m_descendantsAreContiguousInStackingOrder : 1;
    212     unsigned m_descendantsAreContiguousInStackingOrderDirty : 1;
    213 
    214     unsigned m_zOrderListsDirty : 1;
    215     unsigned m_normalFlowListDirty: 1;
    216     unsigned m_isNormalFlowOnly : 1;
    217 
    218     unsigned m_needsToBeStackingContainer : 1;
    219     unsigned m_needsToBeStackingContainerHasBeenRecorded : 1;
    220 
    221 #if !ASSERT_DISABLED
    222     unsigned m_layerListMutationAllowed : 1;
    223     RenderLayerStackingNode* m_stackingParent;
    224 #endif
    225 };
    226 
    227 inline void RenderLayerStackingNode::clearZOrderLists()
    228 {
    229     ASSERT(!isStackingContainer());
    230 
    231 #if !ASSERT_DISABLED
    232     updateStackingParentForZOrderLists(0);
    233 #endif
    234 
    235     m_posZOrderList.clear();
    236     m_negZOrderList.clear();
    237 }
    238 
    239 inline void RenderLayerStackingNode::updateZOrderLists()
    240 {
    241     if (!m_zOrderListsDirty)
    242         return;
    243 
    244     if (!isStackingContainer()) {
    245         clearZOrderLists();
    246         m_zOrderListsDirty = false;
    247         return;
    248     }
    249 
    250     rebuildZOrderLists();
    251 }
    252 
    253 #if !ASSERT_DISABLED
    254 class LayerListMutationDetector {
    255 public:
    256     explicit LayerListMutationDetector(RenderLayerStackingNode* stackingNode)
    257         : m_stackingNode(stackingNode)
    258         , m_previousMutationAllowedState(stackingNode->layerListMutationAllowed())
    259     {
    260         m_stackingNode->setLayerListMutationAllowed(false);
    261     }
    262 
    263     ~LayerListMutationDetector()
    264     {
    265         m_stackingNode->setLayerListMutationAllowed(m_previousMutationAllowedState);
    266     }
    267 
    268 private:
    269     RenderLayerStackingNode* m_stackingNode;
    270     bool m_previousMutationAllowedState;
    271 };
    272 #endif
    273 
    274 } // namespace WebCore
    275 
    276 #endif // RenderLayerStackingNode_h
    277