layout/style/nsStyleSet.h

branch
TOR_BUG_9701
changeset 3
141e0f1194b1
equal deleted inserted replaced
-1:000000000000 0:f7ce22c80a39
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

mercurial