|
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 * the container for the style sheets that apply to a presentation, and |
|
8 * the internal API that the style system exposes for creating (and |
|
9 * potentially re-creating) style contexts |
|
10 */ |
|
11 |
|
12 #ifndef nsStyleSet_h_ |
|
13 #define nsStyleSet_h_ |
|
14 |
|
15 #include "mozilla/Attributes.h" |
|
16 #include "mozilla/MemoryReporting.h" |
|
17 |
|
18 #include "nsIStyleRuleProcessor.h" |
|
19 #include "nsCSSStyleSheet.h" |
|
20 #include "nsBindingManager.h" |
|
21 #include "nsRuleNode.h" |
|
22 #include "nsTArray.h" |
|
23 #include "nsCOMArray.h" |
|
24 #include "nsAutoPtr.h" |
|
25 #include "nsIStyleRule.h" |
|
26 #include "nsCSSPseudoElements.h" |
|
27 #include "gfxFontFeatures.h" |
|
28 |
|
29 class nsCSSFontFaceRule; |
|
30 class nsCSSKeyframesRule; |
|
31 class nsCSSFontFeatureValuesRule; |
|
32 class nsCSSPageRule; |
|
33 class nsRuleWalker; |
|
34 struct ElementDependentRuleProcessorData; |
|
35 struct TreeMatchContext; |
|
36 |
|
37 namespace mozilla { |
|
38 class EventStates; |
|
39 } // namespace mozilla |
|
40 |
|
41 class nsEmptyStyleRule MOZ_FINAL : public nsIStyleRule |
|
42 { |
|
43 NS_DECL_ISUPPORTS |
|
44 virtual void MapRuleInfoInto(nsRuleData* aRuleData) MOZ_OVERRIDE; |
|
45 #ifdef DEBUG |
|
46 virtual void List(FILE* out = stdout, int32_t aIndent = 0) const MOZ_OVERRIDE; |
|
47 #endif |
|
48 }; |
|
49 |
|
50 class nsInitialStyleRule MOZ_FINAL : public nsIStyleRule |
|
51 { |
|
52 NS_DECL_ISUPPORTS |
|
53 virtual void MapRuleInfoInto(nsRuleData* aRuleData) MOZ_OVERRIDE; |
|
54 #ifdef DEBUG |
|
55 virtual void List(FILE* out = stdout, int32_t aIndent = 0) const MOZ_OVERRIDE; |
|
56 #endif |
|
57 }; |
|
58 |
|
59 class nsDisableTextZoomStyleRule MOZ_FINAL : public nsIStyleRule |
|
60 { |
|
61 NS_DECL_ISUPPORTS |
|
62 virtual void MapRuleInfoInto(nsRuleData* aRuleData) MOZ_OVERRIDE; |
|
63 #ifdef DEBUG |
|
64 virtual void List(FILE* out = stdout, int32_t aIndent = 0) const MOZ_OVERRIDE; |
|
65 #endif |
|
66 }; |
|
67 |
|
68 // The style set object is created by the document viewer and ownership is |
|
69 // then handed off to the PresShell. Only the PresShell should delete a |
|
70 // style set. |
|
71 |
|
72 class nsStyleSet |
|
73 { |
|
74 public: |
|
75 nsStyleSet(); |
|
76 |
|
77 size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; |
|
78 |
|
79 void Init(nsPresContext *aPresContext); |
|
80 |
|
81 nsRuleNode* GetRuleTree() { return mRuleTree; } |
|
82 |
|
83 // enable / disable the Quirk style sheet |
|
84 void EnableQuirkStyleSheet(bool aEnable); |
|
85 |
|
86 // get a style context for a non-pseudo frame. |
|
87 already_AddRefed<nsStyleContext> |
|
88 ResolveStyleFor(mozilla::dom::Element* aElement, |
|
89 nsStyleContext* aParentContext); |
|
90 |
|
91 already_AddRefed<nsStyleContext> |
|
92 ResolveStyleFor(mozilla::dom::Element* aElement, |
|
93 nsStyleContext* aParentContext, |
|
94 TreeMatchContext& aTreeMatchContext); |
|
95 |
|
96 // Get a style context (with the given parent) for the |
|
97 // sequence of style rules in the |aRules| array. |
|
98 already_AddRefed<nsStyleContext> |
|
99 ResolveStyleForRules(nsStyleContext* aParentContext, |
|
100 const nsTArray< nsCOMPtr<nsIStyleRule> > &aRules); |
|
101 |
|
102 // used in ResolveStyleForRules below |
|
103 struct RuleAndLevel |
|
104 { |
|
105 nsIStyleRule* mRule; |
|
106 uint8_t mLevel; |
|
107 }; |
|
108 |
|
109 // Get a new style context for aElement for the rules in aRules |
|
110 // aRules is an array of rules and their levels in reverse order, |
|
111 // that is from the leaf-most to the root-most rule in the rule tree. |
|
112 already_AddRefed<nsStyleContext> |
|
113 ResolveStyleForRules(nsStyleContext* aParentContext, |
|
114 nsStyleContext* aOldStyle, |
|
115 const nsTArray<RuleAndLevel>& aRules); |
|
116 |
|
117 // Get a style context that represents aBaseContext, but as though |
|
118 // it additionally matched the rules in the aRules array (in that |
|
119 // order, as more specific than any other rules). |
|
120 already_AddRefed<nsStyleContext> |
|
121 ResolveStyleByAddingRules(nsStyleContext* aBaseContext, |
|
122 const nsCOMArray<nsIStyleRule> &aRules); |
|
123 |
|
124 // Get a style context for a non-element (which no rules will match), |
|
125 // such as text nodes, placeholder frames, and the nsFirstLetterFrame |
|
126 // for everything after the first letter. |
|
127 // |
|
128 // Perhaps this should go away and we shouldn't even create style |
|
129 // contexts for such content nodes. However, not doing any rule |
|
130 // matching for them is a first step. |
|
131 already_AddRefed<nsStyleContext> |
|
132 ResolveStyleForNonElement(nsStyleContext* aParentContext); |
|
133 |
|
134 // Get a style context for a pseudo-element. aParentElement must be |
|
135 // non-null. aPseudoID is the nsCSSPseudoElements::Type for the |
|
136 // pseudo-element. aPseudoElement must be non-null if the pseudo-element |
|
137 // type is one that allows user action pseudo-classes after it; otherwise, |
|
138 // it is ignored. |
|
139 already_AddRefed<nsStyleContext> |
|
140 ResolvePseudoElementStyle(mozilla::dom::Element* aParentElement, |
|
141 nsCSSPseudoElements::Type aType, |
|
142 nsStyleContext* aParentContext, |
|
143 mozilla::dom::Element* aPseudoElement); |
|
144 |
|
145 // This functions just like ResolvePseudoElementStyle except that it will |
|
146 // return nullptr if there are no explicit style rules for that |
|
147 // pseudo element. |
|
148 already_AddRefed<nsStyleContext> |
|
149 ProbePseudoElementStyle(mozilla::dom::Element* aParentElement, |
|
150 nsCSSPseudoElements::Type aType, |
|
151 nsStyleContext* aParentContext); |
|
152 already_AddRefed<nsStyleContext> |
|
153 ProbePseudoElementStyle(mozilla::dom::Element* aParentElement, |
|
154 nsCSSPseudoElements::Type aType, |
|
155 nsStyleContext* aParentContext, |
|
156 TreeMatchContext& aTreeMatchContext, |
|
157 mozilla::dom::Element* aPseudoElement = nullptr); |
|
158 |
|
159 // Get a style context for an anonymous box. aPseudoTag is the |
|
160 // pseudo-tag to use and must be non-null. |
|
161 already_AddRefed<nsStyleContext> |
|
162 ResolveAnonymousBoxStyle(nsIAtom* aPseudoTag, nsStyleContext* aParentContext); |
|
163 |
|
164 #ifdef MOZ_XUL |
|
165 // Get a style context for a XUL tree pseudo. aPseudoTag is the |
|
166 // pseudo-tag to use and must be non-null. aParentContent must be |
|
167 // non-null. aComparator must be non-null. |
|
168 already_AddRefed<nsStyleContext> |
|
169 ResolveXULTreePseudoStyle(mozilla::dom::Element* aParentElement, |
|
170 nsIAtom* aPseudoTag, |
|
171 nsStyleContext* aParentContext, |
|
172 nsICSSPseudoComparator* aComparator); |
|
173 #endif |
|
174 |
|
175 // Append all the currently-active font face rules to aArray. Return |
|
176 // true for success and false for failure. |
|
177 bool AppendFontFaceRules(nsPresContext* aPresContext, |
|
178 nsTArray<nsFontFaceRuleContainer>& aArray); |
|
179 |
|
180 // Return the winning (in the cascade) @keyframes rule for the given name. |
|
181 nsCSSKeyframesRule* KeyframesRuleForName(nsPresContext* aPresContext, |
|
182 const nsString& aName); |
|
183 |
|
184 // Fetch object for looking up font feature values |
|
185 already_AddRefed<gfxFontFeatureValueSet> GetFontFeatureValuesLookup(); |
|
186 |
|
187 // Append all the currently-active font feature values rules to aArray. |
|
188 // Return true for success and false for failure. |
|
189 bool AppendFontFeatureValuesRules(nsPresContext* aPresContext, |
|
190 nsTArray<nsCSSFontFeatureValuesRule*>& aArray); |
|
191 |
|
192 // Append all the currently-active page rules to aArray. Return |
|
193 // true for success and false for failure. |
|
194 bool AppendPageRules(nsPresContext* aPresContext, |
|
195 nsTArray<nsCSSPageRule*>& aArray); |
|
196 |
|
197 // Begin ignoring style context destruction, to avoid lots of unnecessary |
|
198 // work on document teardown. |
|
199 void BeginShutdown(nsPresContext* aPresContext); |
|
200 |
|
201 // Free all of the data associated with this style set. |
|
202 void Shutdown(nsPresContext* aPresContext); |
|
203 |
|
204 // Notification that a style context is being destroyed. |
|
205 void NotifyStyleContextDestroyed(nsPresContext* aPresContext, |
|
206 nsStyleContext* aStyleContext); |
|
207 |
|
208 // Get a new style context that lives in a different parent |
|
209 // The new context will be the same as the old if the new parent is the |
|
210 // same as the old parent. |
|
211 // aElement should be non-null if this is a style context for an |
|
212 // element or pseudo-element; in the latter case it should be the |
|
213 // real element the pseudo-element is for. |
|
214 already_AddRefed<nsStyleContext> |
|
215 ReparentStyleContext(nsStyleContext* aStyleContext, |
|
216 nsStyleContext* aNewParentContext, |
|
217 mozilla::dom::Element* aElement); |
|
218 |
|
219 // Test if style is dependent on a document state. |
|
220 bool HasDocumentStateDependentStyle(nsPresContext* aPresContext, |
|
221 nsIContent* aContent, |
|
222 mozilla::EventStates aStateMask); |
|
223 |
|
224 // Test if style is dependent on content state |
|
225 nsRestyleHint HasStateDependentStyle(nsPresContext* aPresContext, |
|
226 mozilla::dom::Element* aElement, |
|
227 mozilla::EventStates aStateMask); |
|
228 nsRestyleHint HasStateDependentStyle(nsPresContext* aPresContext, |
|
229 mozilla::dom::Element* aElement, |
|
230 nsCSSPseudoElements::Type aPseudoType, |
|
231 mozilla::dom::Element* aPseudoElement, |
|
232 mozilla::EventStates aStateMask); |
|
233 |
|
234 // Test if style is dependent on the presence of an attribute. |
|
235 nsRestyleHint HasAttributeDependentStyle(nsPresContext* aPresContext, |
|
236 mozilla::dom::Element* aElement, |
|
237 nsIAtom* aAttribute, |
|
238 int32_t aModType, |
|
239 bool aAttrHasChanged); |
|
240 |
|
241 /* |
|
242 * Do any processing that needs to happen as a result of a change in |
|
243 * the characteristics of the medium, and return whether style rules |
|
244 * may have changed as a result. |
|
245 */ |
|
246 bool MediumFeaturesChanged(nsPresContext* aPresContext); |
|
247 |
|
248 // APIs for registering objects that can supply additional |
|
249 // rules during processing. |
|
250 void SetBindingManager(nsBindingManager* aBindingManager) |
|
251 { |
|
252 mBindingManager = aBindingManager; |
|
253 } |
|
254 |
|
255 // The "origins" of the CSS cascade, from lowest precedence to |
|
256 // highest (for non-!important rules). |
|
257 enum sheetType { |
|
258 eAgentSheet, // CSS |
|
259 eUserSheet, // CSS |
|
260 ePresHintSheet, |
|
261 eDocSheet, // CSS |
|
262 eScopedDocSheet, |
|
263 eStyleAttrSheet, |
|
264 eOverrideSheet, // CSS |
|
265 eAnimationSheet, |
|
266 eTransitionSheet, |
|
267 eSheetTypeCount |
|
268 // be sure to keep the number of bits in |mDirty| below and in |
|
269 // NS_RULE_NODE_LEVEL_MASK updated when changing the number of sheet |
|
270 // types |
|
271 }; |
|
272 |
|
273 // APIs to manipulate the style sheet lists. The sheets in each |
|
274 // list are stored with the most significant sheet last. |
|
275 nsresult AppendStyleSheet(sheetType aType, nsIStyleSheet *aSheet); |
|
276 nsresult PrependStyleSheet(sheetType aType, nsIStyleSheet *aSheet); |
|
277 nsresult RemoveStyleSheet(sheetType aType, nsIStyleSheet *aSheet); |
|
278 nsresult ReplaceSheets(sheetType aType, |
|
279 const nsCOMArray<nsIStyleSheet> &aNewSheets); |
|
280 nsresult InsertStyleSheetBefore(sheetType aType, nsIStyleSheet *aNewSheet, |
|
281 nsIStyleSheet *aReferenceSheet); |
|
282 |
|
283 nsresult DirtyRuleProcessors(sheetType aType); |
|
284 |
|
285 // Enable/Disable entire author style level (Doc, ScopedDoc & PresHint levels) |
|
286 bool GetAuthorStyleDisabled(); |
|
287 nsresult SetAuthorStyleDisabled(bool aStyleDisabled); |
|
288 |
|
289 int32_t SheetCount(sheetType aType) const { |
|
290 return mSheets[aType].Count(); |
|
291 } |
|
292 |
|
293 nsIStyleSheet* StyleSheetAt(sheetType aType, int32_t aIndex) const { |
|
294 return mSheets[aType].ObjectAt(aIndex); |
|
295 } |
|
296 |
|
297 nsresult RemoveDocStyleSheet(nsIStyleSheet* aSheet); |
|
298 nsresult AddDocStyleSheet(nsIStyleSheet* aSheet, nsIDocument* aDocument); |
|
299 |
|
300 void BeginUpdate(); |
|
301 nsresult EndUpdate(); |
|
302 |
|
303 // Methods for reconstructing the tree; BeginReconstruct basically moves the |
|
304 // old rule tree root and style context roots out of the way, |
|
305 // and EndReconstruct destroys the old rule tree when we're done |
|
306 nsresult BeginReconstruct(); |
|
307 // Note: EndReconstruct should not be called if BeginReconstruct fails |
|
308 void EndReconstruct(); |
|
309 |
|
310 // Let the style set know that a particular sheet is the quirks sheet. This |
|
311 // sheet must already have been added to the UA sheets. The pointer must not |
|
312 // be null. This should only be called once for a given style set. |
|
313 void SetQuirkStyleSheet(nsIStyleSheet* aQuirkStyleSheet); |
|
314 |
|
315 // Return whether the rule tree has cached data such that we need to |
|
316 // do dynamic change handling for changes that change the results of |
|
317 // media queries or require rebuilding all style data. |
|
318 // We don't care whether we have cached rule processors or whether |
|
319 // they have cached rule cascades; getting the rule cascades again in |
|
320 // order to do rule matching will get the correct rule cascade. |
|
321 bool HasCachedStyleData() const { |
|
322 return (mRuleTree && mRuleTree->TreeHasCachedData()) || !mRoots.IsEmpty(); |
|
323 } |
|
324 |
|
325 // Notify the style set that a rulenode is no longer in use, or was |
|
326 // just created and is not in use yet. |
|
327 void RuleNodeUnused() { |
|
328 ++mUnusedRuleNodeCount; |
|
329 } |
|
330 |
|
331 // Notify the style set that a rulenode that wasn't in use now is |
|
332 void RuleNodeInUse() { |
|
333 --mUnusedRuleNodeCount; |
|
334 } |
|
335 |
|
336 nsCSSStyleSheet::EnsureUniqueInnerResult EnsureUniqueInnerOnCSSSheets(); |
|
337 |
|
338 nsIStyleRule* InitialStyleRule(); |
|
339 |
|
340 private: |
|
341 nsStyleSet(const nsStyleSet& aCopy) MOZ_DELETE; |
|
342 nsStyleSet& operator=(const nsStyleSet& aCopy) MOZ_DELETE; |
|
343 |
|
344 // Run mark-and-sweep GC on mRuleTree and mOldRuleTrees, based on mRoots. |
|
345 void GCRuleTrees(); |
|
346 |
|
347 // Update the rule processor list after a change to the style sheet list. |
|
348 nsresult GatherRuleProcessors(sheetType aType); |
|
349 |
|
350 void AddImportantRules(nsRuleNode* aCurrLevelNode, |
|
351 nsRuleNode* aLastPrevLevelNode, |
|
352 nsRuleWalker* aRuleWalker); |
|
353 |
|
354 // Move aRuleWalker forward by the appropriate rule if we need to add |
|
355 // a rule due to property restrictions on pseudo-elements. |
|
356 void WalkRestrictionRule(nsCSSPseudoElements::Type aPseudoType, |
|
357 nsRuleWalker* aRuleWalker); |
|
358 |
|
359 void WalkDisableTextZoomRule(mozilla::dom::Element* aElement, |
|
360 nsRuleWalker* aRuleWalker); |
|
361 |
|
362 #ifdef DEBUG |
|
363 // Just like AddImportantRules except it doesn't actually add anything; it |
|
364 // just asserts that there are no important rules between aCurrLevelNode and |
|
365 // aLastPrevLevelNode. |
|
366 void AssertNoImportantRules(nsRuleNode* aCurrLevelNode, |
|
367 nsRuleNode* aLastPrevLevelNode); |
|
368 |
|
369 // Just like AddImportantRules except it doesn't actually add anything; it |
|
370 // just asserts that there are no CSS rules between aCurrLevelNode and |
|
371 // aLastPrevLevelNode. Mostly useful for the preshint level. |
|
372 void AssertNoCSSRules(nsRuleNode* aCurrLevelNode, |
|
373 nsRuleNode* aLastPrevLevelNode); |
|
374 #endif |
|
375 |
|
376 // Enumerate the rules in a way that cares about the order of the |
|
377 // rules. |
|
378 // aElement is the element the rules are for. It might be null. aData |
|
379 // is the closure to pass to aCollectorFunc. If aContent is not null, |
|
380 // aData must be a RuleProcessorData* |
|
381 void FileRules(nsIStyleRuleProcessor::EnumFunc aCollectorFunc, |
|
382 RuleProcessorData* aData, mozilla::dom::Element* aElement, |
|
383 nsRuleWalker* aRuleWalker); |
|
384 |
|
385 // Enumerate all the rules in a way that doesn't care about the order |
|
386 // of the rules and break out if the enumeration is halted. |
|
387 void WalkRuleProcessors(nsIStyleRuleProcessor::EnumFunc aFunc, |
|
388 ElementDependentRuleProcessorData* aData, |
|
389 bool aWalkAllXBLStylesheets); |
|
390 |
|
391 /** |
|
392 * Bit-flags that can be passed to GetContext() in its parameter 'aFlags'. |
|
393 */ |
|
394 enum { |
|
395 eNoFlags = 0, |
|
396 eIsLink = 1 << 0, |
|
397 eIsVisitedLink = 1 << 1, |
|
398 eDoAnimation = 1 << 2, |
|
399 |
|
400 // Indicates that we should skip the flex-item-specific chunk of |
|
401 // ApplyStyleFixups(). This is useful if our parent has "display: flex" |
|
402 // but we can tell it's not going to actually be a flex container (e.g. if |
|
403 // it's the outer frame of a button widget, and we're the inline frame for |
|
404 // the button's label). |
|
405 eSkipFlexItemStyleFixup = 1 << 3 |
|
406 }; |
|
407 |
|
408 already_AddRefed<nsStyleContext> |
|
409 GetContext(nsStyleContext* aParentContext, |
|
410 nsRuleNode* aRuleNode, |
|
411 nsRuleNode* aVisitedRuleNode, |
|
412 nsIAtom* aPseudoTag, |
|
413 nsCSSPseudoElements::Type aPseudoType, |
|
414 mozilla::dom::Element* aElementForAnimation, |
|
415 uint32_t aFlags); |
|
416 |
|
417 nsPresContext* PresContext() { return mRuleTree->PresContext(); } |
|
418 |
|
419 // The sheets in each array in mSheets are stored with the most significant |
|
420 // sheet last. |
|
421 // The arrays for ePresHintSheet, eStyleAttrSheet, eTransitionSheet, |
|
422 // and eAnimationSheet are always empty. (FIXME: We should reduce |
|
423 // the storage needed for them.) |
|
424 nsCOMArray<nsIStyleSheet> mSheets[eSheetTypeCount]; |
|
425 |
|
426 // mRuleProcessors[eScopedDocSheet] is always null; rule processors |
|
427 // for scoped style sheets are stored in mScopedDocSheetRuleProcessors. |
|
428 nsCOMPtr<nsIStyleRuleProcessor> mRuleProcessors[eSheetTypeCount]; |
|
429 |
|
430 // Rule processors for HTML5 scoped style sheets, one per scope. |
|
431 nsTArray<nsCOMPtr<nsIStyleRuleProcessor> > mScopedDocSheetRuleProcessors; |
|
432 |
|
433 // cached instance for enabling/disabling |
|
434 nsCOMPtr<nsIStyleSheet> mQuirkStyleSheet; |
|
435 |
|
436 nsRefPtr<nsBindingManager> mBindingManager; |
|
437 |
|
438 nsRuleNode* mRuleTree; // This is the root of our rule tree. It is a |
|
439 // lexicographic tree of matched rules that style |
|
440 // contexts use to look up properties. |
|
441 |
|
442 uint16_t mBatching; |
|
443 |
|
444 unsigned mInShutdown : 1; |
|
445 unsigned mAuthorStyleDisabled: 1; |
|
446 unsigned mInReconstruct : 1; |
|
447 unsigned mInitFontFeatureValuesLookup : 1; |
|
448 unsigned mDirty : 9; // one dirty bit is used per sheet type |
|
449 |
|
450 uint32_t mUnusedRuleNodeCount; // used to batch rule node GC |
|
451 nsTArray<nsStyleContext*> mRoots; // style contexts with no parent |
|
452 |
|
453 // Empty style rules to force things that restrict which properties |
|
454 // apply into different branches of the rule tree. |
|
455 nsRefPtr<nsEmptyStyleRule> mFirstLineRule, mFirstLetterRule, mPlaceholderRule; |
|
456 |
|
457 // Style rule which sets all properties to their initial values for |
|
458 // determining when context-sensitive values are in use. |
|
459 nsRefPtr<nsInitialStyleRule> mInitialStyleRule; |
|
460 |
|
461 // Style rule that sets the internal -x-text-zoom property on |
|
462 // <svg:text> elements to disable the effect of text zooming. |
|
463 nsRefPtr<nsDisableTextZoomStyleRule> mDisableTextZoomStyleRule; |
|
464 |
|
465 // Old rule trees, which should only be non-empty between |
|
466 // BeginReconstruct and EndReconstruct, but in case of bugs that cause |
|
467 // style contexts to exist too long, may last longer. |
|
468 nsTArray<nsRuleNode*> mOldRuleTrees; |
|
469 |
|
470 // whether font feature values lookup object needs initialization |
|
471 nsRefPtr<gfxFontFeatureValueSet> mFontFeatureValuesLookup; |
|
472 }; |
|
473 |
|
474 #ifdef MOZILLA_INTERNAL_API |
|
475 inline |
|
476 void nsRuleNode::AddRef() |
|
477 { |
|
478 if (mRefCnt++ == 0 && !IsRoot()) { |
|
479 mPresContext->StyleSet()->RuleNodeInUse(); |
|
480 } |
|
481 } |
|
482 |
|
483 inline |
|
484 void nsRuleNode::Release() |
|
485 { |
|
486 if (--mRefCnt == 0 && !IsRoot()) { |
|
487 mPresContext->StyleSet()->RuleNodeUnused(); |
|
488 } |
|
489 } |
|
490 #endif |
|
491 |
|
492 #endif |