LCOV - app.info - layout/base/RestyleTracker.h

LCOV - code coverage report
| Current view: | directory - layout/base - RestyleTracker.h (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 46 | 0 | 0.0 %
| Date: | 2012-07-07 | Functions: | 11 | 0 | 0.0 %

           1                 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
           2                 : /* ***** BEGIN LICENSE BLOCK *****
           3                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
           4                 :  *
           5                 :  * The contents of this file are subject to the Mozilla Public License Version
           6                 :  * 1.1 (the "License"); you may not use this file except in compliance with
           7                 :  * the License. You may obtain a copy of the License at
           8                 :  * http://www.mozilla.org/MPL/
           9                 :  *
          10                 :  * Software distributed under the License is distributed on an "AS IS" basis,
          11                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
          12                 :  * for the specific language governing rights and limitations under the
          13                 :  * License.
          14                 :  *
          15                 :  * The Original Code is mozilla.org code.
          16                 :  *
          17                 :  * The Initial Developer of the Original Code is
          18                 :  * the Mozilla Foundation.
          19                 :  * Portions created by the Initial Developer are Copyright (C) 2010
          20                 :  * the Initial Developer. All Rights Reserved.
          21                 :  *
          22                 :  * Contributor(s):
          23                 :  *     Boris Zbarsky <bzbarsky@mit.edu> (original author)
          24                 :  *
          25                 :  * Alternatively, the contents of this file may be used under the terms of
          26                 :  * either the GNU General Public License Version 2 or later (the "GPL"), or
          27                 :  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
          28                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
          29                 :  * of those above. If you wish to allow use of your version of this file only
          30                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
          31                 :  * use your version of this file under the terms of the MPL, indicate your
          32                 :  * decision by deleting the provisions above and replace them with the notice
          33                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
          34                 :  * the provisions above, a recipient may use your version of this file under
          35                 :  * the terms of any one of the MPL, the GPL or the LGPL.
          36                 :  *
          37                 :  * ***** END LICENSE BLOCK ***** */
          38                 :
          39                 : /**
          40                 :  * A class which manages pending restyles.  This handles keeping track
          41                 :  * of what nodes restyles need to happen on and so forth.
          42                 :  */
          43                 :
          44                 : #ifndef mozilla_css_RestyleTracker_h
          45                 : #define mozilla_css_RestyleTracker_h
          46                 :
          47                 : #include "mozilla/dom/Element.h"
          48                 : #include "nsDataHashtable.h"
          49                 : #include "nsIFrame.h"
          50                 :
          51                 : class nsCSSFrameConstructor;
          52                 :
          53                 : namespace mozilla {
          54                 : namespace css {
          55                 :
          56               0 : class RestyleTracker {
          57                 : public:
          58                 :   typedef mozilla::dom::Element Element;
          59                 :
          60               0 :   RestyleTracker(PRUint32 aRestyleBits,
          61                 :                  nsCSSFrameConstructor* aFrameConstructor) :
          62                 :     mRestyleBits(aRestyleBits), mFrameConstructor(aFrameConstructor),
          63               0 :     mHaveLaterSiblingRestyles(false)
          64                 :   {
          65               0 :     NS_PRECONDITION((mRestyleBits & ~ELEMENT_ALL_RESTYLE_FLAGS) == 0,
          66                 :                     "Why do we have these bits set?");
          67               0 :     NS_PRECONDITION((mRestyleBits & ELEMENT_PENDING_RESTYLE_FLAGS) != 0,
          68                 :                     "Must have a restyle flag");
          69               0 :     NS_PRECONDITION((mRestyleBits & ELEMENT_PENDING_RESTYLE_FLAGS) !=
          70                 :                       ELEMENT_PENDING_RESTYLE_FLAGS,
          71                 :                     "Shouldn't have both restyle flags set");
          72               0 :     NS_PRECONDITION((mRestyleBits & ~ELEMENT_PENDING_RESTYLE_FLAGS) != 0,
          73                 :                     "Must have root flag");
          74               0 :     NS_PRECONDITION((mRestyleBits & ~ELEMENT_PENDING_RESTYLE_FLAGS) !=
          75                 :                     (ELEMENT_ALL_RESTYLE_FLAGS & ~ELEMENT_PENDING_RESTYLE_FLAGS),
          76                 :                     "Shouldn't have both root flags");
          77               0 :   }
          78                 :
          79               0 :   bool Init() {
          80               0 :     return mPendingRestyles.Init();
          81                 :   }
          82                 :
          83               0 :   PRUint32 Count() const {
          84               0 :     return mPendingRestyles.Count();
          85                 :   }
          86                 :
          87                 :   /**
          88                 :    * Add a restyle for the given element to the tracker.  Returns true
          89                 :    * if the element already had eRestyle_LaterSiblings set on it.
          90                 :    */
          91                 :   bool AddPendingRestyle(Element* aElement, nsRestyleHint aRestyleHint,
          92                 :                            nsChangeHint aMinChangeHint);
          93                 :
          94                 :   /**
          95                 :    * Process the restyles we've been tracking.
          96                 :    */
          97               0 :   void ProcessRestyles() {
          98                 :     // Fast-path the common case (esp. for the animation restyle
          99                 :     // tracker) of not having anything to do.
         100               0 :     if (mPendingRestyles.Count()) {
         101               0 :       DoProcessRestyles();
         102                 :     }
         103               0 :   }
         104                 :
         105                 :   // Return our ELEMENT_HAS_PENDING_(ANIMATION_)RESTYLE bit
         106               0 :   PRUint32 RestyleBit() const {
         107               0 :     return mRestyleBits & ELEMENT_PENDING_RESTYLE_FLAGS;
         108                 :   }
         109                 :
         110                 :   // Return our ELEMENT_IS_POTENTIAL_(ANIMATION_)RESTYLE_ROOT bit
         111               0 :   PRUint32 RootBit() const {
         112               0 :     return mRestyleBits & ~ELEMENT_PENDING_RESTYLE_FLAGS;
         113                 :   }
         114                 :
         115               0 :   struct RestyleData {
         116                 :     nsRestyleHint mRestyleHint;  // What we want to restyle
         117                 :     nsChangeHint  mChangeHint;   // The minimal change hint for "self"
         118                 :   };
         119                 :
         120                 :   /**
         121                 :    * If the given Element has a restyle pending for it, return the
         122                 :    * relevant restyle data.  This function will clear everything other
         123                 :    * than a possible eRestyle_LaterSiblings hint for aElement out of
         124                 :    * our hashtable.  The returned aData will never have an
         125                 :    * eRestyle_LaterSiblings hint in it.
         126                 :    *
         127                 :    * The return value indicates whether any restyle data was found for
         128                 :    * the element.  If false is returned, then the state of *aData is
         129                 :    * undefined.
         130                 :    */
         131                 :   bool GetRestyleData(Element* aElement, RestyleData* aData);
         132                 :
         133                 :   /**
         134                 :    * The document we're associated with.
         135                 :    */
         136                 :   inline nsIDocument* Document() const;
         137                 :
         138               0 :   struct RestyleEnumerateData : public RestyleData {
         139                 :     nsRefPtr<Element> mElement;
         140                 :   };
         141                 :
         142                 : private:
         143                 :   /**
         144                 :    * Handle a single mPendingRestyles entry.  aRestyleHint must not
         145                 :    * include eRestyle_LaterSiblings; that needs to be dealt with
         146                 :    * before calling this function.
         147                 :    */
         148                 :   inline void ProcessOneRestyle(Element* aElement,
         149                 :                                 nsRestyleHint aRestyleHint,
         150                 :                                 nsChangeHint aChangeHint);
         151                 :
         152                 :   /**
         153                 :    * The guts of our restyle processing.
         154                 :    */
         155                 :   void DoProcessRestyles();
         156                 :
         157                 :   typedef nsDataHashtable<nsISupportsHashKey, RestyleData> PendingRestyleTable;
         158                 :   typedef nsAutoTArray< nsRefPtr<Element>, 32> RestyleRootArray;
         159                 :   // Our restyle bits.  These will be a subset of ELEMENT_ALL_RESTYLE_FLAGS, and
         160                 :   // will include one flag from ELEMENT_PENDING_RESTYLE_FLAGS and one flag
         161                 :   // that's not in ELEMENT_PENDING_RESTYLE_FLAGS.
         162                 :   PRUint32 mRestyleBits;
         163                 :   nsCSSFrameConstructor* mFrameConstructor; // Owns us
         164                 :   // A hashtable that maps elements to RestyleData structs.  The
         165                 :   // values only make sense if the element's current document is our
         166                 :   // document and it has our RestyleBit() flag set.  In particular,
         167                 :   // said bit might not be set if the element had a restyle posted and
         168                 :   // then was moved around in the DOM.
         169                 :   PendingRestyleTable mPendingRestyles;
         170                 :   // An array that keeps track of our possible restyle roots.  This
         171                 :   // maintains the invariant that if A and B are both restyle roots
         172                 :   // and A is an ancestor of B then A will come after B in the array.
         173                 :   // We maintain this invariant by checking whether an element has an
         174                 :   // ancestor with the restyle root bit set before appending it to the
         175                 :   // array.
         176                 :   RestyleRootArray mRestyleRoots;
         177                 :   // True if we have some entries with the eRestyle_LaterSiblings
         178                 :   // flag.  We need this to avoid enumerating the hashtable looking
         179                 :   // for such entries when we can't possibly have any.
         180                 :   bool mHaveLaterSiblingRestyles;
         181                 : };
         182                 :
         183               0 : inline bool RestyleTracker::AddPendingRestyle(Element* aElement,
         184                 :                                                 nsRestyleHint aRestyleHint,
         185                 :                                                 nsChangeHint aMinChangeHint)
         186                 : {
         187                 :   RestyleData existingData;
         188               0 :   existingData.mRestyleHint = nsRestyleHint(0);
         189               0 :   existingData.mChangeHint = NS_STYLE_HINT_NONE;
         190                 :
         191                 :   // Check the RestyleBit() flag before doing the hashtable Get, since
         192                 :   // it's possible that the data in the hashtable isn't actually
         193                 :   // relevant anymore (if the flag is not set).
         194               0 :   if (aElement->HasFlag(RestyleBit())) {
         195               0 :     mPendingRestyles.Get(aElement, &existingData);
         196                 :   } else {
         197               0 :     aElement->SetFlags(RestyleBit());
         198                 :   }
         199                 :
         200                 :   bool hadRestyleLaterSiblings =
         201               0 :     (existingData.mRestyleHint & eRestyle_LaterSiblings) != 0;
         202                 :   existingData.mRestyleHint =
         203               0 :     nsRestyleHint(existingData.mRestyleHint | aRestyleHint);
         204               0 :   NS_UpdateHint(existingData.mChangeHint, aMinChangeHint);
         205                 :
         206               0 :   mPendingRestyles.Put(aElement, existingData);
         207                 :
         208                 :   // We can only treat this element as a restyle root if we would
         209                 :   // actually restyle its descendants (so either call
         210                 :   // ReResolveStyleContext on it or just reframe it).
         211               0 :   if ((aRestyleHint & (eRestyle_Self | eRestyle_Subtree)) ||
         212                 :       (aMinChangeHint & nsChangeHint_ReconstructFrame)) {
         213               0 :     for (const Element* cur = aElement; !cur->HasFlag(RootBit()); ) {
         214               0 :       nsIContent* parent = cur->GetFlattenedTreeParent();
         215                 :       // Stop if we have no parent or the parent is not an element or
         216                 :       // we're part of the viewport scrollbars (because those are not
         217                 :       // frametree descendants of the primary frame of the root
         218                 :       // element).
         219                 :       // XXXbz maybe the primary frame of the root should be the root scrollframe?
         220               0 :       if (!parent || !parent->IsElement() ||
         221                 :           // If we've hit the root via a native anonymous kid and that
         222                 :           // this native anonymous kid is not obviously a descendant
         223                 :           // of the root's primary frame, assume we're under the root
         224                 :           // scrollbars.  Since those don't get reresolved when
         225                 :           // reresolving the root, we need to make sure to add the
         226                 :           // element to mRestyleRoots.
         227               0 :           (cur->IsInNativeAnonymousSubtree() && !parent->GetParent() &&
         228               0 :            cur->GetPrimaryFrame() &&
         229               0 :            cur->GetPrimaryFrame()->GetParent() != parent->GetPrimaryFrame())) {
         230               0 :         mRestyleRoots.AppendElement(aElement);
         231               0 :         break;
         232                 :       }
         233               0 :       cur = parent->AsElement();
         234                 :     }
         235                 :     // At this point some ancestor of aElement (possibly aElement
         236                 :     // itself) is in mRestyleRoots.  Set the root bit on aElement, to
         237                 :     // speed up searching for an existing root on its descendants.
         238               0 :     aElement->SetFlags(RootBit());
         239                 :   }
         240                 :
         241                 :   mHaveLaterSiblingRestyles =
         242               0 :     mHaveLaterSiblingRestyles || (aRestyleHint & eRestyle_LaterSiblings) != 0;
         243               0 :   return hadRestyleLaterSiblings;
         244                 : }
         245                 :
         246                 : } // namespace css
         247                 : } // namespace mozilla
         248                 :
         249                 : #endif /* mozilla_css_RestyleTracker_h */

Generated by: LCOV version 1.7