LCOV - code coverage report
Current view: top level - layout/style - nsRuleNode.h (source / functions) Hit Total Coverage
Test: output.info Lines: 161 171 94.2 %
Date: 2017-07-14 16:53:18 Functions: 47 50 94.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : /*
       7             :  * a node in the lexicographic tree of rules that match an element,
       8             :  * responsible for converting the rules' information into computed style
       9             :  */
      10             : 
      11             : #ifndef nsRuleNode_h___
      12             : #define nsRuleNode_h___
      13             : 
      14             : #include "mozilla/ArenaObjectID.h"
      15             : #include "mozilla/LinkedList.h"
      16             : #include "mozilla/PodOperations.h"
      17             : #include "mozilla/RangedArray.h"
      18             : #include "mozilla/RuleNodeCacheConditions.h"
      19             : #include "mozilla/LookAndFeel.h"
      20             : #include "mozilla/SheetType.h"
      21             : #include "nsPresContext.h"
      22             : #include "nsStyleStruct.h"
      23             : 
      24             : class nsCSSPropertyIDSet;
      25             : class nsCSSValue;
      26             : class nsFontMetrics;
      27             : class nsIStyleRule;
      28             : class nsStyleCoord;
      29             : struct nsCSSRect;
      30             : struct nsCSSValueList;
      31             : struct nsCSSValuePairList;
      32             : struct nsRuleData;
      33             : 
      34             : namespace mozilla {
      35             :   class GeckoStyleContext;
      36             : }
      37             : 
      38             : struct nsInheritedStyleData
      39             : {
      40             :   mozilla::RangedArray<void*,
      41             :                        nsStyleStructID_Inherited_Start,
      42             :                        nsStyleStructID_Inherited_Count> mStyleStructs;
      43             : 
      44          23 :   void* operator new(size_t sz, nsPresContext* aContext) {
      45             :     return aContext->PresShell()->
      46          23 :       AllocateByObjectID(mozilla::eArenaObjectID_nsInheritedStyleData, sz);
      47             :   }
      48             : 
      49        1618 :   void DestroyStructs(uint64_t aBits, nsPresContext* aContext) {
      50             : #define STYLE_STRUCT_INHERITED(name, checkdata_cb) \
      51             :     void *name##Data = mStyleStructs[eStyleStruct_##name]; \
      52             :     if (name##Data && !(aBits & NS_STYLE_INHERIT_BIT(name))) \
      53             :       static_cast<nsStyle##name*>(name##Data)->Destroy(aContext);
      54             : #define STYLE_STRUCT_RESET(name, checkdata_cb)
      55             : 
      56             : #include "nsStyleStructList.h"
      57             : 
      58             : #undef STYLE_STRUCT_INHERITED
      59             : #undef STYLE_STRUCT_RESET
      60        1618 :   }
      61             : 
      62           0 :   void Destroy(uint64_t aBits, nsPresContext* aContext) {
      63           0 :     DestroyStructs(aBits, aContext);
      64             :     aContext->PresShell()->
      65           0 :       FreeByObjectID(mozilla::eArenaObjectID_nsInheritedStyleData, this);
      66           0 :   }
      67             : 
      68        2226 :   nsInheritedStyleData() {
      69       22260 :     for (nsStyleStructID i = nsStyleStructID_Inherited_Start;
      70       22260 :          i < nsStyleStructID_Inherited_Start + nsStyleStructID_Inherited_Count;
      71       20034 :          i = nsStyleStructID(i + 1)) {
      72       20034 :       mStyleStructs[i] = nullptr;
      73             :     }
      74        2226 :   }
      75             : };
      76             : 
      77             : struct nsResetStyleData
      78             : {
      79             :   mozilla::RangedArray<void*,
      80             :                        nsStyleStructID_Reset_Start,
      81             :                        nsStyleStructID_Reset_Count> mStyleStructs;
      82             : 
      83         890 :   nsResetStyleData()
      84         890 :   {
      85       14240 :     for (nsStyleStructID i = nsStyleStructID_Reset_Start;
      86       14240 :          i < nsStyleStructID_Reset_Start + nsStyleStructID_Reset_Count;
      87       13350 :          i = nsStyleStructID(i + 1)) {
      88       13350 :       mStyleStructs[i] = nullptr;
      89             :     }
      90         890 :   }
      91             : 
      92         890 :   void* operator new(size_t sz, nsPresContext* aContext) {
      93             :     return aContext->PresShell()->
      94         890 :       AllocateByObjectID(mozilla::eArenaObjectID_nsResetStyleData, sz);
      95             :   }
      96             : 
      97         643 :   void Destroy(uint64_t aBits, nsPresContext* aContext) {
      98             : #define STYLE_STRUCT_RESET(name, checkdata_cb) \
      99             :     void *name##Data = mStyleStructs[eStyleStruct_##name]; \
     100             :     if (name##Data && !(aBits & NS_STYLE_INHERIT_BIT(name))) \
     101             :       static_cast<nsStyle##name*>(name##Data)->Destroy(aContext);
     102             : #define STYLE_STRUCT_INHERITED(name, checkdata_cb)
     103             : 
     104             : #include "nsStyleStructList.h"
     105             : 
     106             : #undef STYLE_STRUCT_RESET
     107             : #undef STYLE_STRUCT_INHERITED
     108             : 
     109             :     aContext->PresShell()->
     110         643 :       FreeByObjectID(mozilla::eArenaObjectID_nsResetStyleData, this);
     111         643 :   }
     112             : };
     113             : 
     114             : struct nsConditionalResetStyleData
     115             : {
     116      459738 :   static uint32_t GetBitForSID(const nsStyleStructID aSID) {
     117      459738 :     return 1 << aSID;
     118             :   }
     119             : 
     120             :   struct Entry
     121             :   {
     122          72 :     Entry(const mozilla::RuleNodeCacheConditions& aConditions,
     123             :           void* aStyleStruct,
     124             :           Entry* aNext)
     125          72 :       : mConditions(aConditions), mStyleStruct(aStyleStruct), mNext(aNext) {}
     126             : 
     127          72 :     void* operator new(size_t sz, nsPresContext* aContext) {
     128          72 :       return aContext->PresShell()->AllocateByObjectID(
     129          72 :           mozilla::eArenaObjectID_nsConditionalResetStyleDataEntry, sz);
     130             :     }
     131             : 
     132             :     const mozilla::RuleNodeCacheConditions mConditions;
     133             :     void* const mStyleStruct;
     134             :     Entry* const mNext;
     135             :   };
     136             : 
     137             :   // Each entry is either a pointer to a style struct or a
     138             :   // pointer to an Entry object.  A bit in mConditionalBits
     139             :   // means that it is an Entry.
     140             :   mozilla::RangedArray<void*,
     141             :                        nsStyleStructID_Reset_Start,
     142             :                        nsStyleStructID_Reset_Count> mEntries;
     143             : 
     144             :   uint32_t mConditionalBits;
     145             : 
     146        1175 :   nsConditionalResetStyleData()
     147        1175 :   {
     148       18800 :     for (nsStyleStructID i = nsStyleStructID_Reset_Start;
     149       18800 :          i < nsStyleStructID_Reset_Start + nsStyleStructID_Reset_Count;
     150       17625 :          i = nsStyleStructID(i + 1)) {
     151       17625 :       mEntries[i] = nullptr;
     152             :     }
     153        1175 :     mConditionalBits = 0;
     154        1175 :   }
     155             : 
     156        1175 :   void* operator new(size_t sz, nsPresContext* aContext) {
     157        1175 :     return aContext->PresShell()->AllocateByObjectID(
     158        1175 :         mozilla::eArenaObjectID_nsConditionalResetStyleData, sz);
     159             :   }
     160             : 
     161       22930 :   void* GetStyleData(nsStyleStructID aSID) const {
     162       22930 :     if (mConditionalBits & GetBitForSID(aSID)) {
     163           7 :       return nullptr;
     164             :     }
     165       22923 :     return mEntries[aSID];
     166             :   }
     167             : 
     168      281501 :   void* GetStyleData(nsStyleStructID aSID,
     169             :                      mozilla::GeckoStyleContext* aStyleContext,
     170             :                      bool aCanComputeData) const {
     171      281501 :     if (!(mConditionalBits & GetBitForSID(aSID))) {
     172      281428 :       return mEntries[aSID];
     173             :     }
     174          73 :     if (!aCanComputeData) {
     175             :       // If aCanComputeData is false, then any previously-computed data
     176             :       // would have been cached on the style context.  Therefore it's
     177             :       // unnecessary to check the conditional data.  It's also
     178             :       // incorrect, because calling e->mConditions.Matches() below could
     179             :       // cause additional structs to be computed, which is incorrect
     180             :       // during CalcStyleDifference.
     181          23 :       return nullptr;
     182             :     }
     183          50 :     return GetConditionalStyleData(aSID, aStyleContext);
     184             :   }
     185             : 
     186             : private:
     187             :   // non-inline helper for GetStyleData
     188             :   void* GetConditionalStyleData(nsStyleStructID aSID,
     189             :                                 mozilla::GeckoStyleContext* aStyleContext) const;
     190             : 
     191             : public:
     192       12577 :   void SetStyleData(nsStyleStructID aSID, void* aStyleStruct) {
     193       12577 :     MOZ_ASSERT(!(mConditionalBits & GetBitForSID(aSID)),
     194             :                "rule node should not have unconditional and conditional style "
     195             :                "data for a given struct");
     196       12577 :     mConditionalBits &= ~GetBitForSID(aSID);
     197       12577 :     mEntries[aSID] = aStyleStruct;
     198       12577 :   }
     199             : 
     200          72 :   void SetStyleData(nsStyleStructID aSID,
     201             :                     nsPresContext* aPresContext,
     202             :                     void* aStyleStruct,
     203             :                     const mozilla::RuleNodeCacheConditions& aConditions) {
     204          72 :     if (!(mConditionalBits & GetBitForSID(aSID))) {
     205          72 :       MOZ_ASSERT(!mEntries[aSID],
     206             :                  "rule node should not have unconditional and conditional "
     207             :                  "style data for a given struct");
     208          72 :       mEntries[aSID] = nullptr;
     209             :     }
     210             : 
     211          72 :     MOZ_ASSERT(aConditions.CacheableWithDependencies(),
     212             :                "don't call SetStyleData with a cache key that has no "
     213             :                "conditions or is uncacheable");
     214             : 
     215             : #ifdef DEBUG
     216          72 :     for (Entry* e = static_cast<Entry*>(mEntries[aSID]); e; e = e->mNext) {
     217           0 :       NS_WARNING_ASSERTION(e->mConditions != aConditions,
     218             :                            "wasteful to have duplicate conditional style data");
     219             :     }
     220             : #endif
     221             : 
     222          72 :     mConditionalBits |= GetBitForSID(aSID);
     223          72 :     mEntries[aSID] =
     224             :       new (aPresContext) Entry(aConditions, aStyleStruct,
     225          72 :                                static_cast<Entry*>(mEntries[aSID]));
     226          72 :   }
     227             : 
     228         516 :   void Destroy(uint64_t aBits, nsPresContext* aContext) {
     229             : #define STYLE_STRUCT_RESET(name, checkdata_cb)                                 \
     230             :     void* name##Ptr = mEntries[eStyleStruct_##name];                           \
     231             :     if (name##Ptr) {                                                           \
     232             :       if (!(mConditionalBits & NS_STYLE_INHERIT_BIT(name))) {                  \
     233             :         if (!(aBits & NS_STYLE_INHERIT_BIT(name))) {                           \
     234             :           static_cast<nsStyle##name*>(name##Ptr)->Destroy(aContext);           \
     235             :         }                                                                      \
     236             :       } else {                                                                 \
     237             :         Entry* e = static_cast<Entry*>(name##Ptr);                             \
     238             :         MOZ_ASSERT(e, "if mConditionalBits bit is set, we must have at least " \
     239             :                       "one conditional style struct");                         \
     240             :         do {                                                                   \
     241             :           static_cast<nsStyle##name*>(e->mStyleStruct)->Destroy(aContext);     \
     242             :           Entry* next = e->mNext;                                              \
     243             :           aContext->PresShell()->FreeByObjectID(                               \
     244             :               mozilla::eArenaObjectID_nsConditionalResetStyleDataEntry, e);    \
     245             :           e = next;                                                            \
     246             :         } while (e);                                                           \
     247             :       }                                                                        \
     248             :     }
     249             : #define STYLE_STRUCT_INHERITED(name, checkdata_cb)
     250             : 
     251             : #include "nsStyleStructList.h"
     252             : 
     253             : #undef STYLE_STRUCT_RESET
     254             : #undef STYLE_STRUCT_INHERITED
     255             : 
     256         516 :     aContext->PresShell()->FreeByObjectID(
     257         516 :         mozilla::eArenaObjectID_nsConditionalResetStyleData, this);
     258         516 :   }
     259             : 
     260             : };
     261             : 
     262             : struct nsCachedStyleData
     263             : {
     264             :   nsInheritedStyleData* mInheritedData;
     265             :   nsConditionalResetStyleData* mResetData;
     266             : 
     267      402940 :   static bool IsReset(const nsStyleStructID aSID) {
     268      402940 :     MOZ_ASSERT(0 <= aSID && aSID < nsStyleStructID_Length,
     269             :                "must be an inherited or reset SID");
     270      402940 :     return nsStyleStructID_Reset_Start <= aSID;
     271             :   }
     272             : 
     273           0 :   static bool IsInherited(const nsStyleStructID aSID) {
     274           0 :     return !IsReset(aSID);
     275             :   }
     276             : 
     277      129959 :   static uint32_t GetBitForSID(const nsStyleStructID aSID) {
     278      129959 :     return nsConditionalResetStyleData::GetBitForSID(aSID);
     279             :   }
     280             : 
     281       48495 :   void* NS_FASTCALL GetStyleData(const nsStyleStructID aSID) {
     282       48495 :     if (IsReset(aSID)) {
     283       34440 :       if (mResetData) {
     284       21529 :         return mResetData->GetStyleData(aSID);
     285             :       }
     286             :     } else {
     287       14055 :       if (mInheritedData) {
     288          62 :         return mInheritedData->mStyleStructs[aSID];
     289             :       }
     290             :     }
     291       26904 :     return nullptr;
     292             :   }
     293             : 
     294         827 :   void* NS_FASTCALL GetStyleData(const nsStyleStructID aSID,
     295             :                                  mozilla::GeckoStyleContext* aStyleContext,
     296             :                                  bool aCanComputeData) {
     297         827 :     if (IsReset(aSID)) {
     298         412 :       if (mResetData) {
     299         412 :         return mResetData->GetStyleData(aSID, aStyleContext, aCanComputeData);
     300             :       }
     301             :     } else {
     302         415 :       if (mInheritedData) {
     303           8 :         return mInheritedData->mStyleStructs[aSID];
     304             :       }
     305             :     }
     306         407 :     return nullptr;
     307             :   }
     308             : 
     309       11195 :   void NS_FASTCALL SetStyleData(const nsStyleStructID aSID,
     310             :                                 nsPresContext *aPresContext, void *aData) {
     311       11195 :     if (IsReset(aSID)) {
     312       11176 :       if (!mResetData) {
     313         798 :         mResetData = new (aPresContext) nsConditionalResetStyleData;
     314             :       }
     315       11176 :       mResetData->SetStyleData(aSID, aData);
     316             :     } else {
     317          19 :       if (!mInheritedData) {
     318          13 :         mInheritedData = new (aPresContext) nsInheritedStyleData;
     319             :       }
     320          19 :       mInheritedData->mStyleStructs[aSID] = aData;
     321             :     }
     322       11195 :   }
     323             : 
     324             :   // Typesafe and faster versions of the above
     325             :   #define STYLE_STRUCT_INHERITED(name_, checkdata_cb_)                         \
     326             :     nsStyle##name_ * NS_FASTCALL GetStyle##name_ () {                          \
     327             :       return mInheritedData ? static_cast<nsStyle##name_*>(                    \
     328             :         mInheritedData->mStyleStructs[eStyleStruct_##name_]) : nullptr;        \
     329             :     }
     330             :   #define STYLE_STRUCT_RESET(name_, checkdata_cb_)                             \
     331             :     nsStyle##name_ * NS_FASTCALL GetStyle##name_ (mozilla::GeckoStyleContext* aContext,    \
     332             :                                                   bool aCanComputeData) {      \
     333             :       return mResetData ? static_cast<nsStyle##name_*>(                        \
     334             :         mResetData->GetStyleData(eStyleStruct_##name_, aContext,               \
     335             :                                  aCanComputeData))                             \
     336             :                         : nullptr;                                             \
     337             :     }
     338             :   #include "nsStyleStructList.h"
     339             :   #undef STYLE_STRUCT_RESET
     340             :   #undef STYLE_STRUCT_INHERITED
     341             : 
     342         516 :   void Destroy(uint64_t aBits, nsPresContext* aContext) {
     343         516 :     if (mResetData)
     344         516 :       mResetData->Destroy(aBits, aContext);
     345         516 :     if (mInheritedData)
     346           0 :       mInheritedData->Destroy(aBits, aContext);
     347         516 :     mResetData = nullptr;
     348         516 :     mInheritedData = nullptr;
     349         516 :   }
     350             : 
     351        2022 :   nsCachedStyleData() :mInheritedData(nullptr), mResetData(nullptr) {}
     352         946 :   ~nsCachedStyleData() {}
     353             : };
     354             : 
     355             : /**
     356             :  * nsRuleNode is a node in a lexicographic tree (the "rule tree")
     357             :  * indexed by style rules (implementations of nsIStyleRule).
     358             :  *
     359             :  * The rule tree is owned by the nsStyleSet and is destroyed when the
     360             :  * presentation of the document goes away. Its entries are reference-
     361             :  * counted, with strong references held by child nodes, style structs
     362             :  * and (for the root), the style set. Rule nodes are not immediately
     363             :  * destroyed when their reference-count drops to zero, but are instead
     364             :  * destroyed during a GC sweep.
     365             :  *
     366             :  * An mozilla::GeckoStyleContext, which represents the computed style data for an
     367             :  * element, points to an nsRuleNode.  The path from the root of the rule
     368             :  * tree to the mozilla::GeckoStyleContext's mRuleNode gives the list of the rules
     369             :  * matched, from least important in the cascading order to most
     370             :  * important in the cascading order.
     371             :  *
     372             :  * The reason for using a lexicographic tree is that it allows for
     373             :  * sharing of style data, which saves both memory (for storing the
     374             :  * computed style data) and time (for computing them).  This sharing
     375             :  * depends on the computed style data being stored in structs (nsStyle*)
     376             :  * that contain only properties that are inherited by default
     377             :  * ("inherited structs") or structs that contain only properties that
     378             :  * are not inherited by default ("reset structs").  The optimization
     379             :  * depends on the normal case being that style rules specify relatively
     380             :  * few properties and even that elements generally have relatively few
     381             :  * properties specified.  This allows sharing in the following ways:
     382             :  *   1. [mainly reset structs] When a style data struct will contain the
     383             :  *      same computed value for any elements that match the same set of
     384             :  *      rules (common for reset structs), it can be stored on the
     385             :  *      nsRuleNode instead of on the mozilla::GeckoStyleContext.
     386             :  *   2. [only? reset structs] When (1) occurs, and an nsRuleNode doesn't
     387             :  *      have any rules that change the values in the struct, the
     388             :  *      nsRuleNode can share that struct with its parent nsRuleNode.
     389             :  *   3. [mainly inherited structs] When an element doesn't match any
     390             :  *      rules that change the value of a property (or, in the edge case,
     391             :  *      when all the values specified are 'inherit'), the mozilla::GeckoStyleContext
     392             :  *      can use the same nsStyle* struct as its parent mozilla::GeckoStyleContext.
     393             :  *
     394             :  * Since the data represented by an nsIStyleRule are immutable, the data
     395             :  * represented by an nsRuleNode are also immutable.
     396             :  */
     397             : 
     398             : enum nsFontSizeType {
     399             :   eFontSize_HTML = 1,
     400             :   eFontSize_CSS = 2
     401             : };
     402             : 
     403             : // Note: This LinkedListElement is used for storing unused nodes in the
     404             : // linked list on nsStyleSet. We use mNextSibling for the singly-linked
     405             : // sibling list.
     406             : class nsRuleNode : public mozilla::LinkedListElement<nsRuleNode> {
     407             : public:
     408             :   enum RuleDetail {
     409             :     eRuleNone, // No props have been specified at all.
     410             :     eRulePartialReset, // At least one prop with a non-"inherit" value
     411             :                        // has been specified.  No props have been
     412             :                        // specified with an "inherit" value.  At least
     413             :                        // one prop remains unspecified.
     414             :     eRulePartialMixed, // At least one prop with a non-"inherit" value
     415             :                        // has been specified.  Some props may also have
     416             :                        // been specified with an "inherit" value.  At
     417             :                        // least one prop remains unspecified.
     418             :     eRulePartialInherited, // Only props with "inherit" values have
     419             :                            // have been specified.  At least one prop
     420             :                            // remains unspecified.
     421             :     eRuleFullReset, // All props have been specified.  None has an
     422             :                     // "inherit" value.
     423             :     eRuleFullMixed, // All props have been specified.  At least one has
     424             :                     // a non-"inherit" value.
     425             :     eRuleFullInherited  // All props have been specified with "inherit"
     426             :                         // values.
     427             :   };
     428             : 
     429             : private:
     430             :   nsPresContext* const mPresContext; // Our pres context.
     431             : 
     432             :   const RefPtr<nsRuleNode> mParent; // A pointer to the parent node in the tree.
     433             :                                     // This enables us to walk backwards from the
     434             :                                     // most specific rule matched to the least
     435             :                                     // specific rule (which is the optimal order to
     436             :                                     // use for lookups of style properties.
     437             : 
     438             :   const nsCOMPtr<nsIStyleRule> mRule; // A pointer to our specific rule.
     439             : 
     440             :   nsRuleNode* mNextSibling; // This value should be used only by the
     441             :                             // parent, since the parent may store
     442             :                             // children in a hash, which means this
     443             :                             // pointer is not meaningful.  Order of
     444             :                             // siblings is also not meaningful.
     445             : 
     446             :   struct Key {
     447             :     nsIStyleRule* mRule;
     448             :     mozilla::SheetType mLevel;
     449             :     bool mIsImportantRule;
     450             : 
     451       51707 :     Key(nsIStyleRule* aRule, mozilla::SheetType aLevel, bool aIsImportantRule)
     452       51707 :       : mRule(aRule), mLevel(aLevel), mIsImportantRule(aIsImportantRule)
     453       51707 :     {}
     454             : 
     455       39928 :     bool operator==(const Key& aOther) const
     456             :     {
     457       49715 :       return mRule == aOther.mRule &&
     458       49715 :              mLevel == aOther.mLevel &&
     459       49715 :              mIsImportantRule == aOther.mIsImportantRule;
     460             :     }
     461             : 
     462       38259 :     bool operator!=(const Key& aOther) const
     463             :     {
     464       38259 :       return !(*this == aOther);
     465             :     }
     466             :   };
     467             : 
     468             :   static PLDHashNumber
     469             :   ChildrenHashHashKey(const void *aKey);
     470             : 
     471             :   static bool
     472             :   ChildrenHashMatchEntry(const PLDHashEntryHdr *aHdr, const void *aKey);
     473             : 
     474             :   static const PLDHashTableOps ChildrenHashOps;
     475             : 
     476       40056 :   Key GetKey() const {
     477       40056 :     return Key(mRule, GetLevel(), IsImportantRule());
     478             :   }
     479             : 
     480             :   // The children of this node are stored in either a hashtable or list
     481             :   // that maps from rules to our nsRuleNode children.  When matching
     482             :   // rules, we use this mapping to transition from node to node
     483             :   // (constructing new nodes as needed to flesh out the tree).
     484             : 
     485             :   union {
     486             :     void* asVoid;
     487             :     nsRuleNode* asList;
     488             :     PLDHashTable* asHash;
     489             :   } mChildren; // Accessed only through the methods below.
     490             : 
     491             :   enum {
     492             :     kTypeMask = 0x1,
     493             :     kListType = 0x0,
     494             :     kHashType = 0x1
     495             :   };
     496             :   enum {
     497             :     // Maximum to have in a list before converting to a hashtable.
     498             :     // XXX Need to optimize this.
     499             :     kMaxChildrenInList = 32
     500             :   };
     501             : 
     502       13614 :   bool HaveChildren() const {
     503       13614 :     return mChildren.asVoid != nullptr;
     504             :   }
     505       22950 :   bool ChildrenAreHashed() {
     506       22950 :     return (intptr_t(mChildren.asVoid) & kTypeMask) == kHashType;
     507             :   }
     508       10684 :   nsRuleNode* ChildrenList() {
     509       10684 :     return mChildren.asList;
     510             :   }
     511             :   nsRuleNode** ChildrenListPtr() {
     512             :     return &mChildren.asList;
     513             :   }
     514        1669 :   PLDHashTable* ChildrenHash() {
     515        1669 :     return (PLDHashTable*) (intptr_t(mChildren.asHash) & ~intptr_t(kTypeMask));
     516             :   }
     517        1928 :   void SetChildrenList(nsRuleNode *aList) {
     518        1928 :     NS_ASSERTION(!(intptr_t(aList) & kTypeMask),
     519             :                  "pointer not 2-byte aligned");
     520        1928 :     mChildren.asList = aList;
     521        1928 :   }
     522           2 :   void SetChildrenHash(PLDHashTable *aHashtable) {
     523           2 :     NS_ASSERTION(!(intptr_t(aHashtable) & kTypeMask),
     524             :                  "pointer not 2-byte aligned");
     525           2 :     mChildren.asHash = (PLDHashTable*)(intptr_t(aHashtable) | kHashType);
     526           2 :   }
     527             :   void ConvertChildrenToHash(int32_t aNumKids);
     528             : 
     529             :   void RemoveChild(nsRuleNode* aNode);
     530             : 
     531             :   nsCachedStyleData mStyleData;   // Any data we cached on the rule node.
     532             : 
     533             :   uint32_t mDependentBits; // Used to cache the fact that we can look up
     534             :                            // cached data under a parent rule.
     535             : 
     536             :   uint32_t mNoneBits; // Used to cache the fact that the branch to this
     537             :                       // node specifies no non-inherited data for a
     538             :                       // given struct type.  (This usually implies that
     539             :                       // the entire branch specifies no non-inherited
     540             :                       // data, although not necessarily, if a
     541             :                       // non-inherited value is overridden by an
     542             :                       // explicit 'inherit' value.)  For example, if an
     543             :                       // entire rule branch specifies no color
     544             :                       // information, then a bit will be set along every
     545             :                       // rule node on that branch, so that you can break
     546             :                       // out of the rule tree early and just inherit
     547             :                       // from the parent style context.  The presence of
     548             :                       // this bit means we should just get inherited
     549             :                       // data from the parent style context, and it is
     550             :                       // never used for reset structs since their
     551             :                       // Compute*Data functions don't initialize from
     552             :                       // inherited data.
     553             : 
     554             :   // Reference count. Style contexts hold strong references to their rule node,
     555             :   // and rule nodes hold strong references to their parent.
     556             :   //
     557             :   // When the refcount drops to zero, we don't necessarily free the node.
     558             :   // Instead, we notify the style set, which performs periodic sweeps.
     559             :   uint32_t mRefCnt;
     560             : 
     561             : public:
     562             :   // Infallible overloaded new operator that allocates from a presShell arena.
     563             :   void* operator new(size_t sz, nsPresContext* aContext);
     564             :   void Destroy();
     565             : 
     566             :   // Implemented in nsStyleSet.h, since it needs to know about nsStyleSet.
     567             :   inline void AddRef();
     568             : 
     569             :   // Implemented in nsStyleSet.h, since it needs to know about nsStyleSet.
     570             :   inline void Release();
     571             : 
     572             : protected:
     573             :   void PropagateDependentBit(nsStyleStructID aSID, nsRuleNode* aHighestNode,
     574             :                              void* aStruct);
     575             :   void PropagateNoneBit(uint32_t aBit, nsRuleNode* aHighestNode);
     576             :   static void PropagateGrandancestorBit(mozilla::GeckoStyleContext* aContext,
     577             :                                         mozilla::GeckoStyleContext* aContextInheritedFrom);
     578             : 
     579             :   const void* SetDefaultOnRoot(const nsStyleStructID aSID,
     580             :                                mozilla::GeckoStyleContext* aContext);
     581             : 
     582             :   /**
     583             :    * Resolves any property values in aRuleData for a given style struct that
     584             :    * have eCSSUnit_TokenStream values, by resolving them against the computed
     585             :    * variable values on the style context and re-parsing the property.
     586             :    *
     587             :    * @return Whether any properties with eCSSUnit_TokenStream values were
     588             :    *   encountered.
     589             :    */
     590             :   static bool ResolveVariableReferences(const nsStyleStructID aSID,
     591             :                                         nsRuleData* aRuleData,
     592             :                                         mozilla::GeckoStyleContext* aContext);
     593             : 
     594             :   const void*
     595             :     WalkRuleTree(const nsStyleStructID aSID, mozilla::GeckoStyleContext* aContext);
     596             : 
     597             :   const void*
     598             :     ComputeDisplayData(void* aStartStruct,
     599             :                        const nsRuleData* aRuleData,
     600             :                        mozilla::GeckoStyleContext* aContext, nsRuleNode* aHighestNode,
     601             :                        RuleDetail aRuleDetail,
     602             :                        const mozilla::RuleNodeCacheConditions aConditions);
     603             : 
     604             :   const void*
     605             :     ComputeVisibilityData(void* aStartStruct,
     606             :                           const nsRuleData* aRuleData,
     607             :                           mozilla::GeckoStyleContext* aContext, nsRuleNode* aHighestNode,
     608             :                           RuleDetail aRuleDetail,
     609             :                           const mozilla::RuleNodeCacheConditions aConditions);
     610             : 
     611             :   const void*
     612             :     ComputeFontData(void* aStartStruct,
     613             :                     const nsRuleData* aRuleData,
     614             :                     mozilla::GeckoStyleContext* aContext, nsRuleNode* aHighestNode,
     615             :                     RuleDetail aRuleDetail,
     616             :                     const mozilla::RuleNodeCacheConditions aConditions);
     617             : 
     618             :   const void*
     619             :     ComputeColorData(void* aStartStruct,
     620             :                      const nsRuleData* aRuleData,
     621             :                      mozilla::GeckoStyleContext* aContext, nsRuleNode* aHighestNode,
     622             :                      RuleDetail aRuleDetail,
     623             :                      const mozilla::RuleNodeCacheConditions aConditions);
     624             : 
     625             :   const void*
     626             :     ComputeBackgroundData(void* aStartStruct,
     627             :                           const nsRuleData* aRuleData,
     628             :                           mozilla::GeckoStyleContext* aContext, nsRuleNode* aHighestNode,
     629             :                           RuleDetail aRuleDetail,
     630             :                           const mozilla::RuleNodeCacheConditions aConditions);
     631             : 
     632             :   const void*
     633             :     ComputeMarginData(void* aStartStruct,
     634             :                       const nsRuleData* aRuleData,
     635             :                       mozilla::GeckoStyleContext* aContext, nsRuleNode* aHighestNode,
     636             :                       RuleDetail aRuleDetail,
     637             :                       const mozilla::RuleNodeCacheConditions aConditions);
     638             : 
     639             :   const void*
     640             :     ComputeBorderData(void* aStartStruct,
     641             :                       const nsRuleData* aRuleData,
     642             :                       mozilla::GeckoStyleContext* aContext, nsRuleNode* aHighestNode,
     643             :                       RuleDetail aRuleDetail,
     644             :                       const mozilla::RuleNodeCacheConditions aConditions);
     645             : 
     646             :   const void*
     647             :     ComputePaddingData(void* aStartStruct,
     648             :                        const nsRuleData* aRuleData,
     649             :                        mozilla::GeckoStyleContext* aContext, nsRuleNode* aHighestNode,
     650             :                        RuleDetail aRuleDetail,
     651             :                        const mozilla::RuleNodeCacheConditions aConditions);
     652             : 
     653             :   const void*
     654             :     ComputeOutlineData(void* aStartStruct,
     655             :                        const nsRuleData* aRuleData,
     656             :                        mozilla::GeckoStyleContext* aContext, nsRuleNode* aHighestNode,
     657             :                        RuleDetail aRuleDetail,
     658             :                        const mozilla::RuleNodeCacheConditions aConditions);
     659             : 
     660             :   const void*
     661             :     ComputeListData(void* aStartStruct,
     662             :                     const nsRuleData* aRuleData,
     663             :                     mozilla::GeckoStyleContext* aContext, nsRuleNode* aHighestNode,
     664             :                     RuleDetail aRuleDetail,
     665             :                     const mozilla::RuleNodeCacheConditions aConditions);
     666             : 
     667             :   const void*
     668             :     ComputePositionData(void* aStartStruct,
     669             :                         const nsRuleData* aRuleData,
     670             :                         mozilla::GeckoStyleContext* aContext, nsRuleNode* aHighestNode,
     671             :                         RuleDetail aRuleDetail,
     672             :                         const mozilla::RuleNodeCacheConditions aConditions);
     673             : 
     674             :   const void*
     675             :     ComputeTableData(void* aStartStruct,
     676             :                      const nsRuleData* aRuleData,
     677             :                      mozilla::GeckoStyleContext* aContext, nsRuleNode* aHighestNode,
     678             :                      RuleDetail aRuleDetail,
     679             :                      const mozilla::RuleNodeCacheConditions aConditions);
     680             : 
     681             :   const void*
     682             :     ComputeTableBorderData(void* aStartStruct,
     683             :                            const nsRuleData* aRuleData,
     684             :                            mozilla::GeckoStyleContext* aContext, nsRuleNode* aHighestNode,
     685             :                            RuleDetail aRuleDetail,
     686             :                            const mozilla::RuleNodeCacheConditions aConditions);
     687             : 
     688             :   const void*
     689             :     ComputeContentData(void* aStartStruct,
     690             :                        const nsRuleData* aRuleData,
     691             :                        mozilla::GeckoStyleContext* aContext, nsRuleNode* aHighestNode,
     692             :                        RuleDetail aRuleDetail,
     693             :                        const mozilla::RuleNodeCacheConditions aConditions);
     694             : 
     695             :   const void*
     696             :     ComputeTextData(void* aStartStruct,
     697             :                     const nsRuleData* aRuleData,
     698             :                     mozilla::GeckoStyleContext* aContext, nsRuleNode* aHighestNode,
     699             :                     RuleDetail aRuleDetail,
     700             :                     const mozilla::RuleNodeCacheConditions aConditions);
     701             : 
     702             :   const void*
     703             :     ComputeTextResetData(void* aStartStruct,
     704             :                          const nsRuleData* aRuleData,
     705             :                          mozilla::GeckoStyleContext* aContext, nsRuleNode* aHighestNode,
     706             :                          RuleDetail aRuleDetail,
     707             :                          const mozilla::RuleNodeCacheConditions aConditions);
     708             : 
     709             :   const void*
     710             :     ComputeUserInterfaceData(void* aStartStruct,
     711             :                              const nsRuleData* aRuleData,
     712             :                              mozilla::GeckoStyleContext* aContext,
     713             :                              nsRuleNode* aHighestNode,
     714             :                              RuleDetail aRuleDetail,
     715             :                              const mozilla::RuleNodeCacheConditions aConditions);
     716             : 
     717             :   const void*
     718             :     ComputeUIResetData(void* aStartStruct,
     719             :                        const nsRuleData* aRuleData,
     720             :                        mozilla::GeckoStyleContext* aContext, nsRuleNode* aHighestNode,
     721             :                        RuleDetail aRuleDetail,
     722             :                        const mozilla::RuleNodeCacheConditions aConditions);
     723             : 
     724             :   const void*
     725             :     ComputeXULData(void* aStartStruct,
     726             :                    const nsRuleData* aRuleData,
     727             :                    mozilla::GeckoStyleContext* aContext, nsRuleNode* aHighestNode,
     728             :                    RuleDetail aRuleDetail,
     729             :                    const mozilla::RuleNodeCacheConditions aConditions);
     730             : 
     731             :   const void*
     732             :     ComputeColumnData(void* aStartStruct,
     733             :                       const nsRuleData* aRuleData,
     734             :                       mozilla::GeckoStyleContext* aContext, nsRuleNode* aHighestNode,
     735             :                       RuleDetail aRuleDetail,
     736             :                       const mozilla::RuleNodeCacheConditions aConditions);
     737             : 
     738             :   const void*
     739             :     ComputeSVGData(void* aStartStruct,
     740             :                    const nsRuleData* aRuleData,
     741             :                    mozilla::GeckoStyleContext* aContext, nsRuleNode* aHighestNode,
     742             :                    RuleDetail aRuleDetail,
     743             :                    const mozilla::RuleNodeCacheConditions aConditions);
     744             : 
     745             :   const void*
     746             :     ComputeSVGResetData(void* aStartStruct,
     747             :                         const nsRuleData* aRuleData,
     748             :                         mozilla::GeckoStyleContext* aContext, nsRuleNode* aHighestNode,
     749             :                         RuleDetail aRuleDetail,
     750             :                         const mozilla::RuleNodeCacheConditions aConditions);
     751             : 
     752             :   const void*
     753             :     ComputeVariablesData(void* aStartStruct,
     754             :                          const nsRuleData* aRuleData,
     755             :                          mozilla::GeckoStyleContext* aContext, nsRuleNode* aHighestNode,
     756             :                          RuleDetail aRuleDetail,
     757             :                          const mozilla::RuleNodeCacheConditions aConditions);
     758             : 
     759             :   const void*
     760             :     ComputeEffectsData(void* aStartStruct,
     761             :                        const nsRuleData* aRuleData,
     762             :                        mozilla::GeckoStyleContext* aContext, nsRuleNode* aHighestNode,
     763             :                        RuleDetail aRuleDetail,
     764             :                        const mozilla::RuleNodeCacheConditions aConditions);
     765             : 
     766             :   // helpers for |ComputeFontData| that need access to |mNoneBits|:
     767             :   static void SetFontSize(nsPresContext* aPresContext,
     768             :                           mozilla::GeckoStyleContext* aContext,
     769             :                           const nsRuleData* aRuleData,
     770             :                           const nsStyleFont* aFont,
     771             :                           const nsStyleFont* aParentFont,
     772             :                           nscoord* aSize,
     773             :                           const nsFont& aSystemFont,
     774             :                           nscoord aParentSize,
     775             :                           nscoord aScriptLevelAdjustedParentSize,
     776             :                           bool aUsedStartStruct,
     777             :                           bool aAtRoot,
     778             :                           mozilla::RuleNodeCacheConditions& aConditions);
     779             : 
     780             :   static void SetFont(nsPresContext* aPresContext,
     781             :                       mozilla::GeckoStyleContext* aContext,
     782             :                       uint8_t aGenericFontID,
     783             :                       const nsRuleData* aRuleData,
     784             :                       const nsStyleFont* aParentFont,
     785             :                       nsStyleFont* aFont,
     786             :                       bool aStartStruct,
     787             :                       mozilla::RuleNodeCacheConditions& aConditions);
     788             : 
     789             :   static void SetGenericFont(nsPresContext* aPresContext,
     790             :                              mozilla::GeckoStyleContext* aContext,
     791             :                              uint8_t aGenericFontID,
     792             :                              nsStyleFont* aFont);
     793             : 
     794             :   inline RuleDetail CheckSpecifiedProperties(const nsStyleStructID aSID,
     795             :                                              const nsRuleData* aRuleData);
     796             : 
     797             : private:
     798             :   nsRuleNode(nsPresContext* aPresContext, nsRuleNode* aParent,
     799             :              nsIStyleRule* aRule, mozilla::SheetType aLevel, bool aIsImportant);
     800             :   ~nsRuleNode();
     801             : 
     802             : public:
     803             :   // This is infallible; it will never return nullptr.
     804             :   static already_AddRefed<nsRuleNode> CreateRootNode(nsPresContext* aPresContext);
     805             : 
     806             :   static void EnsureBlockDisplay(mozilla::StyleDisplay& display,
     807             :                                  bool aConvertListItem = false);
     808             :   static void EnsureInlineDisplay(mozilla::StyleDisplay& display);
     809             : 
     810             :   static already_AddRefed<nsFontMetrics> GetMetricsFor(nsPresContext* aPresContext,
     811             :                                                        bool aIsVertical,
     812             :                                                        const nsStyleFont* aStyleFont,
     813             :                                                        nscoord aFontSize,
     814             :                                                        bool aUseUserFontSet);
     815             : 
     816             :   static already_AddRefed<nsFontMetrics> GetMetricsFor(nsPresContext* aPresContext,
     817             :                                                        nsStyleContext* aStyleContext,
     818             :                                                        const nsStyleFont* aStyleFont,
     819             :                                                        nscoord aFontSize,
     820             :                                                        bool aUseUserFontSet);
     821             : 
     822             :   /**
     823             :    * Appropriately add the correct font if we are using DocumentFonts or
     824             :    * overriding for XUL
     825             :    */
     826             :   static void FixupNoneGeneric(nsFont* aFont,
     827             :                                const nsPresContext* aPresContext,
     828             :                                uint8_t aGenericFontID,
     829             :                                const nsFont* aDefaultVariableFont);
     830             : 
     831             :   /**
     832             :    * For an nsStyleFont with mSize set, apply minimum font size constraints
     833             :    * from preferences, as well as -moz-min-font-size-ratio.
     834             :    */
     835             :   static void ApplyMinFontSize(nsStyleFont* aFont,
     836             :                                const nsPresContext* aPresContext,
     837             :                                nscoord aMinFontSize);
     838             : 
     839             :   // Transition never returns null; on out of memory it'll just return |this|.
     840             :   nsRuleNode* Transition(nsIStyleRule* aRule, mozilla::SheetType aLevel,
     841             :                          bool aIsImportantRule);
     842       52486 :   nsRuleNode* GetParent() const { return mParent; }
     843      184771 :   bool IsRoot() const { return mParent == nullptr; }
     844             : 
     845             :   // Return the root of the rule tree that this rule node is in.
     846             :   nsRuleNode* RuleTree();
     847             :   const nsRuleNode* RuleTree() const {
     848             :     return const_cast<nsRuleNode*>(this)->RuleTree();
     849             :   }
     850             : 
     851       82489 :   mozilla::SheetType GetLevel() const {
     852       82489 :     NS_ASSERTION(!IsRoot(), "can't call on root");
     853             :     return mozilla::SheetType(
     854       82489 :         (mDependentBits & NS_RULE_NODE_LEVEL_MASK) >>
     855       82489 :           NS_RULE_NODE_LEVEL_SHIFT);
     856             :   }
     857       77616 :   bool IsImportantRule() const {
     858       77616 :     NS_ASSERTION(!IsRoot(), "can't call on root");
     859       77616 :     return (mDependentBits & NS_RULE_NODE_IS_IMPORTANT) != 0;
     860             :   }
     861             : 
     862             :   /**
     863             :    * Has this rule node at some time in its lifetime been the mRuleNode
     864             :    * of some style context (as opposed to only being the ancestor of
     865             :    * some style context's mRuleNode)?
     866             :    */
     867             :   void SetUsedDirectly();
     868      320144 :   bool IsUsedDirectly() const {
     869      320144 :     return (mDependentBits & NS_RULE_NODE_USED_DIRECTLY) != 0;
     870             :   }
     871             : 
     872             :   /**
     873             :    * Is the mRule of this rule node an AnimValuesStyleRule?
     874             :    */
     875          14 :   void SetIsAnimationRule() {
     876          14 :     MOZ_ASSERT(!HaveChildren() ||
     877             :                (mDependentBits & NS_RULE_NODE_IS_ANIMATION_RULE),
     878             :                "SetIsAnimationRule must only set the IS_ANIMATION_RULE bit "
     879             :                "before the rule node has children");
     880          14 :     mDependentBits |= NS_RULE_NODE_IS_ANIMATION_RULE;
     881          14 :     mNoneBits |= NS_RULE_NODE_HAS_ANIMATION_DATA;
     882          14 :   }
     883         118 :   bool IsAnimationRule() const {
     884         118 :     return (mDependentBits & NS_RULE_NODE_IS_ANIMATION_RULE) != 0;
     885             :   }
     886             : 
     887             :   /**
     888             :    * Is the mRule of this rule node or any of its ancestors an
     889             :    * AnimValuesStyleRule?
     890             :    */
     891      559928 :   bool HasAnimationData() const {
     892      559928 :     return (mNoneBits & NS_RULE_NODE_HAS_ANIMATION_DATA) != 0;
     893             :   }
     894             : 
     895             :   // NOTE:  Does not |AddRef|.  Null only for the root.
     896       12923 :   nsIStyleRule* GetRule() const { return mRule; }
     897             :   // NOTE: Does not |AddRef|.  Never null.
     898       95492 :   nsPresContext* PresContext() const { return mPresContext; }
     899             : 
     900             :   const void* GetStyleData(nsStyleStructID aSID,
     901             :                            mozilla::GeckoStyleContext* aContext,
     902             :                            bool aComputeData);
     903             : 
     904             :   void GetDiscretelyAnimatedCSSValue(nsCSSPropertyID aProperty,
     905             :                                      nsCSSValue* aValue);
     906             : 
     907             :   // See comments in GetStyleData for an explanation of what the
     908             :   // code below does.
     909             :   #define STYLE_STRUCT_INHERITED(name_, checkdata_cb_)                        \
     910             :   template<bool aComputeData>                                                 \
     911             :   const nsStyle##name_*                                                       \
     912             :   GetStyle##name_(mozilla::GeckoStyleContext* aContext, uint64_t& aContextStyleBits)      \
     913             :   {                                                                           \
     914             :     NS_ASSERTION(IsUsedDirectly(),                                            \
     915             :                  "if we ever call this on rule nodes that aren't used "       \
     916             :                  "directly, we should adjust handling of mDependentBits "     \
     917             :                  "in some way.");                                             \
     918             :     MOZ_ASSERT(!ContextHasCachedData(aContext, eStyleStruct_##name_),         \
     919             :                "style context should not have cached data for struct");       \
     920             :                                                                               \
     921             :     const nsStyle##name_ *data;                                               \
     922             :                                                                               \
     923             :     /* Never use cached data for animated style inside a pseudo-element; */   \
     924             :     /* see comment on cacheability in AnimValuesStyleRule::MapRuleInfoInto */ \
     925             :     if (!(HasAnimationData() && ParentHasPseudoElementData(aContext))) {      \
     926             :       data = mStyleData.GetStyle##name_();                                    \
     927             :       if (data != nullptr) {                                                  \
     928             :         /* For inherited structs, mark the struct (which will be set on */    \
     929             :         /* the context by our caller) as not being owned by the context. */   \
     930             :         /* Normally this would be aContext->AddStyleBit(), but aContext is */ \
     931             :         /* an incomplete type here, so we work around that with a param. */   \
     932             :         aContextStyleBits |= NS_STYLE_INHERIT_BIT(name_);                     \
     933             :         /* Our caller will cache the data on the style context. */            \
     934             :         return data;                                                          \
     935             :       }                                                                       \
     936             :     }                                                                         \
     937             :                                                                               \
     938             :     if (!aComputeData)                                                        \
     939             :       return nullptr;                                                         \
     940             :                                                                               \
     941             :     data = static_cast<const nsStyle##name_ *>                                \
     942             :              (WalkRuleTree(eStyleStruct_##name_, aContext));                  \
     943             :                                                                               \
     944             :     MOZ_ASSERT(data, "should have aborted on out-of-memory");                 \
     945             :     return data;                                                              \
     946             :   }
     947             : 
     948             :   #define STYLE_STRUCT_RESET(name_, checkdata_cb_)                            \
     949             :   template<bool aComputeData>                                                 \
     950             :   const nsStyle##name_*                                                       \
     951             :   GetStyle##name_(mozilla::GeckoStyleContext* aContext)                                   \
     952             :   {                                                                           \
     953             :     NS_ASSERTION(IsUsedDirectly(),                                            \
     954             :                  "if we ever call this on rule nodes that aren't used "       \
     955             :                  "directly, we should adjust handling of mDependentBits "     \
     956             :                  "in some way.");                                             \
     957             :     MOZ_ASSERT(!ContextHasCachedData(aContext, eStyleStruct_##name_),         \
     958             :                "style context should not have cached data for struct");       \
     959             :                                                                               \
     960             :     const nsStyle##name_ *data;                                               \
     961             :                                                                               \
     962             :     /* Never use cached data for animated style inside a pseudo-element; */   \
     963             :     /* see comment on cacheability in AnimValuesStyleRule::MapRuleInfoInto */ \
     964             :     if (!(HasAnimationData() && ParentHasPseudoElementData(aContext))) {      \
     965             :       data = mStyleData.GetStyle##name_(aContext, aComputeData);              \
     966             :       if (MOZ_LIKELY(data != nullptr)) {                                      \
     967             :         if (HasAnimationData()) {                                             \
     968             :           /* If we have animation data, the struct should be cached on the */ \
     969             :           /* style context so that we can peek the struct. */                 \
     970             :           /* See comment in AnimValuesStyleRule::MapRuleInfoInto. */          \
     971             :           StoreStyleOnContext(aContext,                                       \
     972             :                               eStyleStruct_##name_,                           \
     973             :                               const_cast<nsStyle##name_*>(data));             \
     974             :         }                                                                     \
     975             :         return data;                                                          \
     976             :       }                                                                       \
     977             :     }                                                                         \
     978             :                                                                               \
     979             :     if (!aComputeData)                                                        \
     980             :       return nullptr;                                                         \
     981             :                                                                               \
     982             :     data = static_cast<const nsStyle##name_ *>                                \
     983             :              (WalkRuleTree(eStyleStruct_##name_, aContext));                  \
     984             :                                                                               \
     985             :     MOZ_ASSERT(data, "should have aborted on out-of-memory");                 \
     986             :     return data;                                                              \
     987             :   }
     988             : 
     989             :   #include "nsStyleStructList.h"
     990             : 
     991             :   #undef STYLE_STRUCT_RESET
     992             :   #undef STYLE_STRUCT_INHERITED
     993             : 
     994             :   static bool
     995             :     HasAuthorSpecifiedRules(nsStyleContext* aStyleContext,
     996             :                             uint32_t ruleTypeMask,
     997             :                             bool aAuthorColorsAllowed);
     998             : 
     999             :   /**
    1000             :    * Fill in to aPropertiesOverridden all of the properties in aProperties
    1001             :    * that, for this rule node, have a declaration that is higher than the
    1002             :    * animation level in the CSS Cascade.
    1003             :    */
    1004             :   static void
    1005             :   ComputePropertiesOverridingAnimation(
    1006             :                               const nsTArray<nsCSSPropertyID>& aProperties,
    1007             :                               mozilla::GeckoStyleContext* aStyleContext,
    1008             :                               nsCSSPropertyIDSet& aPropertiesOverridden);
    1009             : 
    1010             :   // Expose this so media queries can use it
    1011             :   static nscoord CalcLengthWithInitialFont(nsPresContext* aPresContext,
    1012             :                                            const nsCSSValue& aValue);
    1013             :   // Expose this so nsTransformFunctions can use it.
    1014             :   static nscoord CalcLength(const nsCSSValue& aValue,
    1015             :                             nsStyleContext* aStyleContext,
    1016             :                             nsPresContext* aPresContext,
    1017             :                             mozilla::RuleNodeCacheConditions& aConditions);
    1018             : 
    1019             :   struct ComputedCalc {
    1020             :     nscoord mLength;
    1021             :     float mPercent;
    1022             : 
    1023         414 :     ComputedCalc(nscoord aLength, float aPercent)
    1024         414 :       : mLength(aLength), mPercent(aPercent) {}
    1025             :   };
    1026             :   static ComputedCalc
    1027             :   SpecifiedCalcToComputedCalc(const nsCSSValue& aValue,
    1028             :                               nsStyleContext* aStyleContext,
    1029             :                               nsPresContext* aPresContext,
    1030             :                               mozilla::RuleNodeCacheConditions& aConditions);
    1031             : 
    1032             :   // Compute the value of an nsStyleCoord that IsCalcUnit().
    1033             :   // (Values that don't require aPercentageBasis should be handled
    1034             :   // inside nsRuleNode rather than through this API.)
    1035             :   // @note the caller is expected to handle percentage of an indefinite size
    1036             :   // and NOT call this method with aPercentageBasis == NS_UNCONSTRAINEDSIZE.
    1037             :   // @note the return value may be negative, e.g. for "calc(a - b%)"
    1038             :   static nscoord ComputeComputedCalc(const nsStyleCoord& aCoord,
    1039             :                                      nscoord aPercentageBasis);
    1040             : 
    1041             :   // Compute the value of an nsStyleCoord that is either a coord, a
    1042             :   // percent, or a calc expression.
    1043             :   // @note the caller is expected to handle percentage of an indefinite size
    1044             :   // and NOT call this method with aPercentageBasis == NS_UNCONSTRAINEDSIZE.
    1045             :   // @note the return value may be negative, e.g. for "calc(a - b%)"
    1046             :   static nscoord ComputeCoordPercentCalc(const nsStyleCoord& aCoord,
    1047             :                                          nscoord aPercentageBasis);
    1048             : 
    1049             :   // Return whether the rule tree for which this node is the root has
    1050             :   // cached data such that we need to do dynamic change handling for
    1051             :   // changes that change the results of media queries or require
    1052             :   // rebuilding all style data.
    1053          61 :   bool TreeHasCachedData() const {
    1054          61 :     NS_ASSERTION(IsRoot(), "should only be called on root of rule tree");
    1055          61 :     return HaveChildren() || mStyleData.mInheritedData || mStyleData.mResetData;
    1056             :   }
    1057             : 
    1058             :   // Note that this will return false if we have cached conditional
    1059             :   // style structs.
    1060           0 :   bool NodeHasCachedUnconditionalData(const nsStyleStructID aSID) {
    1061           0 :     return !!mStyleData.GetStyleData(aSID);
    1062             :   }
    1063             : 
    1064             :   static void ComputeFontFeatures(const nsCSSValuePairList* aFeaturesList,
    1065             :                                   nsTArray<gfxFontFeature>& aFeatureSettings);
    1066             : 
    1067             :   static void ComputeFontVariations(const nsCSSValuePairList* aVariationsList,
    1068             :                                     nsTArray<gfxFontVariation>& aVariationSettings);
    1069             : 
    1070             :   static nscoord CalcFontPointSize(int32_t aHTMLSize, int32_t aBasePointSize,
    1071             :                                    nsPresContext* aPresContext,
    1072             :                                    nsFontSizeType aFontSizeType = eFontSize_HTML);
    1073             : 
    1074             :   static nscoord FindNextSmallerFontSize(nscoord aFontSize, int32_t aBasePointSize,
    1075             :                                          nsPresContext* aPresContext,
    1076             :                                          nsFontSizeType aFontSizeType = eFontSize_HTML);
    1077             : 
    1078             :   static nscoord FindNextLargerFontSize(nscoord aFontSize, int32_t aBasePointSize,
    1079             :                                         nsPresContext* aPresContext,
    1080             :                                         nsFontSizeType aFontSizeType = eFontSize_HTML);
    1081             : 
    1082             :   static uint32_t ParseFontLanguageOverride(const nsAString& aLangTag);
    1083             : 
    1084             :   /**
    1085             :    * @param aValue The color value, returned from nsCSSParser::ParseColorString
    1086             :    * @param aPresContext Presentation context whose preferences are used
    1087             :    *                     for certain enumerated colors
    1088             :    * @param aStyleContext Style context whose color is used for 'currentColor'
    1089             :    *
    1090             :    * @note aPresContext and aStyleContext may be null, but in that case, fully
    1091             :    *       opaque black will be returned for the values that rely on these
    1092             :    *       objects to compute the color. (For example, -moz-hyperlinktext.)
    1093             :    *
    1094             :    * @return false if we fail to extract a color; this will not happen if both
    1095             :    *         aPresContext and aStyleContext are non-null
    1096             :    */
    1097             :   static bool ComputeColor(const nsCSSValue& aValue,
    1098             :                            nsPresContext* aPresContext,
    1099             :                            nsStyleContext* aStyleContext,
    1100             :                            nscolor& aResult);
    1101             : 
    1102             :   static bool ParentHasPseudoElementData(mozilla::GeckoStyleContext* aContext);
    1103             : 
    1104             :   static void ComputeTimingFunction(const nsCSSValue& aValue,
    1105             :                                     nsTimingFunction& aResult);
    1106             : 
    1107             :   // Fill unspecified layers by cycling through their values
    1108             :   // till they all are of length aMaxItemCount
    1109             :   static void FillAllBackgroundLists(nsStyleImageLayers& aLayers,
    1110             :                                      uint32_t aMaxItemCount);
    1111             : 
    1112             :   static void FillAllMaskLists(nsStyleImageLayers& aLayers,
    1113             :                                uint32_t aMaxItemCount);
    1114             : 
    1115             :   static void ComputeSystemFont(nsFont* aSystemFont,
    1116             :                                 mozilla::LookAndFeel::FontID aFontID,
    1117             :                                 const nsPresContext* aPresContext,
    1118             :                                 const nsFont* aDefaultVariableFont);
    1119             : 
    1120             : private:
    1121             : #ifdef DEBUG
    1122             :   // non-inline helper function to allow assertions without incomplete
    1123             :   // type errors
    1124             :   bool ContextHasCachedData(mozilla::GeckoStyleContext* aContext, nsStyleStructID aSID);
    1125             : #endif
    1126             : 
    1127             :   // Store style struct on the style context and tell the style context
    1128             :   // that it doesn't own the data
    1129             :   static void StoreStyleOnContext(mozilla::GeckoStyleContext* aContext,
    1130             :                                   nsStyleStructID aSID,
    1131             :                                   void* aStruct);
    1132             : };
    1133             : 
    1134             : /**
    1135             :  * We allocate arrays of CSS values with alloca.  (These arrays are a
    1136             :  * fixed size per style struct, but we don't want to waste the
    1137             :  * allocation and construction/destruction costs of the big structs when
    1138             :  * we're handling much smaller ones.)  Since the lifetime of an alloca
    1139             :  * allocation is the life of the calling function, the caller must call
    1140             :  * alloca.  However, to ensure that constructors and destructors are
    1141             :  * balanced, we do the constructor and destructor calling from this RAII
    1142             :  * class, AutoCSSValueArray.
    1143             :  */
    1144             : struct AutoCSSValueArray
    1145             : {
    1146             :   /**
    1147             :    * aStorage must be the result of alloca(aCount * sizeof(nsCSSValue))
    1148             :    */
    1149             :   AutoCSSValueArray(void* aStorage, size_t aCount);
    1150             : 
    1151             :   ~AutoCSSValueArray();
    1152             : 
    1153       11858 :   nsCSSValue* get() { return mArray; }
    1154             : 
    1155             : private:
    1156             :   nsCSSValue *mArray;
    1157             :   size_t mCount;
    1158             : };
    1159             : 
    1160             : #endif

Generated by: LCOV version 1.13