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-06-02 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