1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is Mozilla Communicator client code.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications Corporation.
19 : * Portions created by the Initial Developer are Copyright (C) 1998
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Original Author: David W. Hyatt (hyatt@netscape.com)
24 : * L. David Baron <dbaron@dbaron.org>
25 : *
26 : * Alternatively, the contents of this file may be used under the terms of
27 : * either of the GNU General Public License Version 2 or later (the "GPL"),
28 : * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 : * in which case the provisions of the GPL or the LGPL are applicable instead
30 : * of those above. If you wish to allow use of your version of this file only
31 : * under the terms of either the GPL or the LGPL, and not to allow others to
32 : * use your version of this file under the terms of the MPL, indicate your
33 : * decision by deleting the provisions above and replace them with the notice
34 : * and other provisions required by the GPL or the LGPL. If you do not delete
35 : * the provisions above, a recipient may use your version of this file under
36 : * the terms of any one of the MPL, the GPL or the LGPL.
37 : *
38 : * ***** END LICENSE BLOCK ***** */
39 :
40 : /*
41 : * a node in the lexicographic tree of rules that match an element,
42 : * responsible for converting the rules' information into computed style
43 : */
44 :
45 : #ifndef nsRuleNode_h___
46 : #define nsRuleNode_h___
47 :
48 : #include "nsPresContext.h"
49 : #include "nsStyleStruct.h"
50 :
51 : class nsStyleContext;
52 : struct PLDHashTable;
53 : struct nsRuleData;
54 : class nsIStyleRule;
55 : struct nsCSSValueList;
56 :
57 : class nsCSSValue;
58 : struct nsCSSRect;
59 :
60 : class nsStyleCoord;
61 :
62 : template <nsStyleStructID MinIndex, nsStyleStructID Count>
63 : class FixedStyleStructArray
64 : {
65 : private:
66 : void* mArray[Count];
67 : public:
68 0 : void*& operator[](nsStyleStructID aIndex) {
69 0 : NS_ABORT_IF_FALSE(MinIndex <= aIndex && aIndex < (MinIndex + Count),
70 : "out of range");
71 0 : return mArray[aIndex - MinIndex];
72 : }
73 :
74 : const void* operator[](nsStyleStructID aIndex) const {
75 : NS_ABORT_IF_FALSE(MinIndex <= aIndex && aIndex < (MinIndex + Count),
76 : "out of range");
77 : return mArray[aIndex - MinIndex];
78 : }
79 : };
80 :
81 : struct nsInheritedStyleData
82 : {
83 : FixedStyleStructArray<nsStyleStructID_Inherited_Start,
84 : nsStyleStructID_Inherited_Count> mStyleStructs;
85 :
86 : void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
87 : return aContext->AllocateFromShell(sz);
88 : }
89 :
90 : void DestroyStructs(PRUint32 aBits, nsPresContext* aContext) {
91 : #define STYLE_STRUCT_INHERITED(name, checkdata_cb, ctor_args) \
92 : void *name##Data = mStyleStructs[eStyleStruct_##name]; \
93 : if (name##Data && !(aBits & NS_STYLE_INHERIT_BIT(name))) \
94 : static_cast<nsStyle##name*>(name##Data)->Destroy(aContext);
95 : #define STYLE_STRUCT_RESET(name, checkdata_cb, ctor_args)
96 :
97 : #include "nsStyleStructList.h"
98 :
99 : #undef STYLE_STRUCT_INHERITED
100 : #undef STYLE_STRUCT_RESET
101 : }
102 :
103 : void Destroy(PRUint32 aBits, nsPresContext* aContext) {
104 : DestroyStructs(aBits, aContext);
105 : aContext->FreeToShell(sizeof(nsInheritedStyleData), this);
106 : }
107 :
108 : nsInheritedStyleData() {
109 : for (nsStyleStructID i = nsStyleStructID_Inherited_Start;
110 : i < nsStyleStructID_Inherited_Start + nsStyleStructID_Inherited_Count;
111 : i = nsStyleStructID(i + 1)) {
112 : mStyleStructs[i] = nsnull;
113 : }
114 : }
115 : };
116 :
117 : struct nsResetStyleData
118 : {
119 : FixedStyleStructArray<nsStyleStructID_Reset_Start,
120 : nsStyleStructID_Reset_Count> mStyleStructs;
121 :
122 : nsResetStyleData()
123 : {
124 : for (nsStyleStructID i = nsStyleStructID_Reset_Start;
125 : i < nsStyleStructID_Reset_Start + nsStyleStructID_Reset_Count;
126 : i = nsStyleStructID(i + 1)) {
127 : mStyleStructs[i] = nsnull;
128 : }
129 : }
130 :
131 : void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW {
132 : return aContext->AllocateFromShell(sz);
133 : }
134 :
135 : void Destroy(PRUint32 aBits, nsPresContext* aContext) {
136 : #define STYLE_STRUCT_RESET(name, checkdata_cb, ctor_args) \
137 : void *name##Data = mStyleStructs[eStyleStruct_##name]; \
138 : if (name##Data && !(aBits & NS_STYLE_INHERIT_BIT(name))) \
139 : static_cast<nsStyle##name*>(name##Data)->Destroy(aContext);
140 : #define STYLE_STRUCT_INHERITED(name, checkdata_cb, ctor_args)
141 :
142 : #include "nsStyleStructList.h"
143 :
144 : #undef STYLE_STRUCT_RESET
145 : #undef STYLE_STRUCT_INHERITED
146 :
147 : aContext->FreeToShell(sizeof(nsResetStyleData), this);
148 : }
149 : };
150 :
151 : struct nsCachedStyleData
152 : {
153 : nsInheritedStyleData* mInheritedData;
154 : nsResetStyleData* mResetData;
155 :
156 : static bool IsReset(const nsStyleStructID aSID) {
157 : NS_ABORT_IF_FALSE(0 <= aSID && aSID < nsStyleStructID_Length,
158 : "must be an inherited or reset SID");
159 : return nsStyleStructID_Reset_Start <= aSID;
160 : }
161 :
162 : static PRUint32 GetBitForSID(const nsStyleStructID aSID) {
163 : return 1 << aSID;
164 : }
165 :
166 : void* NS_FASTCALL GetStyleData(const nsStyleStructID aSID) {
167 : if (IsReset(aSID)) {
168 : if (mResetData) {
169 : return mResetData->mStyleStructs[aSID];
170 : }
171 : } else {
172 : if (mInheritedData) {
173 : return mInheritedData->mStyleStructs[aSID];
174 : }
175 : }
176 : return nsnull;
177 : }
178 :
179 : // Typesafe and faster versions of the above
180 : #define STYLE_STRUCT_INHERITED(name_, checkdata_cb_, ctor_args_) \
181 : nsStyle##name_ * NS_FASTCALL GetStyle##name_ () { \
182 : return mInheritedData ? static_cast<nsStyle##name_*>( \
183 : mInheritedData->mStyleStructs[eStyleStruct_##name_]) : nsnull; \
184 : }
185 : #define STYLE_STRUCT_RESET(name_, checkdata_cb_, ctor_args_) \
186 : nsStyle##name_ * NS_FASTCALL GetStyle##name_ () { \
187 : return mResetData ? static_cast<nsStyle##name_*>( \
188 : mResetData->mStyleStructs[eStyleStruct_##name_]) : nsnull; \
189 : }
190 : #include "nsStyleStructList.h"
191 : #undef STYLE_STRUCT_RESET
192 : #undef STYLE_STRUCT_INHERITED
193 :
194 : void Destroy(PRUint32 aBits, nsPresContext* aContext) {
195 : if (mResetData)
196 : mResetData->Destroy(aBits, aContext);
197 : if (mInheritedData)
198 : mInheritedData->Destroy(aBits, aContext);
199 : mResetData = nsnull;
200 : mInheritedData = nsnull;
201 : }
202 :
203 : nsCachedStyleData() :mInheritedData(nsnull), mResetData(nsnull) {}
204 0 : ~nsCachedStyleData() {}
205 : };
206 :
207 : /**
208 : * nsRuleNode is a node in a lexicographic tree (the "rule tree")
209 : * indexed by style rules (implementations of nsIStyleRule).
210 : *
211 : * The rule tree is owned by the nsStyleSet and is destroyed when the
212 : * presentation of the document goes away. It is garbage-collected
213 : * (using mark-and-sweep garbage collection) during the lifetime of the
214 : * document (when dynamic changes cause the destruction of enough style
215 : * contexts). Rule nodes are marked if they are pointed to by a style
216 : * context or one of their descendants is.
217 : *
218 : * An nsStyleContext, which represents the computed style data for an
219 : * element, points to an nsRuleNode. The path from the root of the rule
220 : * tree to the nsStyleContext's mRuleNode gives the list of the rules
221 : * matched, from least important in the cascading order to most
222 : * important in the cascading order.
223 : *
224 : * The reason for using a lexicographic tree is that it allows for
225 : * sharing of style data, which saves both memory (for storing the
226 : * computed style data) and time (for computing them). This sharing
227 : * depends on the computed style data being stored in structs (nsStyle*)
228 : * that contain only properties that are inherited by default
229 : * ("inherited structs") or structs that contain only properties that
230 : * are not inherited by default ("reset structs"). The optimization
231 : * depends on the normal case being that style rules specify relatively
232 : * few properties and even that elements generally have relatively few
233 : * properties specified. This allows sharing in the following ways:
234 : * 1. [mainly reset structs] When a style data struct will contain the
235 : * same computed value for any elements that match the same set of
236 : * rules (common for reset structs), it can be stored on the
237 : * nsRuleNode instead of on the nsStyleContext.
238 : * 2. [only? reset structs] When (1) occurs, and an nsRuleNode doesn't
239 : * have any rules that change the values in the struct, the
240 : * nsRuleNode can share that struct with its parent nsRuleNode.
241 : * 3. [mainly inherited structs] When an element doesn't match any
242 : * rules that change the value of a property (or, in the edge case,
243 : * when all the values specified are 'inherit'), the nsStyleContext
244 : * can use the same nsStyle* struct as its parent nsStyleContext.
245 : *
246 : * Since the data represented by an nsIStyleRule are immutable, the data
247 : * represented by an nsRuleNode are also immutable.
248 : */
249 :
250 : class nsRuleNode {
251 : public:
252 : enum RuleDetail {
253 : eRuleNone, // No props have been specified at all.
254 : eRulePartialReset, // At least one prop with a non-"inherit" value
255 : // has been specified. No props have been
256 : // specified with an "inherit" value. At least
257 : // one prop remains unspecified.
258 : eRulePartialMixed, // At least one prop with a non-"inherit" value
259 : // has been specified. Some props may also have
260 : // been specified with an "inherit" value. At
261 : // least one prop remains unspecified.
262 : eRulePartialInherited, // Only props with "inherit" values have
263 : // have been specified. At least one prop
264 : // remains unspecified.
265 : eRuleFullReset, // All props have been specified. None has an
266 : // "inherit" value.
267 : eRuleFullMixed, // All props have been specified. At least one has
268 : // a non-"inherit" value.
269 : eRuleFullInherited // All props have been specified with "inherit"
270 : // values.
271 : };
272 :
273 : private:
274 : nsPresContext* mPresContext; // Our pres context.
275 :
276 : nsRuleNode* mParent; // A pointer to the parent node in the tree.
277 : // This enables us to walk backwards from the
278 : // most specific rule matched to the least
279 : // specific rule (which is the optimal order to
280 : // use for lookups of style properties.
281 : nsIStyleRule* mRule; // [STRONG] A pointer to our specific rule.
282 :
283 : nsRuleNode* mNextSibling; // This value should be used only by the
284 : // parent, since the parent may store
285 : // children in a hash, which means this
286 : // pointer is not meaningful. Order of
287 : // siblings is also not meaningful.
288 :
289 : struct Key {
290 : nsIStyleRule* mRule;
291 : PRUint8 mLevel;
292 : bool mIsImportantRule;
293 :
294 : Key(nsIStyleRule* aRule, PRUint8 aLevel, bool aIsImportantRule)
295 : : mRule(aRule), mLevel(aLevel), mIsImportantRule(aIsImportantRule)
296 : {}
297 :
298 : bool operator==(const Key& aOther) const
299 : {
300 : return mRule == aOther.mRule &&
301 : mLevel == aOther.mLevel &&
302 : mIsImportantRule == aOther.mIsImportantRule;
303 : }
304 :
305 : bool operator!=(const Key& aOther) const
306 : {
307 : return !(*this == aOther);
308 : }
309 : };
310 :
311 : static PLDHashNumber
312 : ChildrenHashHashKey(PLDHashTable *aTable, const void *aKey);
313 :
314 : static bool
315 : ChildrenHashMatchEntry(PLDHashTable *aTable,
316 : const PLDHashEntryHdr *aHdr,
317 : const void *aKey);
318 :
319 : static PLDHashTableOps ChildrenHashOps;
320 :
321 : static PLDHashOperator
322 : EnqueueRuleNodeChildren(PLDHashTable *table, PLDHashEntryHdr *hdr,
323 : PRUint32 number, void *arg);
324 :
325 : Key GetKey() const {
326 : return Key(mRule, GetLevel(), IsImportantRule());
327 : }
328 :
329 : // The children of this node are stored in either a hashtable or list
330 : // that maps from rules to our nsRuleNode children. When matching
331 : // rules, we use this mapping to transition from node to node
332 : // (constructing new nodes as needed to flesh out the tree).
333 :
334 : union {
335 : void* asVoid;
336 : nsRuleNode* asList;
337 : PLDHashTable* asHash;
338 : } mChildren; // Accessed only through the methods below.
339 :
340 : enum {
341 : kTypeMask = 0x1,
342 : kListType = 0x0,
343 : kHashType = 0x1
344 : };
345 : enum {
346 : // Maximum to have in a list before converting to a hashtable.
347 : // XXX Need to optimize this.
348 : kMaxChildrenInList = 32
349 : };
350 :
351 : bool HaveChildren() const {
352 : return mChildren.asVoid != nsnull;
353 : }
354 : bool ChildrenAreHashed() {
355 : return (PRWord(mChildren.asVoid) & kTypeMask) == kHashType;
356 : }
357 : nsRuleNode* ChildrenList() {
358 : return mChildren.asList;
359 : }
360 : nsRuleNode** ChildrenListPtr() {
361 : return &mChildren.asList;
362 : }
363 : PLDHashTable* ChildrenHash() {
364 : return (PLDHashTable*) (PRWord(mChildren.asHash) & ~PRWord(kTypeMask));
365 : }
366 : void SetChildrenList(nsRuleNode *aList) {
367 : NS_ASSERTION(!(PRWord(aList) & kTypeMask),
368 : "pointer not 2-byte aligned");
369 : mChildren.asList = aList;
370 : }
371 : void SetChildrenHash(PLDHashTable *aHashtable) {
372 : NS_ASSERTION(!(PRWord(aHashtable) & kTypeMask),
373 : "pointer not 2-byte aligned");
374 : mChildren.asHash = (PLDHashTable*)(PRWord(aHashtable) | kHashType);
375 : }
376 : void ConvertChildrenToHash();
377 :
378 : nsCachedStyleData mStyleData; // Any data we cached on the rule node.
379 :
380 : PRUint32 mDependentBits; // Used to cache the fact that we can look up
381 : // cached data under a parent rule.
382 :
383 : PRUint32 mNoneBits; // Used to cache the fact that the branch to this
384 : // node specifies no non-inherited data for a
385 : // given struct type. (This usually implies that
386 : // the entire branch specifies no non-inherited
387 : // data, although not necessarily, if a
388 : // non-inherited value is overridden by an
389 : // explicit 'inherit' value.) For example, if an
390 : // entire rule branch specifies no color
391 : // information, then a bit will be set along every
392 : // rule node on that branch, so that you can break
393 : // out of the rule tree early and just inherit
394 : // from the parent style context. The presence of
395 : // this bit means we should just get inherited
396 : // data from the parent style context, and it is
397 : // never used for reset structs since their
398 : // Compute*Data functions don't initialize from
399 : // inherited data.
400 :
401 : // Reference count. This just counts the style contexts that reference this
402 : // rulenode. And children the rulenode has had. When this goes to 0 or
403 : // stops being 0, we notify the style set.
404 : // Note, in particular, that when a child is removed mRefCnt is NOT
405 : // decremented. This is on purpose; the notifications to the style set are
406 : // only used to determine when it's worth running GC on the ruletree, and
407 : // this setup makes it so we only count unused ruletree leaves for purposes
408 : // of deciding when to GC. We could more accurately count unused rulenodes
409 : // by releasing/addrefing our parent when our refcount transitions to or from
410 : // 0, but it doesn't seem worth it to do that.
411 : PRUint32 mRefCnt;
412 :
413 : public:
414 : // Overloaded new operator. Initializes the memory to 0 and relies on an arena
415 : // (which comes from the presShell) to perform the allocation.
416 : void* operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW;
417 : void Destroy() { DestroyInternal(nsnull); }
418 :
419 : // Implemented in nsStyleSet.h, since it needs to know about nsStyleSet.
420 : inline void AddRef();
421 :
422 : // Implemented in nsStyleSet.h, since it needs to know about nsStyleSet.
423 : inline void Release();
424 :
425 : protected:
426 : void DestroyInternal(nsRuleNode ***aDestroyQueueTail);
427 : void PropagateDependentBit(PRUint32 aBit, nsRuleNode* aHighestNode);
428 : void PropagateNoneBit(PRUint32 aBit, nsRuleNode* aHighestNode);
429 :
430 : const void* SetDefaultOnRoot(const nsStyleStructID aSID,
431 : nsStyleContext* aContext);
432 :
433 : const void*
434 : WalkRuleTree(const nsStyleStructID aSID, nsStyleContext* aContext);
435 :
436 : const void*
437 : ComputeDisplayData(void* aStartStruct,
438 : const nsRuleData* aRuleData,
439 : nsStyleContext* aContext, nsRuleNode* aHighestNode,
440 : RuleDetail aRuleDetail,
441 : const bool aCanStoreInRuleTree);
442 :
443 : const void*
444 : ComputeVisibilityData(void* aStartStruct,
445 : const nsRuleData* aRuleData,
446 : nsStyleContext* aContext, nsRuleNode* aHighestNode,
447 : RuleDetail aRuleDetail,
448 : const bool aCanStoreInRuleTree);
449 :
450 : const void*
451 : ComputeFontData(void* aStartStruct,
452 : const nsRuleData* aRuleData,
453 : nsStyleContext* aContext, nsRuleNode* aHighestNode,
454 : RuleDetail aRuleDetail,
455 : const bool aCanStoreInRuleTree);
456 :
457 : const void*
458 : ComputeColorData(void* aStartStruct,
459 : const nsRuleData* aRuleData,
460 : nsStyleContext* aContext, nsRuleNode* aHighestNode,
461 : RuleDetail aRuleDetail,
462 : const bool aCanStoreInRuleTree);
463 :
464 : const void*
465 : ComputeBackgroundData(void* aStartStruct,
466 : const nsRuleData* aRuleData,
467 : nsStyleContext* aContext, nsRuleNode* aHighestNode,
468 : RuleDetail aRuleDetail,
469 : const bool aCanStoreInRuleTree);
470 :
471 : const void*
472 : ComputeMarginData(void* aStartStruct,
473 : const nsRuleData* aRuleData,
474 : nsStyleContext* aContext, nsRuleNode* aHighestNode,
475 : RuleDetail aRuleDetail,
476 : const bool aCanStoreInRuleTree);
477 :
478 : const void*
479 : ComputeBorderData(void* aStartStruct,
480 : const nsRuleData* aRuleData,
481 : nsStyleContext* aContext, nsRuleNode* aHighestNode,
482 : RuleDetail aRuleDetail,
483 : const bool aCanStoreInRuleTree);
484 :
485 : const void*
486 : ComputePaddingData(void* aStartStruct,
487 : const nsRuleData* aRuleData,
488 : nsStyleContext* aContext, nsRuleNode* aHighestNode,
489 : RuleDetail aRuleDetail,
490 : const bool aCanStoreInRuleTree);
491 :
492 : const void*
493 : ComputeOutlineData(void* aStartStruct,
494 : const nsRuleData* aRuleData,
495 : nsStyleContext* aContext, nsRuleNode* aHighestNode,
496 : RuleDetail aRuleDetail,
497 : const bool aCanStoreInRuleTree);
498 :
499 : const void*
500 : ComputeListData(void* aStartStruct,
501 : const nsRuleData* aRuleData,
502 : nsStyleContext* aContext, nsRuleNode* aHighestNode,
503 : RuleDetail aRuleDetail,
504 : const bool aCanStoreInRuleTree);
505 :
506 : const void*
507 : ComputePositionData(void* aStartStruct,
508 : const nsRuleData* aRuleData,
509 : nsStyleContext* aContext, nsRuleNode* aHighestNode,
510 : RuleDetail aRuleDetail,
511 : const bool aCanStoreInRuleTree);
512 :
513 : const void*
514 : ComputeTableData(void* aStartStruct,
515 : const nsRuleData* aRuleData,
516 : nsStyleContext* aContext, nsRuleNode* aHighestNode,
517 : RuleDetail aRuleDetail,
518 : const bool aCanStoreInRuleTree);
519 :
520 : const void*
521 : ComputeTableBorderData(void* aStartStruct,
522 : const nsRuleData* aRuleData,
523 : nsStyleContext* aContext, nsRuleNode* aHighestNode,
524 : RuleDetail aRuleDetail,
525 : const bool aCanStoreInRuleTree);
526 :
527 : const void*
528 : ComputeContentData(void* aStartStruct,
529 : const nsRuleData* aRuleData,
530 : nsStyleContext* aContext, nsRuleNode* aHighestNode,
531 : RuleDetail aRuleDetail,
532 : const bool aCanStoreInRuleTree);
533 :
534 : const void*
535 : ComputeQuotesData(void* aStartStruct,
536 : const nsRuleData* aRuleData,
537 : nsStyleContext* aContext, nsRuleNode* aHighestNode,
538 : RuleDetail aRuleDetail,
539 : const bool aCanStoreInRuleTree);
540 :
541 : const void*
542 : ComputeTextData(void* aStartStruct,
543 : const nsRuleData* aRuleData,
544 : nsStyleContext* aContext, nsRuleNode* aHighestNode,
545 : RuleDetail aRuleDetail,
546 : const bool aCanStoreInRuleTree);
547 :
548 : const void*
549 : ComputeTextResetData(void* aStartStruct,
550 : const nsRuleData* aRuleData,
551 : nsStyleContext* aContext, nsRuleNode* aHighestNode,
552 : RuleDetail aRuleDetail,
553 : const bool aCanStoreInRuleTree);
554 :
555 : const void*
556 : ComputeUserInterfaceData(void* aStartStruct,
557 : const nsRuleData* aRuleData,
558 : nsStyleContext* aContext,
559 : nsRuleNode* aHighestNode,
560 : RuleDetail aRuleDetail,
561 : const bool aCanStoreInRuleTree);
562 :
563 : const void*
564 : ComputeUIResetData(void* aStartStruct,
565 : const nsRuleData* aRuleData,
566 : nsStyleContext* aContext, nsRuleNode* aHighestNode,
567 : RuleDetail aRuleDetail,
568 : const bool aCanStoreInRuleTree);
569 :
570 : const void*
571 : ComputeXULData(void* aStartStruct,
572 : const nsRuleData* aRuleData,
573 : nsStyleContext* aContext, nsRuleNode* aHighestNode,
574 : RuleDetail aRuleDetail,
575 : const bool aCanStoreInRuleTree);
576 :
577 : const void*
578 : ComputeColumnData(void* aStartStruct,
579 : const nsRuleData* aRuleData,
580 : nsStyleContext* aContext, nsRuleNode* aHighestNode,
581 : RuleDetail aRuleDetail,
582 : const bool aCanStoreInRuleTree);
583 :
584 : const void*
585 : ComputeSVGData(void* aStartStruct,
586 : const nsRuleData* aRuleData,
587 : nsStyleContext* aContext, nsRuleNode* aHighestNode,
588 : RuleDetail aRuleDetail,
589 : const bool aCanStoreInRuleTree);
590 :
591 : const void*
592 : ComputeSVGResetData(void* aStartStruct,
593 : const nsRuleData* aRuleData,
594 : nsStyleContext* aContext, nsRuleNode* aHighestNode,
595 : RuleDetail aRuleDetail,
596 : const bool aCanStoreInRuleTree);
597 :
598 : // helpers for |ComputeFontData| that need access to |mNoneBits|:
599 : static void SetFontSize(nsPresContext* aPresContext,
600 : const nsRuleData* aRuleData,
601 : const nsStyleFont* aFont,
602 : const nsStyleFont* aParentFont,
603 : nscoord* aSize,
604 : const nsFont& aSystemFont,
605 : nscoord aParentSize,
606 : nscoord aScriptLevelAdjustedParentSize,
607 : bool aUsedStartStruct,
608 : bool aAtRoot,
609 : bool& aCanStoreInRuleTree);
610 :
611 : static void SetFont(nsPresContext* aPresContext,
612 : nsStyleContext* aContext,
613 : PRUint8 aGenericFontID,
614 : const nsRuleData* aRuleData,
615 : const nsStyleFont* aParentFont,
616 : nsStyleFont* aFont,
617 : bool aStartStruct,
618 : bool& aCanStoreInRuleTree);
619 :
620 : static void SetGenericFont(nsPresContext* aPresContext,
621 : nsStyleContext* aContext,
622 : PRUint8 aGenericFontID,
623 : nsStyleFont* aFont);
624 :
625 : void AdjustLogicalBoxProp(nsStyleContext* aContext,
626 : const nsCSSValue& aLTRSource,
627 : const nsCSSValue& aRTLSource,
628 : const nsCSSValue& aLTRLogicalValue,
629 : const nsCSSValue& aRTLLogicalValue,
630 : mozilla::css::Side aSide,
631 : nsCSSRect& aValueRect,
632 : bool& aCanStoreInRuleTree);
633 :
634 : inline RuleDetail CheckSpecifiedProperties(const nsStyleStructID aSID,
635 : const nsRuleData* aRuleData);
636 :
637 : const void* GetParentData(const nsStyleStructID aSID);
638 : #define STYLE_STRUCT(name_, checkdata_cb_, ctor_args_) \
639 : const nsStyle##name_* GetParent##name_();
640 : #include "nsStyleStructList.h"
641 : #undef STYLE_STRUCT
642 :
643 : already_AddRefed<nsCSSShadowArray>
644 : GetShadowData(const nsCSSValueList* aList,
645 : nsStyleContext* aContext,
646 : bool aIsBoxShadow,
647 : bool& inherited);
648 :
649 : private:
650 : nsRuleNode(nsPresContext* aPresContext, nsRuleNode* aParent,
651 : nsIStyleRule* aRule, PRUint8 aLevel, bool aIsImportant);
652 : ~nsRuleNode();
653 :
654 : public:
655 : static nsRuleNode* CreateRootNode(nsPresContext* aPresContext);
656 :
657 : // Transition never returns null; on out of memory it'll just return |this|.
658 : nsRuleNode* Transition(nsIStyleRule* aRule, PRUint8 aLevel,
659 : bool aIsImportantRule);
660 : nsRuleNode* GetParent() const { return mParent; }
661 : bool IsRoot() const { return mParent == nsnull; }
662 :
663 : // These PRUint8s are really nsStyleSet::sheetType values.
664 : PRUint8 GetLevel() const {
665 : NS_ASSERTION(!IsRoot(), "can't call on root");
666 : return (mDependentBits & NS_RULE_NODE_LEVEL_MASK) >>
667 : NS_RULE_NODE_LEVEL_SHIFT;
668 : }
669 : bool IsImportantRule() const {
670 : NS_ASSERTION(!IsRoot(), "can't call on root");
671 : return (mDependentBits & NS_RULE_NODE_IS_IMPORTANT) != 0;
672 : }
673 :
674 : // NOTE: Does not |AddRef|.
675 : nsIStyleRule* GetRule() const { return mRule; }
676 : // NOTE: Does not |AddRef|.
677 0 : nsPresContext* GetPresContext() const { return mPresContext; }
678 :
679 : const void* GetStyleData(nsStyleStructID aSID,
680 : nsStyleContext* aContext,
681 : bool aComputeData);
682 :
683 : #define STYLE_STRUCT(name_, checkdata_cb_, ctor_args_) \
684 : const nsStyle##name_* GetStyle##name_(nsStyleContext* aContext, \
685 : bool aComputeData);
686 : #include "nsStyleStructList.h"
687 : #undef STYLE_STRUCT
688 :
689 : /*
690 : * Garbage collection. Mark walks up the tree, marking any unmarked
691 : * ancestors until it reaches a marked one. Sweep recursively sweeps
692 : * the children, destroys any that are unmarked, and clears marks,
693 : * returning true if the node on which it was called was destroyed.
694 : */
695 : void Mark();
696 : bool Sweep();
697 :
698 : static bool
699 : HasAuthorSpecifiedRules(nsStyleContext* aStyleContext,
700 : PRUint32 ruleTypeMask,
701 : bool aAuthorColorsAllowed);
702 :
703 : // Expose this so media queries can use it
704 : static nscoord CalcLengthWithInitialFont(nsPresContext* aPresContext,
705 : const nsCSSValue& aValue);
706 : // Expose this so nsTransformFunctions can use it.
707 : static nscoord CalcLength(const nsCSSValue& aValue,
708 : nsStyleContext* aStyleContext,
709 : nsPresContext* aPresContext,
710 : bool& aCanStoreInRuleTree);
711 :
712 : struct ComputedCalc {
713 : nscoord mLength;
714 : float mPercent;
715 :
716 : ComputedCalc(nscoord aLength, float aPercent)
717 : : mLength(aLength), mPercent(aPercent) {}
718 : };
719 : static ComputedCalc
720 : SpecifiedCalcToComputedCalc(const nsCSSValue& aValue,
721 : nsStyleContext* aStyleContext,
722 : nsPresContext* aPresContext,
723 : bool& aCanStoreInRuleTree);
724 :
725 : // Compute the value of an nsStyleCoord that IsCalcUnit().
726 : // (Values that don't require aPercentageBasis should be handled
727 : // inside nsRuleNode rather than through this API.)
728 : static nscoord ComputeComputedCalc(const nsStyleCoord& aCoord,
729 : nscoord aPercentageBasis);
730 :
731 : // Compute the value of an nsStyleCoord that is either a coord, a
732 : // percent, or a calc expression.
733 : static nscoord ComputeCoordPercentCalc(const nsStyleCoord& aCoord,
734 : nscoord aPercentageBasis);
735 :
736 : // Return whether the rule tree for which this node is the root has
737 : // cached data such that we need to do dynamic change handling for
738 : // changes that change the results of media queries or require
739 : // rebuilding all style data.
740 : bool TreeHasCachedData() const {
741 : NS_ASSERTION(IsRoot(), "should only be called on root of rule tree");
742 : return HaveChildren() || mStyleData.mInheritedData || mStyleData.mResetData;
743 : }
744 :
745 : bool NodeHasCachedData(const nsStyleStructID aSID) {
746 : return !!mStyleData.GetStyleData(aSID);
747 : }
748 : };
749 :
750 : #endif
|