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
|