Bug 451040 ? Passwords Manager Empty after convert to MozStorage. r=gavin
[wine-gecko.git] / layout / style / nsRuleNode.cpp
blob26ba3e79847eba0f5318eb941a212ea570f91ed4
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
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/
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.
15 * The Original Code is Mozilla Communicator client code.
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.
22 * Contributor(s):
23 * Original Author: David W. Hyatt (hyatt@netscape.com)
24 * Daniel Glazman <glazman@netscape.com>
25 * Roger B. Sidje <rbs@maths.uq.edu.au>
26 * Mats Palmgren <mats.palmgren@bredband.net>
27 * L. David Baron <dbaron@dbaron.org>
28 * Christian Biesinger <cbiesinger@web.de>
29 * Michael Ventnor <m.ventnor@gmail.com>
31 * Alternatively, the contents of this file may be used under the terms of
32 * either of the GNU General Public License Version 2 or later (the "GPL"),
33 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
34 * in which case the provisions of the GPL or the LGPL are applicable instead
35 * of those above. If you wish to allow use of your version of this file only
36 * under the terms of either the GPL or the LGPL, and not to allow others to
37 * use your version of this file under the terms of the MPL, indicate your
38 * decision by deleting the provisions above and replace them with the notice
39 * and other provisions required by the GPL or the LGPL. If you do not delete
40 * the provisions above, a recipient may use your version of this file under
41 * the terms of any one of the MPL, the GPL or the LGPL.
43 * ***** END LICENSE BLOCK ***** */
46 * a node in the lexicographic tree of rules that match an element,
47 * responsible for converting the rules' information into computed style
50 #include "nsRuleNode.h"
51 #include "nscore.h"
52 #include "nsIServiceManager.h"
53 #include "nsIDeviceContext.h"
54 #include "nsILookAndFeel.h"
55 #include "nsIPresShell.h"
56 #include "nsIThebesFontMetrics.h"
57 #include "gfxFont.h"
58 #include "nsStyleUtil.h"
59 #include "nsCSSPseudoElements.h"
60 #include "nsThemeConstants.h"
61 #include "nsITheme.h"
62 #include "pldhash.h"
63 #include "nsStyleContext.h"
64 #include "nsStyleSet.h"
65 #include "nsSize.h"
66 #include "imgIRequest.h"
67 #include "nsRuleData.h"
68 #include "nsILanguageAtomService.h"
69 #include "nsIStyleRule.h"
70 #include "nsBidiUtils.h"
71 #include "nsStyleStructInlines.h"
74 * For storage of an |nsRuleNode|'s children in a PLDHashTable.
77 struct ChildrenHashEntry : public PLDHashEntryHdr {
78 // key is |mRuleNode->GetKey()|
79 nsRuleNode *mRuleNode;
82 /* static */ PR_CALLBACK PLDHashNumber
83 nsRuleNode::ChildrenHashHashKey(PLDHashTable *aTable, const void *aKey)
85 const nsRuleNode::Key *key =
86 static_cast<const nsRuleNode::Key*>(aKey);
87 // Disagreement on importance and level for the same rule is extremely
88 // rare, so hash just on the rule.
89 return PL_DHashVoidPtrKeyStub(aTable, key->mRule);
92 /* static */ PR_CALLBACK PRBool
93 nsRuleNode::ChildrenHashMatchEntry(PLDHashTable *aTable,
94 const PLDHashEntryHdr *aHdr,
95 const void *aKey)
97 const ChildrenHashEntry *entry =
98 static_cast<const ChildrenHashEntry*>(aHdr);
99 const nsRuleNode::Key *key =
100 static_cast<const nsRuleNode::Key*>(aKey);
101 return entry->mRuleNode->GetKey() == *key;
104 /* static */ PLDHashTableOps
105 nsRuleNode::ChildrenHashOps = {
106 // It's probably better to allocate the table itself using malloc and
107 // free rather than the pres shell's arena because the table doesn't
108 // grow very often and the pres shell's arena doesn't recycle very
109 // large size allocations.
110 PL_DHashAllocTable,
111 PL_DHashFreeTable,
112 ChildrenHashHashKey,
113 ChildrenHashMatchEntry,
114 PL_DHashMoveEntryStub,
115 PL_DHashClearEntryStub,
116 PL_DHashFinalizeStub,
117 NULL
121 // EnsureBlockDisplay:
122 // - if the display value (argument) is not a block-type
123 // then we set it to a valid block display value
124 // - For enforcing the floated/positioned element CSS2 rules
125 static void EnsureBlockDisplay(PRUint8& display)
127 // see if the display value is already a block
128 switch (display) {
129 case NS_STYLE_DISPLAY_NONE :
130 // never change display:none *ever*
131 case NS_STYLE_DISPLAY_TABLE :
132 case NS_STYLE_DISPLAY_BLOCK :
133 case NS_STYLE_DISPLAY_LIST_ITEM :
134 // do not muck with these at all - already blocks
135 // This is equivalent to nsStyleDisplay::IsBlockOutside. (XXX Maybe we
136 // should just call that?)
137 break;
139 case NS_STYLE_DISPLAY_INLINE_TABLE :
140 // make inline tables into tables
141 display = NS_STYLE_DISPLAY_TABLE;
142 break;
144 default :
145 // make it a block
146 display = NS_STYLE_DISPLAY_BLOCK;
150 // XXX This should really be done in the CSS parser.
151 static nsString& Unquote(nsString& aString)
153 PRUnichar start = aString.First();
154 PRUnichar end = aString.Last();
156 if ((start == end) &&
157 ((start == PRUnichar('\"')) ||
158 (start == PRUnichar('\'')))) {
159 PRInt32 length = aString.Length();
160 aString.Truncate(length - 1);
161 aString.Cut(0, 1);
163 return aString;
166 static nscoord CalcLengthWith(const nsCSSValue& aValue,
167 nscoord aFontSize,
168 const nsStyleFont* aStyleFont,
169 nsStyleContext* aStyleContext,
170 nsPresContext* aPresContext,
171 PRBool& aInherited)
173 NS_ASSERTION(aValue.IsLengthUnit(), "not a length unit");
174 NS_ASSERTION(aStyleFont || aStyleContext, "Must have style data");
175 NS_ASSERTION(aPresContext, "Must have prescontext");
177 if (aValue.IsFixedLengthUnit()) {
178 return aPresContext->TwipsToAppUnits(aValue.GetLengthTwips());
180 nsCSSUnit unit = aValue.GetUnit();
181 if (unit == eCSSUnit_Pixel) {
182 return nsPresContext::CSSPixelsToAppUnits(aValue.GetFloatValue());
184 // Common code for all units other than pixels:
185 aInherited = PR_TRUE;
186 if (!aStyleFont) {
187 aStyleFont = aStyleContext->GetStyleFont();
189 if (aFontSize == -1) {
190 // XXX Should this be aStyleFont->mSize instead to avoid taking minfontsize
191 // prefs into account?
192 aFontSize = aStyleFont->mFont.size;
194 switch (unit) {
195 case eCSSUnit_EM: {
196 return NSToCoordRound(aValue.GetFloatValue() * float(aFontSize));
197 // XXX scale against font metrics height instead?
199 case eCSSUnit_EN: {
200 return NSToCoordRound((aValue.GetFloatValue() * float(aFontSize)) / 2.0f);
202 case eCSSUnit_XHeight: {
203 nsFont font = aStyleFont->mFont;
204 font.size = aFontSize;
205 nsCOMPtr<nsIFontMetrics> fm = aPresContext->GetMetricsFor(font);
206 nscoord xHeight;
207 fm->GetXHeight(xHeight);
208 return NSToCoordRound(aValue.GetFloatValue() * float(xHeight));
210 case eCSSUnit_CapHeight: {
211 NS_NOTYETIMPLEMENTED("cap height unit");
212 nscoord capHeight = ((aFontSize / 3) * 2); // XXX HACK!
213 return NSToCoordRound(aValue.GetFloatValue() * float(capHeight));
215 case eCSSUnit_Char: {
216 nsFont font = aStyleFont->mFont;
217 font.size = aFontSize;
218 nsCOMPtr<nsIFontMetrics> fm = aPresContext->GetMetricsFor(font);
219 nsCOMPtr<nsIThebesFontMetrics> tfm(do_QueryInterface(fm));
220 gfxFloat zeroWidth = (tfm->GetThebesFontGroup()->GetFontAt(0)
221 ->GetMetrics().zeroOrAveCharWidth);
223 return NSToCoordRound(aValue.GetFloatValue() *
224 NS_ceil(aPresContext->AppUnitsPerDevPixel() *
225 zeroWidth));
227 default:
228 NS_NOTREACHED("unexpected unit");
229 break;
231 return 0;
234 static nscoord CalcLength(const nsCSSValue& aValue,
235 nsStyleContext* aStyleContext,
236 nsPresContext* aPresContext,
237 PRBool& aInherited)
239 NS_ASSERTION(aStyleContext, "Must have style data");
241 return CalcLengthWith(aValue, -1, nsnull, aStyleContext, aPresContext, aInherited);
244 /* static */ nscoord
245 nsRuleNode::CalcLengthWithInitialFont(nsPresContext* aPresContext,
246 const nsCSSValue& aValue)
248 nsStyleFont defaultFont(aPresContext);
249 PRBool inherited;
250 return CalcLengthWith(aValue, -1, &defaultFont, nsnull, aPresContext,
251 inherited);
254 #define SETCOORD_NORMAL 0x01 // N
255 #define SETCOORD_AUTO 0x02 // A
256 #define SETCOORD_INHERIT 0x04 // H
257 #define SETCOORD_PERCENT 0x08 // P
258 #define SETCOORD_FACTOR 0x10 // F
259 #define SETCOORD_LENGTH 0x20 // L
260 #define SETCOORD_INTEGER 0x40 // I
261 #define SETCOORD_ENUMERATED 0x80 // E
262 #define SETCOORD_NONE 0x100 // O
263 #define SETCOORD_INITIAL_ZERO 0x200
264 #define SETCOORD_INITIAL_AUTO 0x400
265 #define SETCOORD_INITIAL_NONE 0x800
266 #define SETCOORD_INITIAL_NORMAL 0x1000
268 #define SETCOORD_LP (SETCOORD_LENGTH | SETCOORD_PERCENT)
269 #define SETCOORD_LH (SETCOORD_LENGTH | SETCOORD_INHERIT)
270 #define SETCOORD_AH (SETCOORD_AUTO | SETCOORD_INHERIT)
271 #define SETCOORD_LAH (SETCOORD_AUTO | SETCOORD_LENGTH | SETCOORD_INHERIT)
272 #define SETCOORD_LPH (SETCOORD_LP | SETCOORD_INHERIT)
273 #define SETCOORD_LPAH (SETCOORD_LP | SETCOORD_AH)
274 #define SETCOORD_LPEH (SETCOORD_LP | SETCOORD_ENUMERATED | SETCOORD_INHERIT)
275 #define SETCOORD_LPAEH (SETCOORD_LPAH | SETCOORD_ENUMERATED)
276 #define SETCOORD_LPOH (SETCOORD_LPH | SETCOORD_NONE)
277 #define SETCOORD_LPOEH (SETCOORD_LPOH | SETCOORD_ENUMERATED)
278 #define SETCOORD_LE (SETCOORD_LENGTH | SETCOORD_ENUMERATED)
279 #define SETCOORD_LEH (SETCOORD_LE | SETCOORD_INHERIT)
280 #define SETCOORD_IA (SETCOORD_INTEGER | SETCOORD_AUTO)
281 #define SETCOORD_LAE (SETCOORD_LENGTH | SETCOORD_AUTO | SETCOORD_ENUMERATED)
283 // changes aCoord iff it returns PR_TRUE
284 static PRBool SetCoord(const nsCSSValue& aValue, nsStyleCoord& aCoord,
285 const nsStyleCoord& aParentCoord,
286 PRInt32 aMask, nsStyleContext* aStyleContext,
287 nsPresContext* aPresContext, PRBool& aInherited)
289 PRBool result = PR_TRUE;
290 if (aValue.GetUnit() == eCSSUnit_Null) {
291 result = PR_FALSE;
293 else if (((aMask & SETCOORD_LENGTH) != 0) &&
294 aValue.IsLengthUnit()) {
295 aCoord.SetCoordValue(CalcLength(aValue, aStyleContext, aPresContext, aInherited));
297 else if (((aMask & SETCOORD_PERCENT) != 0) &&
298 (aValue.GetUnit() == eCSSUnit_Percent)) {
299 aCoord.SetPercentValue(aValue.GetPercentValue());
301 else if (((aMask & SETCOORD_INTEGER) != 0) &&
302 (aValue.GetUnit() == eCSSUnit_Integer)) {
303 aCoord.SetIntValue(aValue.GetIntValue(), eStyleUnit_Integer);
305 else if (((aMask & SETCOORD_ENUMERATED) != 0) &&
306 (aValue.GetUnit() == eCSSUnit_Enumerated)) {
307 aCoord.SetIntValue(aValue.GetIntValue(), eStyleUnit_Enumerated);
309 else if (((aMask & SETCOORD_AUTO) != 0) &&
310 (aValue.GetUnit() == eCSSUnit_Auto)) {
311 aCoord.SetAutoValue();
313 else if (((aMask & SETCOORD_INHERIT) != 0) &&
314 (aValue.GetUnit() == eCSSUnit_Inherit)) {
315 aCoord = aParentCoord; // just inherit value from parent
316 aInherited = PR_TRUE;
318 else if (((aMask & SETCOORD_NORMAL) != 0) &&
319 (aValue.GetUnit() == eCSSUnit_Normal)) {
320 aCoord.SetNormalValue();
322 else if (((aMask & SETCOORD_NONE) != 0) &&
323 (aValue.GetUnit() == eCSSUnit_None)) {
324 aCoord.SetNoneValue();
326 else if (((aMask & SETCOORD_FACTOR) != 0) &&
327 (aValue.GetUnit() == eCSSUnit_Number)) {
328 aCoord.SetFactorValue(aValue.GetFloatValue());
330 else if (((aMask & SETCOORD_INITIAL_AUTO) != 0) &&
331 (aValue.GetUnit() == eCSSUnit_Initial)) {
332 aCoord.SetAutoValue();
334 else if (((aMask & SETCOORD_INITIAL_ZERO) != 0) &&
335 (aValue.GetUnit() == eCSSUnit_Initial)) {
336 aCoord.SetCoordValue(0);
338 else if (((aMask & SETCOORD_INITIAL_NONE) != 0) &&
339 (aValue.GetUnit() == eCSSUnit_Initial)) {
340 aCoord.SetNoneValue();
342 else if (((aMask & SETCOORD_INITIAL_NORMAL) != 0) &&
343 (aValue.GetUnit() == eCSSUnit_Initial)) {
344 aCoord.SetNormalValue();
346 else {
347 result = PR_FALSE; // didn't set anything
349 return result;
352 static PRBool SetColor(const nsCSSValue& aValue, const nscolor aParentColor,
353 nsPresContext* aPresContext, nsStyleContext *aContext,
354 nscolor& aResult, PRBool& aInherited)
356 PRBool result = PR_FALSE;
357 nsCSSUnit unit = aValue.GetUnit();
359 if (eCSSUnit_Color == unit) {
360 aResult = aValue.GetColorValue();
361 result = PR_TRUE;
363 else if (eCSSUnit_String == unit) {
364 nsAutoString value;
365 aValue.GetStringValue(value);
366 nscolor rgba;
367 if (NS_ColorNameToRGB(value, &rgba)) {
368 aResult = rgba;
369 result = PR_TRUE;
372 else if (eCSSUnit_EnumColor == unit) {
373 PRInt32 intValue = aValue.GetIntValue();
374 if (0 <= intValue) {
375 nsILookAndFeel* look = aPresContext->LookAndFeel();
376 nsILookAndFeel::nsColorID colorID = (nsILookAndFeel::nsColorID) intValue;
377 if (NS_SUCCEEDED(look->GetColor(colorID, aResult))) {
378 result = PR_TRUE;
381 else {
382 switch (intValue) {
383 case NS_COLOR_MOZ_HYPERLINKTEXT:
384 aResult = aPresContext->DefaultLinkColor();
385 break;
386 case NS_COLOR_MOZ_VISITEDHYPERLINKTEXT:
387 aResult = aPresContext->DefaultVisitedLinkColor();
388 break;
389 case NS_COLOR_MOZ_ACTIVEHYPERLINKTEXT:
390 aResult = aPresContext->DefaultActiveLinkColor();
391 break;
392 case NS_COLOR_CURRENTCOLOR:
393 // The data computed from this can't be shared in the rule tree
394 // because they could be used on a node with a different color
395 aInherited = PR_TRUE;
396 aResult = aContext->GetStyleColor()->mColor;
397 break;
398 default:
399 NS_NOTREACHED("Should never have an unknown negative colorID.");
400 break;
402 result = PR_TRUE;
405 else if (eCSSUnit_Inherit == unit) {
406 aResult = aParentColor;
407 result = PR_TRUE;
408 aInherited = PR_TRUE;
410 return result;
413 // Overloaded new operator. Initializes the memory to 0 and relies on an arena
414 // (which comes from the presShell) to perform the allocation.
415 void*
416 nsRuleNode::operator new(size_t sz, nsPresContext* aPresContext) CPP_THROW_NEW
418 // Check the recycle list first.
419 return aPresContext->AllocateFromShell(sz);
422 /* static */ PR_CALLBACK PLDHashOperator
423 nsRuleNode::EnqueueRuleNodeChildren(PLDHashTable *table, PLDHashEntryHdr *hdr,
424 PRUint32 number, void *arg)
426 ChildrenHashEntry *entry = static_cast<ChildrenHashEntry*>(hdr);
427 nsRuleNode ***destroyQueueTail = static_cast<nsRuleNode***>(arg);
428 **destroyQueueTail = entry->mRuleNode;
429 *destroyQueueTail = &entry->mRuleNode->mNextSibling;
430 return PL_DHASH_NEXT;
433 // Overridden to prevent the global delete from being called, since the memory
434 // came out of an nsIArena instead of the global delete operator's heap.
435 void
436 nsRuleNode::DestroyInternal(nsRuleNode ***aDestroyQueueTail)
438 nsRuleNode *destroyQueue, **destroyQueueTail;
439 if (aDestroyQueueTail) {
440 destroyQueueTail = *aDestroyQueueTail;
441 } else {
442 destroyQueue = nsnull;
443 destroyQueueTail = &destroyQueue;
446 if (ChildrenAreHashed()) {
447 PLDHashTable *children = ChildrenHash();
448 PL_DHashTableEnumerate(children, EnqueueRuleNodeChildren,
449 &destroyQueueTail);
450 *destroyQueueTail = nsnull; // ensure null-termination
451 PL_DHashTableDestroy(children);
452 } else if (HaveChildren()) {
453 *destroyQueueTail = ChildrenList();
454 do {
455 destroyQueueTail = &(*destroyQueueTail)->mNextSibling;
456 } while (*destroyQueueTail);
458 mChildrenTaggedPtr = nsnull;
460 if (aDestroyQueueTail) {
461 // Our caller destroys the queue.
462 *aDestroyQueueTail = destroyQueueTail;
463 } else {
464 // We have to do destroy the queue. When we destroy each node, it
465 // will add its children to the queue.
466 while (destroyQueue) {
467 nsRuleNode *cur = destroyQueue;
468 destroyQueue = destroyQueue->mNextSibling;
469 if (!destroyQueue) {
470 NS_ASSERTION(destroyQueueTail == &cur->mNextSibling, "mangled list");
471 destroyQueueTail = &destroyQueue;
473 cur->DestroyInternal(&destroyQueueTail);
477 // Destroy ourselves.
478 this->~nsRuleNode();
480 // Don't let the memory be freed, since it will be recycled
481 // instead. Don't call the global operator delete.
482 mPresContext->FreeToShell(sizeof(nsRuleNode), this);
485 nsRuleNode* nsRuleNode::CreateRootNode(nsPresContext* aPresContext)
487 return new (aPresContext)
488 nsRuleNode(aPresContext, nsnull, nsnull, 0xff, PR_FALSE);
491 nsILanguageAtomService* nsRuleNode::gLangService = nsnull;
493 nsRuleNode::nsRuleNode(nsPresContext* aContext, nsRuleNode* aParent,
494 nsIStyleRule* aRule, PRUint8 aLevel,
495 PRBool aIsImportant)
496 : mPresContext(aContext),
497 mParent(aParent),
498 mRule(aRule),
499 mChildrenTaggedPtr(nsnull),
500 mDependentBits((PRUint32(aLevel) << NS_RULE_NODE_LEVEL_SHIFT) |
501 (aIsImportant ? NS_RULE_NODE_IS_IMPORTANT : 0)),
502 mNoneBits(0)
504 MOZ_COUNT_CTOR(nsRuleNode);
505 NS_IF_ADDREF(mRule);
507 NS_ASSERTION(IsRoot() || GetLevel() == aLevel, "not enough bits");
508 NS_ASSERTION(IsRoot() || IsImportantRule() == aIsImportant, "yikes");
511 nsRuleNode::~nsRuleNode()
513 MOZ_COUNT_DTOR(nsRuleNode);
514 if (mStyleData.mResetData || mStyleData.mInheritedData)
515 mStyleData.Destroy(0, mPresContext);
516 NS_IF_RELEASE(mRule);
519 nsRuleNode*
520 nsRuleNode::Transition(nsIStyleRule* aRule, PRUint8 aLevel,
521 PRPackedBool aIsImportantRule)
523 nsRuleNode* next = nsnull;
524 nsRuleNode::Key key(aRule, aLevel, aIsImportantRule);
526 if (HaveChildren() && !ChildrenAreHashed()) {
527 PRInt32 numKids = 0;
528 nsRuleNode* curr = ChildrenList();
529 while (curr && curr->GetKey() != key) {
530 curr = curr->mNextSibling;
531 ++numKids;
533 if (curr)
534 next = curr;
535 else if (numKids >= kMaxChildrenInList)
536 ConvertChildrenToHash();
539 if (ChildrenAreHashed()) {
540 ChildrenHashEntry *entry = static_cast<ChildrenHashEntry*>
541 (PL_DHashTableOperate(ChildrenHash(), &key, PL_DHASH_ADD));
542 if (!entry) {
543 return nsnull;
545 if (entry->mRuleNode)
546 next = entry->mRuleNode;
547 else {
548 next = entry->mRuleNode = new (mPresContext)
549 nsRuleNode(mPresContext, this, aRule, aLevel, aIsImportantRule);
550 if (!next) {
551 PL_DHashTableRawRemove(ChildrenHash(), entry);
552 return nsnull;
555 } else if (!next) {
556 // Create the new entry in our list.
557 next = new (mPresContext)
558 nsRuleNode(mPresContext, this, aRule, aLevel, aIsImportantRule);
559 if (!next) {
560 return nsnull;
562 next->mNextSibling = ChildrenList();
563 SetChildrenList(next);
566 return next;
569 void
570 nsRuleNode::ConvertChildrenToHash()
572 NS_ASSERTION(!ChildrenAreHashed() && HaveChildren(),
573 "must have a non-empty list of children");
574 PLDHashTable *hash = PL_NewDHashTable(&ChildrenHashOps, nsnull,
575 sizeof(ChildrenHashEntry),
576 kMaxChildrenInList * 4);
577 if (!hash)
578 return;
579 for (nsRuleNode* curr = ChildrenList(); curr; curr = curr->mNextSibling) {
580 // This will never fail because of the initial size we gave the table.
581 ChildrenHashEntry *entry = static_cast<ChildrenHashEntry*>(
582 PL_DHashTableOperate(hash, curr->mRule, PL_DHASH_ADD));
583 NS_ASSERTION(!entry->mRuleNode, "duplicate entries in list");
584 entry->mRuleNode = curr;
586 SetChildrenHash(hash);
589 inline void
590 nsRuleNode::PropagateNoneBit(PRUint32 aBit, nsRuleNode* aHighestNode)
592 nsRuleNode* curr = this;
593 for (;;) {
594 NS_ASSERTION(!(curr->mNoneBits & aBit), "propagating too far");
595 curr->mNoneBits |= aBit;
596 if (curr == aHighestNode)
597 break;
598 curr = curr->mParent;
602 inline void
603 nsRuleNode::PropagateDependentBit(PRUint32 aBit, nsRuleNode* aHighestNode)
605 for (nsRuleNode* curr = this; curr != aHighestNode; curr = curr->mParent) {
606 if (curr->mDependentBits & aBit) {
607 #ifdef DEBUG
608 while (curr != aHighestNode) {
609 NS_ASSERTION(curr->mDependentBits & aBit, "bit not set");
610 curr = curr->mParent;
612 #endif
613 break;
616 curr->mDependentBits |= aBit;
621 * The following "Check" functions are used for determining what type of
622 * sharing can be used for the data on this rule node. MORE HERE...
625 /* the information for a property (or in some cases, a rect group of
626 properties) */
628 struct PropertyCheckData {
629 size_t offset;
630 nsCSSType type;
634 * a callback function that that can revise the result of
635 * CheckSpecifiedProperties before finishing; aResult is the current
636 * result, and it returns the revised one.
638 typedef nsRuleNode::RuleDetail
639 (* PR_CALLBACK CheckCallbackFn)(const nsRuleDataStruct& aData,
640 nsRuleNode::RuleDetail aResult);
642 /* the information for all the properties in a style struct */
643 struct StructCheckData {
644 const PropertyCheckData* props;
645 PRInt32 nprops;
646 CheckCallbackFn callback;
651 * @param aValue the value being examined
652 * @param aSpecifiedCount to be incremented by one if the value is specified
653 * @param aInherited to be incremented by one if the value is set to inherit
655 inline void
656 ExamineCSSValue(const nsCSSValue& aValue,
657 PRUint32& aSpecifiedCount, PRUint32& aInheritedCount)
659 if (aValue.GetUnit() != eCSSUnit_Null) {
660 ++aSpecifiedCount;
661 if (aValue.GetUnit() == eCSSUnit_Inherit) {
662 ++aInheritedCount;
667 static void
668 ExamineCSSValuePair(const nsCSSValuePair* aValuePair,
669 PRUint32& aSpecifiedCount, PRUint32& aInheritedCount)
671 NS_PRECONDITION(aValuePair, "Must have a value pair");
673 ExamineCSSValue(aValuePair->mXValue, aSpecifiedCount, aInheritedCount);
674 ExamineCSSValue(aValuePair->mYValue, aSpecifiedCount, aInheritedCount);
677 static void
678 ExamineCSSRect(const nsCSSRect* aRect,
679 PRUint32& aSpecifiedCount, PRUint32& aInheritedCount)
681 NS_PRECONDITION(aRect, "Must have a rect");
683 NS_FOR_CSS_SIDES(side) {
684 ExamineCSSValue(aRect->*(nsCSSRect::sides[side]),
685 aSpecifiedCount, aInheritedCount);
689 PR_STATIC_CALLBACK(nsRuleNode::RuleDetail)
690 CheckFontCallback(const nsRuleDataStruct& aData,
691 nsRuleNode::RuleDetail aResult)
693 const nsRuleDataFont& fontData =
694 static_cast<const nsRuleDataFont&>(aData);
696 // em, ex, percent, 'larger', and 'smaller' values on font-size depend
697 // on the parent context's font-size
698 // Likewise, 'lighter' and 'bolder' values of 'font-weight' depend on
699 // the parent.
700 const nsCSSValue& size = fontData.mSize;
701 const nsCSSValue& weight = fontData.mWeight;
702 if ((size.IsRelativeLengthUnit() && size.GetUnit() != eCSSUnit_Pixel) ||
703 size.GetUnit() == eCSSUnit_Percent ||
704 (size.GetUnit() == eCSSUnit_Enumerated &&
705 (size.GetIntValue() == NS_STYLE_FONT_SIZE_SMALLER ||
706 size.GetIntValue() == NS_STYLE_FONT_SIZE_LARGER)) ||
707 #ifdef MOZ_MATHML
708 fontData.mScriptLevel.GetUnit() == eCSSUnit_Integer ||
709 #endif
710 (weight.GetUnit() == eCSSUnit_Enumerated &&
711 (weight.GetIntValue() == NS_STYLE_FONT_WEIGHT_BOLDER ||
712 weight.GetIntValue() == NS_STYLE_FONT_WEIGHT_LIGHTER))) {
713 NS_ASSERTION(aResult == nsRuleNode::eRulePartialReset ||
714 aResult == nsRuleNode::eRuleFullReset ||
715 aResult == nsRuleNode::eRulePartialMixed ||
716 aResult == nsRuleNode::eRuleFullMixed,
717 "we know we already have a reset-counted property");
718 // Promote reset to mixed since we have something that depends on
719 // the parent. But never promote to inherited since that could
720 // cause inheritance of the exact value.
721 if (aResult == nsRuleNode::eRulePartialReset)
722 aResult = nsRuleNode::eRulePartialMixed;
723 else if (aResult == nsRuleNode::eRuleFullReset)
724 aResult = nsRuleNode::eRuleFullMixed;
727 return aResult;
730 PR_STATIC_CALLBACK(nsRuleNode::RuleDetail)
731 CheckColorCallback(const nsRuleDataStruct& aData,
732 nsRuleNode::RuleDetail aResult)
734 const nsRuleDataColor& colorData =
735 static_cast<const nsRuleDataColor&>(aData);
737 // currentColor values for color require inheritance
738 if (colorData.mColor.GetUnit() == eCSSUnit_EnumColor &&
739 colorData.mColor.GetIntValue() == NS_COLOR_CURRENTCOLOR) {
740 NS_ASSERTION(aResult == nsRuleNode::eRuleFullReset,
741 "we should already be counted as full-reset");
742 aResult = nsRuleNode::eRuleFullInherited;
745 return aResult;
749 // for nsCSSPropList.h, so we get information on things in the style
750 // structs but not nsCSS*
751 #define CSS_PROP_INCLUDE_NOT_CSS
753 static const PropertyCheckData FontCheckProperties[] = {
754 #define CSS_PROP_FONT(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
755 { offsetof(nsRuleData##datastruct_, member_), type_ },
756 #include "nsCSSPropList.h"
757 #undef CSS_PROP_FONT
760 static const PropertyCheckData DisplayCheckProperties[] = {
761 #define CSS_PROP_DISPLAY(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
762 { offsetof(nsRuleData##datastruct_, member_), type_ },
763 #include "nsCSSPropList.h"
764 #undef CSS_PROP_DISPLAY
767 static const PropertyCheckData VisibilityCheckProperties[] = {
768 #define CSS_PROP_VISIBILITY(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
769 { offsetof(nsRuleData##datastruct_, member_), type_ },
770 #include "nsCSSPropList.h"
771 #undef CSS_PROP_VISIBILITY
774 static const PropertyCheckData MarginCheckProperties[] = {
775 #define CSS_PROP_MARGIN(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
776 { offsetof(nsRuleData##datastruct_, member_), type_ },
777 #include "nsCSSPropList.h"
778 #undef CSS_PROP_MARGIN
781 static const PropertyCheckData BorderCheckProperties[] = {
782 #define CSS_PROP_BORDER(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
783 { offsetof(nsRuleData##datastruct_, member_), type_ },
784 #include "nsCSSPropList.h"
785 #undef CSS_PROP_BORDER
788 static const PropertyCheckData PaddingCheckProperties[] = {
789 #define CSS_PROP_PADDING(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
790 { offsetof(nsRuleData##datastruct_, member_), type_ },
791 #include "nsCSSPropList.h"
792 #undef CSS_PROP_PADDING
795 static const PropertyCheckData OutlineCheckProperties[] = {
796 #define CSS_PROP_OUTLINE(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
797 { offsetof(nsRuleData##datastruct_, member_), type_ },
798 #include "nsCSSPropList.h"
799 #undef CSS_PROP_OUTLINE
802 static const PropertyCheckData ListCheckProperties[] = {
803 #define CSS_PROP_LIST(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
804 { offsetof(nsRuleData##datastruct_, member_), type_ },
805 #include "nsCSSPropList.h"
806 #undef CSS_PROP_LIST
809 static const PropertyCheckData ColorCheckProperties[] = {
810 #define CSS_PROP_COLOR(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
811 { offsetof(nsRuleData##datastruct_, member_), type_ },
812 #include "nsCSSPropList.h"
813 #undef CSS_PROP_COLOR
816 static const PropertyCheckData BackgroundCheckProperties[] = {
817 #define CSS_PROP_BACKGROUND(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
818 { offsetof(nsRuleData##datastruct_, member_), type_ },
819 #include "nsCSSPropList.h"
820 #undef CSS_PROP_BACKGROUND
823 static const PropertyCheckData PositionCheckProperties[] = {
824 #define CSS_PROP_POSITION(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
825 { offsetof(nsRuleData##datastruct_, member_), type_ },
826 #include "nsCSSPropList.h"
827 #undef CSS_PROP_POSITION
830 static const PropertyCheckData TableCheckProperties[] = {
831 #define CSS_PROP_TABLE(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
832 { offsetof(nsRuleData##datastruct_, member_), type_ },
833 #include "nsCSSPropList.h"
834 #undef CSS_PROP_TABLE
837 static const PropertyCheckData TableBorderCheckProperties[] = {
838 #define CSS_PROP_TABLEBORDER(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
839 { offsetof(nsRuleData##datastruct_, member_), type_ },
840 #include "nsCSSPropList.h"
841 #undef CSS_PROP_TABLEBORDER
844 static const PropertyCheckData ContentCheckProperties[] = {
845 #define CSS_PROP_CONTENT(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
846 { offsetof(nsRuleData##datastruct_, member_), type_ },
847 #include "nsCSSPropList.h"
848 #undef CSS_PROP_CONTENT
851 static const PropertyCheckData QuotesCheckProperties[] = {
852 #define CSS_PROP_QUOTES(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
853 { offsetof(nsRuleData##datastruct_, member_), type_ },
854 #include "nsCSSPropList.h"
855 #undef CSS_PROP_QUOTES
858 static const PropertyCheckData TextCheckProperties[] = {
859 #define CSS_PROP_TEXT(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
860 { offsetof(nsRuleData##datastruct_, member_), type_ },
861 #include "nsCSSPropList.h"
862 #undef CSS_PROP_TEXT
865 static const PropertyCheckData TextResetCheckProperties[] = {
866 #define CSS_PROP_TEXTRESET(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
867 { offsetof(nsRuleData##datastruct_, member_), type_ },
868 #include "nsCSSPropList.h"
869 #undef CSS_PROP_TEXTRESET
872 static const PropertyCheckData UserInterfaceCheckProperties[] = {
873 #define CSS_PROP_USERINTERFACE(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
874 { offsetof(nsRuleData##datastruct_, member_), type_ },
875 #include "nsCSSPropList.h"
876 #undef CSS_PROP_USERINTERFACE
879 static const PropertyCheckData UIResetCheckProperties[] = {
880 #define CSS_PROP_UIRESET(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
881 { offsetof(nsRuleData##datastruct_, member_), type_ },
882 #include "nsCSSPropList.h"
883 #undef CSS_PROP_UIRESET
886 static const PropertyCheckData XULCheckProperties[] = {
887 #define CSS_PROP_XUL(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
888 { offsetof(nsRuleData##datastruct_, member_), type_ },
889 #include "nsCSSPropList.h"
890 #undef CSS_PROP_XUL
893 #ifdef MOZ_SVG
894 static const PropertyCheckData SVGCheckProperties[] = {
895 #define CSS_PROP_SVG(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
896 { offsetof(nsRuleData##datastruct_, member_), type_ },
897 #include "nsCSSPropList.h"
898 #undef CSS_PROP_SVG
901 static const PropertyCheckData SVGResetCheckProperties[] = {
902 #define CSS_PROP_SVGRESET(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
903 { offsetof(nsRuleData##datastruct_, member_), type_ },
904 #include "nsCSSPropList.h"
905 #undef CSS_PROP_SVGRESET
907 #endif
909 static const PropertyCheckData ColumnCheckProperties[] = {
910 #define CSS_PROP_COLUMN(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
911 { offsetof(nsRuleData##datastruct_, member_), type_ },
912 #include "nsCSSPropList.h"
913 #undef CSS_PROP_COLUMN
916 #undef CSS_PROP_INCLUDE_NOT_CSS
918 static const StructCheckData gCheckProperties[] = {
920 #define STYLE_STRUCT(name, checkdata_cb, ctor_args) \
921 {name##CheckProperties, \
922 sizeof(name##CheckProperties)/sizeof(PropertyCheckData), \
923 checkdata_cb},
924 #include "nsStyleStructList.h"
925 #undef STYLE_STRUCT
926 {nsnull, 0, nsnull}
932 // XXXldb Taking the address of a reference is evil.
934 inline const nsCSSValue&
935 ValueAtOffset(const nsRuleDataStruct& aRuleDataStruct, size_t aOffset)
937 return * reinterpret_cast<const nsCSSValue*>
938 (reinterpret_cast<const char*>(&aRuleDataStruct) + aOffset);
941 inline const nsCSSRect*
942 RectAtOffset(const nsRuleDataStruct& aRuleDataStruct, size_t aOffset)
944 return reinterpret_cast<const nsCSSRect*>
945 (reinterpret_cast<const char*>(&aRuleDataStruct) + aOffset);
948 inline const nsCSSValuePair*
949 ValuePairAtOffset(const nsRuleDataStruct& aRuleDataStruct, size_t aOffset)
951 return reinterpret_cast<const nsCSSValuePair*>
952 (reinterpret_cast<const char*>(&aRuleDataStruct) + aOffset);
955 inline const nsCSSValueList*
956 ValueListAtOffset(const nsRuleDataStruct& aRuleDataStruct, size_t aOffset)
958 return * reinterpret_cast<const nsCSSValueList*const*>
959 (reinterpret_cast<const char*>(&aRuleDataStruct) + aOffset);
962 inline const nsCSSValueList**
963 ValueListArrayAtOffset(const nsRuleDataStruct& aRuleDataStruct, size_t aOffset)
965 return * reinterpret_cast<const nsCSSValueList**const*>
966 (reinterpret_cast<const char*>(&aRuleDataStruct) + aOffset);
969 inline const nsCSSValuePairList*
970 ValuePairListAtOffset(const nsRuleDataStruct& aRuleDataStruct, size_t aOffset)
972 return * reinterpret_cast<const nsCSSValuePairList*const*>
973 (reinterpret_cast<const char*>(&aRuleDataStruct) + aOffset);
976 #if defined(MOZ_MATHML) && defined(DEBUG)
977 static PRBool
978 AreAllMathMLPropertiesUndefined(const nsCSSFont& aRuleData)
980 return aRuleData.mScriptLevel.GetUnit() == eCSSUnit_Null &&
981 aRuleData.mScriptSizeMultiplier.GetUnit() == eCSSUnit_Null &&
982 aRuleData.mScriptMinSize.GetUnit() == eCSSUnit_Null;
984 #endif
986 inline nsRuleNode::RuleDetail
987 nsRuleNode::CheckSpecifiedProperties(const nsStyleStructID aSID,
988 const nsRuleDataStruct& aRuleDataStruct)
990 const StructCheckData *structData = gCheckProperties + aSID;
992 // Build a count of the:
993 PRUint32 total = 0, // total number of props in the struct
994 specified = 0, // number that were specified for this node
995 inherited = 0; // number that were 'inherit' (and not
996 // eCSSUnit_Inherit) for this node
998 for (const PropertyCheckData *prop = structData->props,
999 *prop_end = prop + structData->nprops;
1000 prop != prop_end;
1001 ++prop)
1002 switch (prop->type) {
1004 case eCSSType_Value:
1005 ++total;
1006 ExamineCSSValue(ValueAtOffset(aRuleDataStruct, prop->offset),
1007 specified, inherited);
1008 break;
1010 case eCSSType_Rect:
1011 total += 4;
1012 ExamineCSSRect(RectAtOffset(aRuleDataStruct, prop->offset),
1013 specified, inherited);
1014 break;
1016 case eCSSType_ValuePair:
1017 total += 2;
1018 ExamineCSSValuePair(ValuePairAtOffset(aRuleDataStruct, prop->offset),
1019 specified, inherited);
1020 break;
1022 case eCSSType_ValueList:
1024 ++total;
1025 const nsCSSValueList* valueList =
1026 ValueListAtOffset(aRuleDataStruct, prop->offset);
1027 if (valueList) {
1028 ++specified;
1029 if (eCSSUnit_Inherit == valueList->mValue.GetUnit()) {
1030 ++inherited;
1034 break;
1036 case eCSSType_ValuePairList:
1038 ++total;
1039 const nsCSSValuePairList* quotes =
1040 ValuePairListAtOffset(aRuleDataStruct, prop->offset);
1041 if (quotes) {
1042 ++specified;
1043 if (eCSSUnit_Inherit == quotes->mXValue.GetUnit()) {
1044 ++inherited;
1048 break;
1050 default:
1051 NS_NOTREACHED("unknown type");
1052 break;
1056 #if 0
1057 printf("CheckSpecifiedProperties: SID=%d total=%d spec=%d inh=%d.\n",
1058 aSID, total, specified, inherited);
1059 #endif
1061 #ifdef MOZ_MATHML
1062 NS_ASSERTION(aSID != eStyleStruct_Font ||
1063 mPresContext->Document()->GetMathMLEnabled() ||
1064 AreAllMathMLPropertiesUndefined(static_cast<const nsCSSFont&>(aRuleDataStruct)),
1065 "MathML style property was defined even though MathML is disabled");
1066 #endif
1069 * Return the most specific information we can: prefer None or Full
1070 * over Partial, and Reset or Inherited over Mixed, since we can
1071 * optimize based on the edge cases and not the in-between cases.
1073 nsRuleNode::RuleDetail result;
1074 if (inherited == total)
1075 result = eRuleFullInherited;
1076 else if (specified == total
1077 #ifdef MOZ_MATHML
1078 // MathML defines 3 properties in Font that will never be set when
1079 // MathML is not in use. Therefore if all but three
1080 // properties have been set, and MathML is not enabled, we can treat
1081 // this as fully specified. Code in nsMathMLElementFactory will
1082 // rebuild the rule tree and style data when MathML is first enabled
1083 // (see nsMathMLElement::BindToTree).
1084 || (aSID == eStyleStruct_Font && specified + 3 == total &&
1085 !mPresContext->Document()->GetMathMLEnabled())
1086 #endif
1088 if (inherited == 0)
1089 result = eRuleFullReset;
1090 else
1091 result = eRuleFullMixed;
1092 } else if (specified == 0)
1093 result = eRuleNone;
1094 else if (specified == inherited)
1095 result = eRulePartialInherited;
1096 else if (inherited == 0)
1097 result = eRulePartialReset;
1098 else
1099 result = eRulePartialMixed;
1101 if (structData->callback) {
1102 result = (*structData->callback)(aRuleDataStruct, result);
1105 return result;
1108 const void*
1109 nsRuleNode::GetDisplayData(nsStyleContext* aContext)
1111 nsRuleDataDisplay displayData; // Declare a struct with null CSS values.
1112 nsRuleData ruleData(NS_STYLE_INHERIT_BIT(Display), mPresContext, aContext);
1113 ruleData.mDisplayData = &displayData;
1115 return WalkRuleTree(eStyleStruct_Display, aContext, &ruleData, &displayData);
1118 const void*
1119 nsRuleNode::GetVisibilityData(nsStyleContext* aContext)
1121 nsRuleDataDisplay displayData; // Declare a struct with null CSS values.
1122 nsRuleData ruleData(NS_STYLE_INHERIT_BIT(Visibility), mPresContext, aContext);
1123 ruleData.mDisplayData = &displayData;
1125 return WalkRuleTree(eStyleStruct_Visibility, aContext, &ruleData, &displayData);
1128 const void*
1129 nsRuleNode::GetTextData(nsStyleContext* aContext)
1131 nsRuleDataText textData; // Declare a struct with null CSS values.
1132 nsRuleData ruleData(NS_STYLE_INHERIT_BIT(Text), mPresContext, aContext);
1133 ruleData.mTextData = &textData;
1135 const void* res = WalkRuleTree(eStyleStruct_Text, aContext, &ruleData, &textData);
1136 textData.mTextShadow = nsnull; // We are sharing with some style rule. It really owns the data.
1137 return res;
1140 const void*
1141 nsRuleNode::GetTextResetData(nsStyleContext* aContext)
1143 nsRuleDataText textData; // Declare a struct with null CSS values.
1144 nsRuleData ruleData(NS_STYLE_INHERIT_BIT(TextReset), mPresContext, aContext);
1145 ruleData.mTextData = &textData;
1147 return WalkRuleTree(eStyleStruct_TextReset, aContext, &ruleData, &textData);
1150 const void*
1151 nsRuleNode::GetUserInterfaceData(nsStyleContext* aContext)
1153 nsRuleDataUserInterface uiData; // Declare a struct with null CSS values.
1154 nsRuleData ruleData(NS_STYLE_INHERIT_BIT(UserInterface), mPresContext, aContext);
1155 ruleData.mUserInterfaceData = &uiData;
1157 const void* res = WalkRuleTree(eStyleStruct_UserInterface, aContext, &ruleData, &uiData);
1158 uiData.mCursor = nsnull; // We are sharing with some style rule. It really owns the data.
1159 return res;
1162 const void*
1163 nsRuleNode::GetUIResetData(nsStyleContext* aContext)
1165 nsRuleDataUserInterface uiData; // Declare a struct with null CSS values.
1166 nsRuleData ruleData(NS_STYLE_INHERIT_BIT(UIReset), mPresContext, aContext);
1167 ruleData.mUserInterfaceData = &uiData;
1169 const void* res = WalkRuleTree(eStyleStruct_UIReset, aContext, &ruleData, &uiData);
1170 return res;
1173 const void*
1174 nsRuleNode::GetFontData(nsStyleContext* aContext)
1176 nsRuleDataFont fontData; // Declare a struct with null CSS values.
1177 nsRuleData ruleData(NS_STYLE_INHERIT_BIT(Font), mPresContext, aContext);
1178 ruleData.mFontData = &fontData;
1180 return WalkRuleTree(eStyleStruct_Font, aContext, &ruleData, &fontData);
1183 const void*
1184 nsRuleNode::GetColorData(nsStyleContext* aContext)
1186 nsRuleDataColor colorData; // Declare a struct with null CSS values.
1187 nsRuleData ruleData(NS_STYLE_INHERIT_BIT(Color), mPresContext, aContext);
1188 ruleData.mColorData = &colorData;
1190 return WalkRuleTree(eStyleStruct_Color, aContext, &ruleData, &colorData);
1193 const void*
1194 nsRuleNode::GetBackgroundData(nsStyleContext* aContext)
1196 nsRuleDataColor colorData; // Declare a struct with null CSS values.
1197 nsRuleData ruleData(NS_STYLE_INHERIT_BIT(Background), mPresContext, aContext);
1198 ruleData.mColorData = &colorData;
1200 // If any members need to be set to null here, they must also be set to
1201 // null in HasAuthorSpecifiedRules (look at mBoxShadow in GetBorderData
1202 // and HasAuthorSpecifiedRules).
1204 return WalkRuleTree(eStyleStruct_Background, aContext, &ruleData, &colorData);
1207 const void*
1208 nsRuleNode::GetMarginData(nsStyleContext* aContext)
1210 nsRuleDataMargin marginData; // Declare a struct with null CSS values.
1211 nsRuleData ruleData(NS_STYLE_INHERIT_BIT(Margin), mPresContext, aContext);
1212 ruleData.mMarginData = &marginData;
1214 return WalkRuleTree(eStyleStruct_Margin, aContext, &ruleData, &marginData);
1217 const void*
1218 nsRuleNode::GetBorderData(nsStyleContext* aContext)
1220 nsRuleDataMargin marginData; // Declare a struct with null CSS values.
1221 nsRuleData ruleData(NS_STYLE_INHERIT_BIT(Border), mPresContext, aContext);
1222 ruleData.mMarginData = &marginData;
1224 const void* res = WalkRuleTree(eStyleStruct_Border, aContext, &ruleData, &marginData);
1225 // We are sharing with some style rule. It really owns the data.
1226 // This nulling must also happen in HasAuthorSpecifiedRules.
1227 marginData.mBoxShadow = nsnull;
1228 return res;
1231 const void*
1232 nsRuleNode::GetPaddingData(nsStyleContext* aContext)
1234 nsRuleDataMargin marginData; // Declare a struct with null CSS values.
1235 nsRuleData ruleData(NS_STYLE_INHERIT_BIT(Padding), mPresContext, aContext);
1236 ruleData.mMarginData = &marginData;
1238 // If any members need to be set to null here, they must also be set to
1239 // null in HasAuthorSpecifiedRules (look at mBoxShadow in GetBorderData
1240 // and HasAuthorSpecifiedRules).
1242 return WalkRuleTree(eStyleStruct_Padding, aContext, &ruleData, &marginData);
1245 const void*
1246 nsRuleNode::GetOutlineData(nsStyleContext* aContext)
1248 nsRuleDataMargin marginData; // Declare a struct with null CSS values.
1249 nsRuleData ruleData(NS_STYLE_INHERIT_BIT(Outline), mPresContext, aContext);
1250 ruleData.mMarginData = &marginData;
1252 return WalkRuleTree(eStyleStruct_Outline, aContext, &ruleData, &marginData);
1255 const void*
1256 nsRuleNode::GetListData(nsStyleContext* aContext)
1258 nsRuleDataList listData; // Declare a struct with null CSS values.
1259 nsRuleData ruleData(NS_STYLE_INHERIT_BIT(List), mPresContext, aContext);
1260 ruleData.mListData = &listData;
1262 return WalkRuleTree(eStyleStruct_List, aContext, &ruleData, &listData);
1265 const void*
1266 nsRuleNode::GetPositionData(nsStyleContext* aContext)
1268 nsRuleDataPosition posData; // Declare a struct with null CSS values.
1269 nsRuleData ruleData(NS_STYLE_INHERIT_BIT(Position), mPresContext, aContext);
1270 ruleData.mPositionData = &posData;
1272 return WalkRuleTree(eStyleStruct_Position, aContext, &ruleData, &posData);
1275 const void*
1276 nsRuleNode::GetTableData(nsStyleContext* aContext)
1278 nsRuleDataTable tableData; // Declare a struct with null CSS values.
1279 nsRuleData ruleData(NS_STYLE_INHERIT_BIT(Table), mPresContext, aContext);
1280 ruleData.mTableData = &tableData;
1282 return WalkRuleTree(eStyleStruct_Table, aContext, &ruleData, &tableData);
1285 const void*
1286 nsRuleNode::GetTableBorderData(nsStyleContext* aContext)
1288 nsRuleDataTable tableData; // Declare a struct with null CSS values.
1289 nsRuleData ruleData(NS_STYLE_INHERIT_BIT(TableBorder), mPresContext, aContext);
1290 ruleData.mTableData = &tableData;
1292 return WalkRuleTree(eStyleStruct_TableBorder, aContext, &ruleData, &tableData);
1295 const void*
1296 nsRuleNode::GetContentData(nsStyleContext* aContext)
1298 nsRuleDataContent contentData; // Declare a struct with null CSS values.
1299 nsRuleData ruleData(NS_STYLE_INHERIT_BIT(Content), mPresContext, aContext);
1300 ruleData.mContentData = &contentData;
1302 const void* res = WalkRuleTree(eStyleStruct_Content, aContext, &ruleData, &contentData);
1303 contentData.mCounterIncrement = contentData.mCounterReset = nsnull;
1304 contentData.mContent = nsnull; // We are sharing with some style rule. It really owns the data.
1305 return res;
1308 const void*
1309 nsRuleNode::GetQuotesData(nsStyleContext* aContext)
1311 nsRuleDataContent contentData; // Declare a struct with null CSS values.
1312 nsRuleData ruleData(NS_STYLE_INHERIT_BIT(Quotes), mPresContext, aContext);
1313 ruleData.mContentData = &contentData;
1315 const void* res = WalkRuleTree(eStyleStruct_Quotes, aContext, &ruleData, &contentData);
1316 contentData.mQuotes = nsnull; // We are sharing with some style rule. It really owns the data.
1317 return res;
1320 const void*
1321 nsRuleNode::GetXULData(nsStyleContext* aContext)
1323 nsRuleDataXUL xulData; // Declare a struct with null CSS values.
1324 nsRuleData ruleData(NS_STYLE_INHERIT_BIT(XUL), mPresContext, aContext);
1325 ruleData.mXULData = &xulData;
1327 return WalkRuleTree(eStyleStruct_XUL, aContext, &ruleData, &xulData);
1330 const void*
1331 nsRuleNode::GetColumnData(nsStyleContext* aContext)
1333 nsRuleDataColumn columnData; // Declare a struct with null CSS values.
1334 nsRuleData ruleData(NS_STYLE_INHERIT_BIT(Column), mPresContext, aContext);
1335 ruleData.mColumnData = &columnData;
1337 return WalkRuleTree(eStyleStruct_Column, aContext, &ruleData, &columnData);
1340 #ifdef MOZ_SVG
1341 const void*
1342 nsRuleNode::GetSVGData(nsStyleContext* aContext)
1344 nsRuleDataSVG svgData; // Declare a struct with null CSS values.
1345 nsRuleData ruleData(NS_STYLE_INHERIT_BIT(SVG), mPresContext, aContext);
1346 ruleData.mSVGData = &svgData;
1348 const void *res = WalkRuleTree(eStyleStruct_SVG, aContext, &ruleData, &svgData);
1349 svgData.mStrokeDasharray = nsnull; // We are sharing with some style rule. It really owns the data.
1350 return res;
1353 const void*
1354 nsRuleNode::GetSVGResetData(nsStyleContext* aContext)
1356 nsRuleDataSVG svgData; // Declare a struct with null CSS values.
1357 nsRuleData ruleData(NS_STYLE_INHERIT_BIT(SVGReset), mPresContext, aContext);
1358 ruleData.mSVGData = &svgData;
1360 return WalkRuleTree(eStyleStruct_SVGReset, aContext, &ruleData, &svgData);
1362 #endif
1364 const void*
1365 nsRuleNode::WalkRuleTree(const nsStyleStructID aSID,
1366 nsStyleContext* aContext,
1367 nsRuleData* aRuleData,
1368 nsRuleDataStruct* aSpecificData)
1370 // We start at the most specific rule in the tree.
1371 void* startStruct = nsnull;
1373 nsRuleNode* ruleNode = this;
1374 nsRuleNode* highestNode = nsnull; // The highest node in the rule tree
1375 // that has the same properties
1376 // specified for struct |aSID| as
1377 // |this| does.
1378 nsRuleNode* rootNode = this; // After the loop below, this will be the
1379 // highest node that we've walked without
1380 // finding cached data on the rule tree.
1381 // If we don't find any cached data, it
1382 // will be the root. (XXX misnamed)
1383 RuleDetail detail = eRuleNone;
1384 PRUint32 bit = nsCachedStyleData::GetBitForSID(aSID);
1386 while (ruleNode) {
1387 // See if this rule node has cached the fact that the remaining
1388 // nodes along this path specify no data whatsoever.
1389 if (ruleNode->mNoneBits & bit)
1390 break;
1392 // If the dependent bit is set on a rule node for this struct, that
1393 // means its rule won't have any information to add, so skip it.
1394 // XXXldb I don't understand why we need to check |detail| here, but
1395 // we do.
1396 if (detail == eRuleNone)
1397 while (ruleNode->mDependentBits & bit) {
1398 NS_ASSERTION(ruleNode->mStyleData.GetStyleData(aSID) == nsnull,
1399 "dependent bit with cached data makes no sense");
1400 // Climb up to the next rule in the tree (a less specific rule).
1401 rootNode = ruleNode;
1402 ruleNode = ruleNode->mParent;
1403 NS_ASSERTION(!(ruleNode->mNoneBits & bit), "can't have both bits set");
1406 // Check for cached data after the inner loop above -- otherwise
1407 // we'll miss it.
1408 startStruct = ruleNode->mStyleData.GetStyleData(aSID);
1409 if (startStruct)
1410 break; // We found a rule with fully specified data. We don't
1411 // need to go up the tree any further, since the remainder
1412 // of this branch has already been computed.
1414 // Ask the rule to fill in the properties that it specifies.
1415 nsIStyleRule *rule = ruleNode->mRule;
1416 if (rule) {
1417 aRuleData->mLevel = ruleNode->GetLevel();
1418 aRuleData->mIsImportantRule = ruleNode->IsImportantRule();
1419 rule->MapRuleInfoInto(aRuleData);
1422 // Now we check to see how many properties have been specified by
1423 // the rules we've examined so far.
1424 RuleDetail oldDetail = detail;
1425 detail = CheckSpecifiedProperties(aSID, *aSpecificData);
1427 if (oldDetail == eRuleNone && detail != eRuleNone)
1428 highestNode = ruleNode;
1430 if (detail == eRuleFullReset ||
1431 detail == eRuleFullMixed ||
1432 detail == eRuleFullInherited)
1433 break; // We don't need to examine any more rules. All properties
1434 // have been fully specified.
1436 // Climb up to the next rule in the tree (a less specific rule).
1437 rootNode = ruleNode;
1438 ruleNode = ruleNode->mParent;
1441 NS_ASSERTION(!startStruct || (detail != eRuleFullReset &&
1442 detail != eRuleFullMixed &&
1443 detail != eRuleFullInherited),
1444 "can't have start struct and be fully specified");
1446 PRBool isReset = nsCachedStyleData::IsReset(aSID);
1447 if (!highestNode)
1448 highestNode = rootNode;
1450 if (!aRuleData->mCanStoreInRuleTree)
1451 detail = eRulePartialMixed; // Treat as though some data is specified to avoid
1452 // the optimizations and force data computation.
1454 if (detail == eRuleNone && startStruct && !aRuleData->mPostResolveCallback) {
1455 // We specified absolutely no rule information, but a parent rule in the tree
1456 // specified all the rule information. We set a bit along the branch from our
1457 // node in the tree to the node that specified the data that tells nodes on that
1458 // branch that they never need to examine their rules for this particular struct type
1459 // ever again.
1460 PropagateDependentBit(bit, ruleNode);
1461 return startStruct;
1463 // FIXME Do we need to check for mPostResolveCallback?
1464 if ((!startStruct && !isReset &&
1465 (detail == eRuleNone || detail == eRulePartialInherited)) ||
1466 detail == eRuleFullInherited) {
1467 // We specified no non-inherited information and neither did any of
1468 // our parent rules.
1470 // We set a bit along the branch from the highest node (ruleNode)
1471 // down to our node (this) indicating that no non-inherited data was
1472 // specified. This bit is guaranteed to be set already on the path
1473 // from the highest node to the root node in the case where
1474 // (detail == eRuleNone), which is the most common case here.
1475 // We must check |!isReset| because the Compute*Data functions for
1476 // reset structs wouldn't handle none bits correctly.
1477 if (highestNode != this && !isReset)
1478 PropagateNoneBit(bit, highestNode);
1480 // All information must necessarily be inherited from our parent style context.
1481 // In the absence of any computed data in the rule tree and with
1482 // no rules specified that didn't have values of 'inherit', we should check our parent.
1483 nsStyleContext* parentContext = aContext->GetParent();
1484 if (parentContext) {
1485 // We have a parent, and so we should just inherit from the parent.
1486 // Set the inherit bits on our context. These bits tell the style context that
1487 // it never has to go back to the rule tree for data. Instead the style context tree
1488 // should be walked to find the data.
1489 const void* parentStruct = parentContext->GetStyleData(aSID);
1490 aContext->AddStyleBit(bit); // makes const_cast OK.
1491 aContext->SetStyle(aSID, const_cast<void*>(parentStruct));
1492 return parentStruct;
1494 else
1495 // We are the root. In the case of fonts, the default values just
1496 // come from the pres context.
1497 return SetDefaultOnRoot(aSID, aContext);
1500 // We need to compute the data from the information that the rules specified.
1501 const void* res;
1502 #define STYLE_STRUCT_TEST aSID
1503 #define STYLE_STRUCT(name, checkdata_cb, ctor_args) \
1504 res = Compute##name##Data(startStruct, *aSpecificData, aContext, \
1505 highestNode, detail, !aRuleData->mCanStoreInRuleTree);
1506 #include "nsStyleStructList.h"
1507 #undef STYLE_STRUCT
1508 #undef STYLE_STRUCT_TEST
1510 // If we have a post-resolve callback, handle that now.
1511 if (aRuleData->mPostResolveCallback && (NS_LIKELY(res != nsnull)))
1512 (*aRuleData->mPostResolveCallback)(const_cast<void*>(res), aRuleData);
1514 // Now return the result.
1515 return res;
1518 const void*
1519 nsRuleNode::SetDefaultOnRoot(const nsStyleStructID aSID, nsStyleContext* aContext)
1521 switch (aSID) {
1522 case eStyleStruct_Font:
1524 nsStyleFont* fontData = new (mPresContext) nsStyleFont(mPresContext);
1525 if (NS_LIKELY(fontData != nsnull)) {
1526 nscoord minimumFontSize =
1527 mPresContext->GetCachedIntPref(kPresContext_MinimumFontSize);
1529 if (minimumFontSize > 0 && !mPresContext->IsChrome()) {
1530 fontData->mFont.size = PR_MAX(fontData->mSize, minimumFontSize);
1532 else {
1533 fontData->mFont.size = fontData->mSize;
1535 aContext->SetStyle(eStyleStruct_Font, fontData);
1537 return fontData;
1539 case eStyleStruct_Display:
1541 nsStyleDisplay* disp = new (mPresContext) nsStyleDisplay();
1542 if (NS_LIKELY(disp != nsnull)) {
1543 aContext->SetStyle(eStyleStruct_Display, disp);
1545 return disp;
1547 case eStyleStruct_Visibility:
1549 nsStyleVisibility* vis = new (mPresContext) nsStyleVisibility(mPresContext);
1550 if (NS_LIKELY(vis != nsnull)) {
1551 aContext->SetStyle(eStyleStruct_Visibility, vis);
1553 return vis;
1555 case eStyleStruct_Text:
1557 nsStyleText* text = new (mPresContext) nsStyleText();
1558 if (NS_LIKELY(text != nsnull)) {
1559 aContext->SetStyle(eStyleStruct_Text, text);
1561 return text;
1563 case eStyleStruct_TextReset:
1565 nsStyleTextReset* text = new (mPresContext) nsStyleTextReset();
1566 if (NS_LIKELY(text != nsnull)) {
1567 aContext->SetStyle(eStyleStruct_TextReset, text);
1569 return text;
1571 case eStyleStruct_Color:
1573 nsStyleColor* color = new (mPresContext) nsStyleColor(mPresContext);
1574 if (NS_LIKELY(color != nsnull)) {
1575 aContext->SetStyle(eStyleStruct_Color, color);
1577 return color;
1579 case eStyleStruct_Background:
1581 nsStyleBackground* bg = new (mPresContext) nsStyleBackground(mPresContext);
1582 if (NS_LIKELY(bg != nsnull)) {
1583 aContext->SetStyle(eStyleStruct_Background, bg);
1585 return bg;
1587 case eStyleStruct_Margin:
1589 nsStyleMargin* margin = new (mPresContext) nsStyleMargin();
1590 if (NS_LIKELY(margin != nsnull)) {
1591 aContext->SetStyle(eStyleStruct_Margin, margin);
1593 return margin;
1595 case eStyleStruct_Border:
1597 nsStyleBorder* border = new (mPresContext) nsStyleBorder(mPresContext);
1598 if (NS_LIKELY(border != nsnull)) {
1599 aContext->SetStyle(eStyleStruct_Border, border);
1601 return border;
1603 case eStyleStruct_Padding:
1605 nsStylePadding* padding = new (mPresContext) nsStylePadding();
1606 if (NS_LIKELY(padding != nsnull)) {
1607 aContext->SetStyle(eStyleStruct_Padding, padding);
1609 return padding;
1611 case eStyleStruct_Outline:
1613 nsStyleOutline* outline = new (mPresContext) nsStyleOutline(mPresContext);
1614 if (NS_LIKELY(outline != nsnull)) {
1615 aContext->SetStyle(eStyleStruct_Outline, outline);
1617 return outline;
1619 case eStyleStruct_List:
1621 nsStyleList* list = new (mPresContext) nsStyleList();
1622 if (NS_LIKELY(list != nsnull)) {
1623 aContext->SetStyle(eStyleStruct_List, list);
1625 return list;
1627 case eStyleStruct_Position:
1629 nsStylePosition* pos = new (mPresContext) nsStylePosition();
1630 if (NS_LIKELY(pos != nsnull)) {
1631 aContext->SetStyle(eStyleStruct_Position, pos);
1633 return pos;
1635 case eStyleStruct_Table:
1637 nsStyleTable* table = new (mPresContext) nsStyleTable();
1638 if (NS_LIKELY(table != nsnull)) {
1639 aContext->SetStyle(eStyleStruct_Table, table);
1641 return table;
1643 case eStyleStruct_TableBorder:
1645 nsStyleTableBorder* table = new (mPresContext) nsStyleTableBorder(mPresContext);
1646 if (NS_LIKELY(table != nsnull)) {
1647 aContext->SetStyle(eStyleStruct_TableBorder, table);
1649 return table;
1651 case eStyleStruct_Content:
1653 nsStyleContent* content = new (mPresContext) nsStyleContent();
1654 if (NS_LIKELY(content != nsnull)) {
1655 aContext->SetStyle(eStyleStruct_Content, content);
1657 return content;
1659 case eStyleStruct_Quotes:
1661 nsStyleQuotes* quotes = new (mPresContext) nsStyleQuotes();
1662 if (NS_LIKELY(quotes != nsnull)) {
1663 aContext->SetStyle(eStyleStruct_Quotes, quotes);
1665 return quotes;
1667 case eStyleStruct_UserInterface:
1669 nsStyleUserInterface* ui = new (mPresContext) nsStyleUserInterface();
1670 if (NS_LIKELY(ui != nsnull)) {
1671 aContext->SetStyle(eStyleStruct_UserInterface, ui);
1673 return ui;
1675 case eStyleStruct_UIReset:
1677 nsStyleUIReset* ui = new (mPresContext) nsStyleUIReset();
1678 if (NS_LIKELY(ui != nsnull)) {
1679 aContext->SetStyle(eStyleStruct_UIReset, ui);
1681 return ui;
1684 case eStyleStruct_XUL:
1686 nsStyleXUL* xul = new (mPresContext) nsStyleXUL();
1687 if (NS_LIKELY(xul != nsnull)) {
1688 aContext->SetStyle(eStyleStruct_XUL, xul);
1690 return xul;
1693 case eStyleStruct_Column:
1695 nsStyleColumn* column = new (mPresContext) nsStyleColumn(mPresContext);
1696 if (NS_LIKELY(column != nsnull)) {
1697 aContext->SetStyle(eStyleStruct_Column, column);
1699 return column;
1702 #ifdef MOZ_SVG
1703 case eStyleStruct_SVG:
1705 nsStyleSVG* svg = new (mPresContext) nsStyleSVG();
1706 if (NS_LIKELY(svg != nsnull)) {
1707 aContext->SetStyle(eStyleStruct_SVG, svg);
1709 return svg;
1712 case eStyleStruct_SVGReset:
1714 nsStyleSVGReset* svgReset = new (mPresContext) nsStyleSVGReset();
1715 if (NS_LIKELY(svgReset != nsnull)) {
1716 aContext->SetStyle(eStyleStruct_SVGReset, svgReset);
1718 return svgReset;
1720 #endif
1722 return nsnull;
1726 * This function handles cascading of *-left or *-right box properties
1727 * against *-start (which is L for LTR and R for RTL) or *-end (which is
1728 * R for LTR and L for RTL).
1730 * Cascading these properties correctly is hard because we need to
1731 * cascade two properties as one, but which two properties depends on a
1732 * third property ('direction'). We solve this by treating each of
1733 * these properties (say, 'margin-start') as a shorthand that sets a
1734 * property containing the value of the property specified
1735 * ('margin-start-value') and sets a pair of properties
1736 * ('margin-left-ltr-source' and 'margin-right-rtl-source') saying which
1737 * of the properties we use. Thus, when we want to compute the value of
1738 * 'margin-left' when 'direction' is 'ltr', we look at the value of
1739 * 'margin-left-ltr-source', which tells us whether to use the highest
1740 * 'margin-left' in the cascade or the highest 'margin-start'.
1742 * Finally, since we can compute the normal (*-left and *-right)
1743 * properties in a loop, this function works by modifying the data we
1744 * will use in that loop (which the caller must copy from the const
1745 * input).
1747 void
1748 nsRuleNode::AdjustLogicalBoxProp(nsStyleContext* aContext,
1749 const nsCSSValue& aLTRSource,
1750 const nsCSSValue& aRTLSource,
1751 const nsCSSValue& aLTRLogicalValue,
1752 const nsCSSValue& aRTLLogicalValue,
1753 PRUint8 aSide,
1754 nsCSSRect& aValueRect,
1755 PRBool& aInherited)
1757 PRBool LTRlogical = aLTRSource.GetUnit() == eCSSUnit_Enumerated &&
1758 aLTRSource.GetIntValue() == NS_BOXPROP_SOURCE_LOGICAL;
1759 PRBool RTLlogical = aRTLSource.GetUnit() == eCSSUnit_Enumerated &&
1760 aRTLSource.GetIntValue() == NS_BOXPROP_SOURCE_LOGICAL;
1761 if (LTRlogical || RTLlogical) {
1762 // We can't cache anything on the rule tree if we use any data from
1763 // the style context, since data cached in the rule tree could be
1764 // used with a style context with a different value.
1765 aInherited = PR_TRUE;
1766 PRUint8 dir = aContext->GetStyleVisibility()->mDirection;
1768 if (dir == NS_STYLE_DIRECTION_LTR) {
1769 if (LTRlogical)
1770 aValueRect.*(nsCSSRect::sides[aSide]) = aLTRLogicalValue;
1771 } else {
1772 if (RTLlogical)
1773 aValueRect.*(nsCSSRect::sides[aSide]) = aRTLLogicalValue;
1779 * Begin an nsRuleNode::Compute*Data function for an inherited struct.
1781 * @param type_ The nsStyle* type this function computes.
1782 * @param ctorargs_ The arguments used for the default nsStyle* constructor.
1783 * @param data_ Variable (declared here) holding the result of this
1784 * function.
1785 * @param parentdata_ Variable (declared here) holding the parent style
1786 * context's data for this struct.
1787 * @param rdtype_ The nsCSS* struct type used to compute this struct's data.
1788 * @param rdata_ Variable (declared here) holding the nsCSS* used here.
1790 #define COMPUTE_START_INHERITED(type_, ctorargs_, data_, parentdata_, rdtype_, rdata_) \
1791 NS_ASSERTION(aRuleDetail != eRuleFullInherited, \
1792 "should not have bothered calling Compute*Data"); \
1794 nsStyleContext* parentContext = aContext->GetParent(); \
1796 const nsRuleData##rdtype_& rdata_ = \
1797 static_cast<const nsRuleData##rdtype_&>(aData); \
1798 nsStyle##type_* data_ = nsnull; \
1799 const nsStyle##type_* parentdata_ = nsnull; \
1800 PRBool inherited = aInherited; \
1802 /* If |inherited| might be false by the time we're done, we can't call */ \
1803 /* parentContext->GetStyle##type_() since it could recur into setting */ \
1804 /* the same struct on the same rule node, causing a leak. */ \
1805 if (parentContext && aRuleDetail != eRuleFullReset && \
1806 (!aStartStruct || (aRuleDetail != eRulePartialReset && \
1807 aRuleDetail != eRuleNone))) \
1808 parentdata_ = parentContext->GetStyle##type_(); \
1809 if (aStartStruct) \
1810 /* We only need to compute the delta between this computed data and */ \
1811 /* our computed data. */ \
1812 data_ = new (mPresContext) \
1813 nsStyle##type_(*static_cast<nsStyle##type_*>(aStartStruct)); \
1814 else { \
1815 if (aRuleDetail != eRuleFullMixed && aRuleDetail != eRuleFullReset) { \
1816 /* No question. We will have to inherit. Go ahead and init */ \
1817 /* with inherited vals from parent. */ \
1818 inherited = PR_TRUE; \
1819 if (parentdata_) \
1820 data_ = new (mPresContext) nsStyle##type_(*parentdata_); \
1821 else \
1822 data_ = new (mPresContext) nsStyle##type_ ctorargs_; \
1824 else \
1825 data_ = new (mPresContext) nsStyle##type_ ctorargs_; \
1828 if (NS_UNLIKELY(!data_)) \
1829 return nsnull; /* Out Of Memory */ \
1830 if (!parentdata_) \
1831 parentdata_ = data_;
1834 * Begin an nsRuleNode::Compute*Data function for a reset struct.
1836 * @param type_ The nsStyle* type this function computes.
1837 * @param ctorargs_ The arguments used for the default nsStyle* constructor.
1838 * @param data_ Variable (declared here) holding the result of this
1839 * function.
1840 * @param parentdata_ Variable (declared here) holding the parent style
1841 * context's data for this struct.
1842 * @param rdtype_ The nsCSS* struct type used to compute this struct's data.
1843 * @param rdata_ Variable (declared here) holding the nsCSS* used here.
1845 #define COMPUTE_START_RESET(type_, ctorargs_, data_, parentdata_, rdtype_, rdata_) \
1846 NS_ASSERTION(aRuleDetail != eRuleFullInherited, \
1847 "should not have bothered calling Compute*Data"); \
1849 nsStyleContext* parentContext = aContext->GetParent(); \
1850 if (parentContext && \
1851 parentContext->GetPseudoType() == nsCSSPseudoElements::firstLine) { \
1852 /* Reset structs don't inherit from first-line */ \
1853 parentContext = parentContext->GetParent(); \
1856 const nsRuleData##rdtype_& rdata_ = \
1857 static_cast<const nsRuleData##rdtype_&>(aData); \
1858 nsStyle##type_* data_; \
1859 if (aStartStruct) \
1860 /* We only need to compute the delta between this computed data and */ \
1861 /* our computed data. */ \
1862 data_ = new (mPresContext) \
1863 nsStyle##type_(*static_cast<nsStyle##type_*>(aStartStruct)); \
1864 else \
1865 data_ = new (mPresContext) nsStyle##type_ ctorargs_; \
1867 if (NS_UNLIKELY(!data_)) \
1868 return nsnull; /* Out Of Memory */ \
1870 /* If |inherited| might be false by the time we're done, we can't call */ \
1871 /* parentContext->GetStyle##type_() since it could recur into setting */ \
1872 /* the same struct on the same rule node, causing a leak. */ \
1873 const nsStyle##type_* parentdata_ = data_; \
1874 if (parentContext && \
1875 aRuleDetail != eRuleFullReset && \
1876 aRuleDetail != eRulePartialReset && \
1877 aRuleDetail != eRuleNone) \
1878 parentdata_ = parentContext->GetStyle##type_(); \
1879 PRBool inherited = aInherited;
1882 * Begin an nsRuleNode::Compute*Data function for an inherited struct.
1884 * @param type_ The nsStyle* type this function computes.
1885 * @param data_ Variable holding the result of this function.
1887 #define COMPUTE_END_INHERITED(type_, data_) \
1888 if (inherited) \
1889 /* We inherited, and therefore can't be cached in the rule node. We */ \
1890 /* have to be put right on the style context. */ \
1891 aContext->SetStyle(eStyleStruct_##type_, data_); \
1892 else { \
1893 /* We were fully specified and can therefore be cached right on the */ \
1894 /* rule node. */ \
1895 if (!aHighestNode->mStyleData.mInheritedData) { \
1896 aHighestNode->mStyleData.mInheritedData = \
1897 new (mPresContext) nsInheritedStyleData; \
1898 if (NS_UNLIKELY(!aHighestNode->mStyleData.mInheritedData)) { \
1899 data_->Destroy(mPresContext); \
1900 return nsnull; \
1903 aHighestNode->mStyleData.mInheritedData->m##type_##Data = data_; \
1904 /* Propagate the bit down. */ \
1905 PropagateDependentBit(NS_STYLE_INHERIT_BIT(type_), aHighestNode); \
1908 return data_;
1911 * Begin an nsRuleNode::Compute*Data function for a reset struct.
1913 * @param type_ The nsStyle* type this function computes.
1914 * @param data_ Variable holding the result of this function.
1916 #define COMPUTE_END_RESET(type_, data_) \
1917 if (inherited) \
1918 /* We inherited, and therefore can't be cached in the rule node. We */ \
1919 /* have to be put right on the style context. */ \
1920 aContext->SetStyle(eStyleStruct_##type_, data_); \
1921 else { \
1922 /* We were fully specified and can therefore be cached right on the */ \
1923 /* rule node. */ \
1924 if (!aHighestNode->mStyleData.mResetData) { \
1925 aHighestNode->mStyleData.mResetData = \
1926 new (mPresContext) nsResetStyleData; \
1927 if (NS_UNLIKELY(!aHighestNode->mStyleData.mResetData)) { \
1928 data_->Destroy(mPresContext); \
1929 return nsnull; \
1932 aHighestNode->mStyleData.mResetData->m##type_##Data = data_; \
1933 /* Propagate the bit down. */ \
1934 PropagateDependentBit(NS_STYLE_INHERIT_BIT(type_), aHighestNode); \
1937 return data_;
1939 #ifdef MOZ_MATHML
1940 // This function figures out how much scaling should be suppressed to
1941 // satisfy scriptminsize. This is our attempt to implement
1942 // http://www.w3.org/TR/MathML2/chapter3.html#id.3.3.4.2.2
1943 // This is called after mScriptLevel, mScriptMinSize and mScriptSizeMultiplier
1944 // have been set in aFont.
1946 // Here are the invariants we enforce:
1947 // 1) A decrease in size must not reduce the size below minscriptsize.
1948 // 2) An increase in size must not increase the size above the size we would
1949 // have if minscriptsize had not been applied anywhere.
1950 // 3) The scriptlevel-induced size change must between 1.0 and the parent's
1951 // scriptsizemultiplier^(new script level - old script level), as close to the
1952 // latter as possible subject to constraints 1 and 2.
1953 static nscoord
1954 ComputeScriptLevelSize(const nsStyleFont* aFont, const nsStyleFont* aParentFont,
1955 nsPresContext* aPresContext, nscoord* aUnconstrainedSize)
1957 PRInt32 scriptLevelChange =
1958 aFont->mScriptLevel - aParentFont->mScriptLevel;
1959 if (scriptLevelChange == 0) {
1960 *aUnconstrainedSize = aParentFont->mScriptUnconstrainedSize;
1961 // Constraint #3 says that we cannot change size, and #1 and #2 are always
1962 // satisfied with no change. It's important this be fast because it covers
1963 // all non-MathML content.
1964 return aParentFont->mSize;
1967 // Compute actual value of minScriptSize
1968 nscoord minScriptSize =
1969 nsStyleFont::ZoomText(aPresContext, aParentFont->mScriptMinSize);
1971 double scriptLevelScale =
1972 pow(aParentFont->mScriptSizeMultiplier, scriptLevelChange);
1973 // Compute the size we would have had if minscriptsize had never been
1974 // applied, also prevent overflow (bug 413274)
1975 *aUnconstrainedSize =
1976 NSToCoordRound(PR_MIN(aParentFont->mScriptUnconstrainedSize*scriptLevelScale,
1977 nscoord_MAX));
1978 // Compute the size we could get via scriptlevel change
1979 nscoord scriptLevelSize =
1980 NSToCoordRound(PR_MIN(aParentFont->mSize*scriptLevelScale,
1981 nscoord_MAX));
1982 if (scriptLevelScale <= 1.0) {
1983 if (aParentFont->mSize <= minScriptSize) {
1984 // We can't decrease the font size at all, so just stick to no change
1985 // (authors are allowed to explicitly set the font size smaller than
1986 // minscriptsize)
1987 return aParentFont->mSize;
1989 // We can decrease, so apply constraint #1
1990 return PR_MAX(minScriptSize, scriptLevelSize);
1991 } else {
1992 // scriptminsize can only make sizes larger than the unconstrained size
1993 NS_ASSERTION(*aUnconstrainedSize <= scriptLevelSize, "How can this ever happen?");
1994 // Apply constraint #2
1995 return PR_MIN(scriptLevelSize, PR_MAX(*aUnconstrainedSize, minScriptSize));
1998 #endif
2000 /* static */ void
2001 nsRuleNode::SetFontSize(nsPresContext* aPresContext,
2002 const nsRuleDataFont& aFontData,
2003 const nsStyleFont* aFont,
2004 const nsStyleFont* aParentFont,
2005 nscoord* aSize,
2006 const nsFont& aSystemFont,
2007 nscoord aParentSize,
2008 nscoord aScriptLevelAdjustedParentSize,
2009 PRBool aUsedStartStruct,
2010 PRBool& aInherited)
2012 PRBool zoom = PR_FALSE;
2013 PRInt32 baseSize = (PRInt32) aPresContext->
2014 GetDefaultFont(aFont->mFlags & NS_STYLE_FONT_FACE_MASK)->size;
2015 if (eCSSUnit_Enumerated == aFontData.mSize.GetUnit()) {
2016 PRInt32 value = aFontData.mSize.GetIntValue();
2017 PRInt32 scaler = aPresContext->FontScaler();
2018 float scaleFactor = nsStyleUtil::GetScalingFactor(scaler);
2020 zoom = PR_TRUE;
2021 if ((NS_STYLE_FONT_SIZE_XXSMALL <= value) &&
2022 (value <= NS_STYLE_FONT_SIZE_XXLARGE)) {
2023 *aSize = nsStyleUtil::CalcFontPointSize(value, baseSize,
2024 scaleFactor, aPresContext, eFontSize_CSS);
2026 else if (NS_STYLE_FONT_SIZE_XXXLARGE == value) {
2027 // <font size="7"> is not specified in CSS, so we don't use eFontSize_CSS.
2028 *aSize = nsStyleUtil::CalcFontPointSize(value, baseSize,
2029 scaleFactor, aPresContext);
2031 else if (NS_STYLE_FONT_SIZE_LARGER == value ||
2032 NS_STYLE_FONT_SIZE_SMALLER == value) {
2033 aInherited = PR_TRUE;
2035 // Un-zoom so we use the tables correctly. We'll then rezoom due
2036 // to the |zoom = PR_TRUE| above.
2037 // Note that relative units here use the parent's size unadjusted
2038 // for scriptlevel changes. A scriptlevel change between us and the parent
2039 // is simply ignored.
2040 nscoord parentSize =
2041 nsStyleFont::UnZoomText(aPresContext, aParentSize);
2043 if (NS_STYLE_FONT_SIZE_LARGER == value) {
2044 *aSize = nsStyleUtil::FindNextLargerFontSize(parentSize,
2045 baseSize, scaleFactor, aPresContext, eFontSize_CSS);
2046 NS_ASSERTION(*aSize > parentSize,
2047 "FindNextLargerFontSize failed");
2049 else {
2050 *aSize = nsStyleUtil::FindNextSmallerFontSize(parentSize,
2051 baseSize, scaleFactor, aPresContext, eFontSize_CSS);
2052 NS_ASSERTION(*aSize < parentSize ||
2053 parentSize <= nsPresContext::CSSPixelsToAppUnits(1),
2054 "FindNextSmallerFontSize failed");
2056 } else {
2057 NS_NOTREACHED("unexpected value");
2060 else if (aFontData.mSize.IsLengthUnit()) {
2061 // Note that font-based length units use the parent's size unadjusted
2062 // for scriptlevel changes. A scriptlevel change between us and the parent
2063 // is simply ignored.
2064 *aSize = CalcLengthWith(aFontData.mSize, aParentSize, aParentFont, nsnull,
2065 aPresContext, aInherited);
2066 zoom = aFontData.mSize.IsFixedLengthUnit() ||
2067 aFontData.mSize.GetUnit() == eCSSUnit_Pixel;
2069 else if (eCSSUnit_Percent == aFontData.mSize.GetUnit()) {
2070 aInherited = PR_TRUE;
2071 // Note that % units use the parent's size unadjusted for scriptlevel
2072 // changes. A scriptlevel change between us and the parent is simply
2073 // ignored.
2074 *aSize = NSToCoordRound(aParentSize *
2075 aFontData.mSize.GetPercentValue());
2076 zoom = PR_FALSE;
2078 else if (eCSSUnit_System_Font == aFontData.mSize.GetUnit()) {
2079 // this becomes our cascading size
2080 *aSize = aSystemFont.size;
2081 zoom = PR_TRUE;
2083 else if (eCSSUnit_Inherit == aFontData.mSize.GetUnit()) {
2084 aInherited = PR_TRUE;
2085 // We apply scriptlevel change for this case, because the default is
2086 // to inherit and we don't want explicit "inherit" to differ from the
2087 // default.
2088 *aSize = aScriptLevelAdjustedParentSize;
2089 zoom = PR_FALSE;
2091 else if (eCSSUnit_Initial == aFontData.mSize.GetUnit()) {
2092 // The initial value is 'medium', which has magical sizing based on
2093 // the generic font family, so do that here too.
2094 *aSize = baseSize;
2095 zoom = PR_TRUE;
2096 } else {
2097 NS_ASSERTION(eCSSUnit_Null == aFontData.mSize.GetUnit(),
2098 "What kind of font-size value is this?");
2099 #ifdef MOZ_MATHML
2100 // if aUsedStartStruct is true, then every single property in the
2101 // font struct is being set all at once. This means scriptlevel is not
2102 // going to have any influence on the font size; there is no need to
2103 // do anything here.
2104 if (!aUsedStartStruct && aParentSize != aScriptLevelAdjustedParentSize) {
2105 // There was no rule affecting the size but the size has been
2106 // affected by the parent's size via scriptlevel change. So treat
2107 // this as inherited.
2108 aInherited = PR_TRUE;
2109 *aSize = aScriptLevelAdjustedParentSize;
2111 #endif
2114 // We want to zoom the cascaded size so that em-based measurements,
2115 // line-heights, etc., work.
2116 if (zoom) {
2117 *aSize = nsStyleFont::ZoomText(aPresContext, *aSize);
2121 static PRInt8 ClampTo8Bit(PRInt32 aValue) {
2122 if (aValue < -128)
2123 return -128;
2124 if (aValue > 127)
2125 return 127;
2126 return PRInt8(aValue);
2129 /* static */ void
2130 nsRuleNode::SetFont(nsPresContext* aPresContext, nsStyleContext* aContext,
2131 nscoord aMinFontSize,
2132 PRUint8 aGenericFontID, const nsRuleDataFont& aFontData,
2133 const nsStyleFont* aParentFont,
2134 nsStyleFont* aFont, PRBool aUsedStartStruct,
2135 PRBool& aInherited)
2137 const nsFont* defaultVariableFont =
2138 aPresContext->GetDefaultFont(kPresContext_DefaultVariableFont_ID);
2140 // -moz-system-font: enum (never inherit!)
2141 nsFont systemFont;
2142 if (eCSSUnit_Enumerated == aFontData.mSystemFont.GetUnit()) {
2143 nsSystemFontID sysID;
2144 switch (aFontData.mSystemFont.GetIntValue()) {
2145 case NS_STYLE_FONT_CAPTION: sysID = eSystemFont_Caption; break; // css2
2146 case NS_STYLE_FONT_ICON: sysID = eSystemFont_Icon; break;
2147 case NS_STYLE_FONT_MENU: sysID = eSystemFont_Menu; break;
2148 case NS_STYLE_FONT_MESSAGE_BOX: sysID = eSystemFont_MessageBox; break;
2149 case NS_STYLE_FONT_SMALL_CAPTION: sysID = eSystemFont_SmallCaption; break;
2150 case NS_STYLE_FONT_STATUS_BAR: sysID = eSystemFont_StatusBar; break;
2151 case NS_STYLE_FONT_WINDOW: sysID = eSystemFont_Window; break; // css3
2152 case NS_STYLE_FONT_DOCUMENT: sysID = eSystemFont_Document; break;
2153 case NS_STYLE_FONT_WORKSPACE: sysID = eSystemFont_Workspace; break;
2154 case NS_STYLE_FONT_DESKTOP: sysID = eSystemFont_Desktop; break;
2155 case NS_STYLE_FONT_INFO: sysID = eSystemFont_Info; break;
2156 case NS_STYLE_FONT_DIALOG: sysID = eSystemFont_Dialog; break;
2157 case NS_STYLE_FONT_BUTTON: sysID = eSystemFont_Button; break;
2158 case NS_STYLE_FONT_PULL_DOWN_MENU:sysID = eSystemFont_PullDownMenu; break;
2159 case NS_STYLE_FONT_LIST: sysID = eSystemFont_List; break;
2160 case NS_STYLE_FONT_FIELD: sysID = eSystemFont_Field; break;
2163 // GetSystemFont sets the font face but not necessarily the size
2164 // XXX Or at least it used to -- no longer true for thebes. Maybe
2165 // it should be again, though.
2166 systemFont.size = defaultVariableFont->size;
2168 if (NS_FAILED(aPresContext->DeviceContext()->GetSystemFont(sysID,
2169 &systemFont))) {
2170 systemFont.name = defaultVariableFont->name;
2173 // XXXldb All of this platform-specific stuff should be in the
2174 // nsIDeviceContext implementations, not here.
2176 #ifdef XP_WIN
2178 // As far as I can tell the system default fonts and sizes for
2179 // on MS-Windows for Buttons, Listboxes/Comboxes and Text Fields are
2180 // all pre-determined and cannot be changed by either the control panel
2181 // or programmtically.
2183 switch (sysID) {
2184 // Fields (text fields)
2185 // Button and Selects (listboxes/comboboxes)
2186 // We use whatever font is defined by the system. Which it appears
2187 // (and the assumption is) it is always a proportional font. Then we
2188 // always use 2 points smaller than what the browser has defined as
2189 // the default proportional font.
2190 case eSystemFont_Field:
2191 case eSystemFont_Button:
2192 case eSystemFont_List:
2193 // Assumption: system defined font is proportional
2194 systemFont.size =
2195 PR_MAX(defaultVariableFont->size - aPresContext->PointsToAppUnits(2), 0);
2196 break;
2198 #endif
2199 } else {
2200 // In case somebody explicitly used -moz-use-system-font.
2201 systemFont = *defaultVariableFont;
2205 // font-family: string list, enum, inherit
2206 NS_ASSERTION(eCSSUnit_Enumerated != aFontData.mFamily.GetUnit(),
2207 "system fonts should not be in mFamily anymore");
2208 if (eCSSUnit_String == aFontData.mFamily.GetUnit()) {
2209 // set the correct font if we are using DocumentFonts OR we are overriding for XUL
2210 // MJA: bug 31816
2211 if (aGenericFontID == kGenericFont_NONE) {
2212 // only bother appending fallback fonts if this isn't a fallback generic font itself
2213 if (!aFont->mFont.name.IsEmpty())
2214 aFont->mFont.name.Append((PRUnichar)',');
2215 // defaultVariableFont.name should always be "serif" or "sans-serif".
2216 aFont->mFont.name.Append(defaultVariableFont->name);
2218 aFont->mFont.familyNameQuirks =
2219 (aPresContext->CompatibilityMode() == eCompatibility_NavQuirks &&
2220 aFontData.mFamilyFromHTML);
2221 aFont->mFont.systemFont = PR_FALSE;
2222 aFont->mFlags &= ~NS_STYLE_FONT_FACE_MASK;
2223 // Technically this is redundant with the code below, but it's good
2224 // to have since we'll still want it once we get rid of
2225 // SetGenericFont (bug 380915).
2226 aFont->mFlags |= aGenericFontID;
2228 else if (eCSSUnit_System_Font == aFontData.mFamily.GetUnit()) {
2229 aFont->mFont.name = systemFont.name;
2230 aFont->mFont.familyNameQuirks = PR_FALSE;
2231 aFont->mFont.systemFont = PR_TRUE;
2232 aFont->mFlags &= ~NS_STYLE_FONT_FACE_MASK;
2234 else if (eCSSUnit_Inherit == aFontData.mFamily.GetUnit()) {
2235 aInherited = PR_TRUE;
2236 aFont->mFont.name = aParentFont->mFont.name;
2237 aFont->mFont.familyNameQuirks = aParentFont->mFont.familyNameQuirks;
2238 aFont->mFont.systemFont = aParentFont->mFont.systemFont;
2239 aFont->mFlags &= ~NS_STYLE_FONT_FACE_MASK;
2240 aFont->mFlags |= (aParentFont->mFlags & NS_STYLE_FONT_FACE_MASK);
2242 else if (eCSSUnit_Initial == aFontData.mFamily.GetUnit()) {
2243 aFont->mFont.name = defaultVariableFont->name;
2244 aFont->mFont.familyNameQuirks = PR_FALSE;
2245 aFont->mFont.systemFont = defaultVariableFont->systemFont;
2246 aFont->mFlags &= ~NS_STYLE_FONT_FACE_MASK;
2249 // When we're in the loop in SetGenericFont, we must ensure that we
2250 // always keep aFont->mFlags set to the correct generic. But we have
2251 // to be careful not to touch it when we're called directly from
2252 // ComputeFontData, because we could have a start struct.
2253 if (aGenericFontID != kGenericFont_NONE) {
2254 aFont->mFlags &= ~NS_STYLE_FONT_FACE_MASK;
2255 aFont->mFlags |= aGenericFontID;
2258 // font-style: enum, normal, inherit
2259 if (eCSSUnit_Enumerated == aFontData.mStyle.GetUnit()) {
2260 aFont->mFont.style = aFontData.mStyle.GetIntValue();
2262 else if (eCSSUnit_Normal == aFontData.mStyle.GetUnit()) {
2263 aFont->mFont.style = NS_STYLE_FONT_STYLE_NORMAL;
2265 else if (eCSSUnit_System_Font == aFontData.mStyle.GetUnit()) {
2266 aFont->mFont.style = systemFont.style;
2268 else if (eCSSUnit_Inherit == aFontData.mStyle.GetUnit()) {
2269 aInherited = PR_TRUE;
2270 aFont->mFont.style = aParentFont->mFont.style;
2272 else if (eCSSUnit_Initial == aFontData.mStyle.GetUnit()) {
2273 aFont->mFont.style = defaultVariableFont->style;
2276 // font-variant: enum, normal, inherit
2277 if (eCSSUnit_Enumerated == aFontData.mVariant.GetUnit()) {
2278 aFont->mFont.variant = aFontData.mVariant.GetIntValue();
2280 else if (eCSSUnit_Normal == aFontData.mVariant.GetUnit()) {
2281 aFont->mFont.variant = NS_STYLE_FONT_VARIANT_NORMAL;
2283 else if (eCSSUnit_System_Font == aFontData.mVariant.GetUnit()) {
2284 aFont->mFont.variant = systemFont.variant;
2286 else if (eCSSUnit_Inherit == aFontData.mVariant.GetUnit()) {
2287 aInherited = PR_TRUE;
2288 aFont->mFont.variant = aParentFont->mFont.variant;
2290 else if (eCSSUnit_Initial == aFontData.mVariant.GetUnit()) {
2291 aFont->mFont.variant = defaultVariableFont->variant;
2294 // font-weight: int, enum, normal, inherit
2295 if (eCSSUnit_Integer == aFontData.mWeight.GetUnit()) {
2296 aFont->mFont.weight = aFontData.mWeight.GetIntValue();
2298 else if (eCSSUnit_Enumerated == aFontData.mWeight.GetUnit()) {
2299 PRInt32 value = aFontData.mWeight.GetIntValue();
2300 switch (value) {
2301 case NS_STYLE_FONT_WEIGHT_NORMAL:
2302 case NS_STYLE_FONT_WEIGHT_BOLD:
2303 aFont->mFont.weight = value;
2304 break;
2305 case NS_STYLE_FONT_WEIGHT_BOLDER:
2306 case NS_STYLE_FONT_WEIGHT_LIGHTER:
2307 aInherited = PR_TRUE;
2308 aFont->mFont.weight = nsStyleUtil::ConstrainFontWeight(aParentFont->mFont.weight + value);
2309 break;
2312 else if (eCSSUnit_Normal == aFontData.mWeight.GetUnit()) {
2313 aFont->mFont.weight = NS_STYLE_FONT_WEIGHT_NORMAL;
2315 else if (eCSSUnit_System_Font == aFontData.mWeight.GetUnit()) {
2316 aFont->mFont.weight = systemFont.weight;
2318 else if (eCSSUnit_Inherit == aFontData.mWeight.GetUnit()) {
2319 aInherited = PR_TRUE;
2320 aFont->mFont.weight = aParentFont->mFont.weight;
2322 else if (eCSSUnit_Initial == aFontData.mWeight.GetUnit()) {
2323 aFont->mFont.weight = defaultVariableFont->weight;
2326 #ifdef MOZ_MATHML
2327 // Compute scriptlevel, scriptminsize and scriptsizemultiplier now so
2328 // they're available for font-size computation.
2330 // -moz-script-min-size: length
2331 if (aFontData.mScriptMinSize.IsLengthUnit()) {
2332 // scriptminsize in font units (em, ex) has to be interpreted relative
2333 // to the parent font, or the size definitions are circular and we
2335 aFont->mScriptMinSize =
2336 CalcLengthWith(aFontData.mScriptMinSize, aParentFont->mSize, aParentFont, nsnull,
2337 aPresContext, aInherited);
2340 // -moz-script-size-multiplier: factor, inherit
2341 if (eCSSUnit_Number == aFontData.mScriptSizeMultiplier.GetUnit()) {
2342 aFont->mScriptSizeMultiplier = aFontData.mScriptSizeMultiplier.GetFloatValue();
2343 NS_ASSERTION(aFont->mScriptSizeMultiplier >= 0.0f, "Cannot have negative script size multiplier");
2345 else if (eCSSUnit_Inherit == aFontData.mScriptSizeMultiplier.GetUnit()) {
2346 aInherited = PR_TRUE;
2347 aFont->mScriptSizeMultiplier = aParentFont->mScriptSizeMultiplier;
2349 else if (eCSSUnit_Initial == aFontData.mScriptSizeMultiplier.GetUnit()) {
2350 aFont->mScriptSizeMultiplier = NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER;
2353 // -moz-script-level: integer, number, inherit
2354 if (eCSSUnit_Integer == aFontData.mScriptLevel.GetUnit()) {
2355 // "relative"
2356 aFont->mScriptLevel = ClampTo8Bit(aParentFont->mScriptLevel + aFontData.mScriptLevel.GetIntValue());
2358 else if (eCSSUnit_Number == aFontData.mScriptLevel.GetUnit()) {
2359 // "absolute"
2360 aFont->mScriptLevel = ClampTo8Bit(PRInt32(aFontData.mScriptLevel.GetFloatValue()));
2362 else if (eCSSUnit_Inherit == aFontData.mScriptSizeMultiplier.GetUnit()) {
2363 aInherited = PR_TRUE;
2364 aFont->mScriptLevel = aParentFont->mScriptLevel;
2366 else if (eCSSUnit_Initial == aFontData.mScriptSizeMultiplier.GetUnit()) {
2367 aFont->mScriptLevel = 0;
2369 #endif
2371 // font-size: enum, length, percent, inherit
2372 nscoord scriptLevelAdjustedParentSize = aParentFont->mSize;
2373 #ifdef MOZ_MATHML
2374 nscoord scriptLevelAdjustedUnconstrainedParentSize;
2375 scriptLevelAdjustedParentSize =
2376 ComputeScriptLevelSize(aFont, aParentFont, aPresContext,
2377 &scriptLevelAdjustedUnconstrainedParentSize);
2378 NS_ASSERTION(!aUsedStartStruct || aFont->mScriptUnconstrainedSize == aFont->mSize,
2379 "If we have a start struct, we should have reset everything coming in here");
2380 #endif
2381 SetFontSize(aPresContext, aFontData, aFont, aParentFont, &aFont->mSize,
2382 systemFont, aParentFont->mSize, scriptLevelAdjustedParentSize,
2383 aUsedStartStruct, aInherited);
2384 #ifdef MOZ_MATHML
2385 if (aParentFont->mSize == aParentFont->mScriptUnconstrainedSize &&
2386 scriptLevelAdjustedParentSize == scriptLevelAdjustedUnconstrainedParentSize) {
2387 // Fast path: we have not been affected by scriptminsize so we don't
2388 // need to call SetFontSize again to compute the
2389 // scriptminsize-unconstrained size. This is OK even if we have a
2390 // start struct, because if we have a start struct then 'font-size'
2391 // was specified and so scriptminsize has no effect.
2392 aFont->mScriptUnconstrainedSize = aFont->mSize;
2393 } else {
2394 SetFontSize(aPresContext, aFontData, aFont, aParentFont,
2395 &aFont->mScriptUnconstrainedSize, systemFont,
2396 aParentFont->mScriptUnconstrainedSize,
2397 scriptLevelAdjustedUnconstrainedParentSize,
2398 aUsedStartStruct, aInherited);
2400 NS_ASSERTION(aFont->mScriptUnconstrainedSize <= aFont->mSize,
2401 "scriptminsize should never be making things bigger");
2402 #endif
2404 // enforce the user' specified minimum font-size on the value that we expose
2405 // (but don't change font-size:0)
2406 if (0 < aFont->mSize && aFont->mSize < aMinFontSize)
2407 aFont->mFont.size = aMinFontSize;
2408 else
2409 aFont->mFont.size = aFont->mSize;
2411 // font-size-adjust: number, none, inherit
2412 if (eCSSUnit_Number == aFontData.mSizeAdjust.GetUnit()) {
2413 aFont->mFont.sizeAdjust = aFontData.mSizeAdjust.GetFloatValue();
2415 else if (eCSSUnit_None == aFontData.mSizeAdjust.GetUnit()) {
2416 aFont->mFont.sizeAdjust = 0.0f;
2418 else if (eCSSUnit_System_Font == aFontData.mSizeAdjust.GetUnit()) {
2419 aFont->mFont.sizeAdjust = systemFont.sizeAdjust;
2421 else if (eCSSUnit_Inherit == aFontData.mSizeAdjust.GetUnit()) {
2422 aInherited = PR_TRUE;
2423 aFont->mFont.sizeAdjust = aParentFont->mFont.sizeAdjust;
2425 else if (eCSSUnit_Initial == aFontData.mSizeAdjust.GetUnit()) {
2426 aFont->mFont.sizeAdjust = 0.0f;
2430 // SetGenericFont:
2431 // - backtrack to an ancestor with the same generic font name (possibly
2432 // up to the root where default values come from the presentation context)
2433 // - re-apply cascading rules from there without caching intermediate values
2434 /* static */ void
2435 nsRuleNode::SetGenericFont(nsPresContext* aPresContext,
2436 nsStyleContext* aContext,
2437 PRUint8 aGenericFontID, nscoord aMinFontSize,
2438 nsStyleFont* aFont)
2440 // walk up the contexts until a context with the desired generic font
2441 nsAutoVoidArray contextPath;
2442 contextPath.AppendElement(aContext);
2443 nsStyleContext* higherContext = aContext->GetParent();
2444 while (higherContext) {
2445 if (higherContext->GetStyleFont()->mFlags & aGenericFontID) {
2446 // done walking up the higher contexts
2447 break;
2449 contextPath.AppendElement(higherContext);
2450 higherContext = higherContext->GetParent();
2453 // re-apply the cascading rules, starting from the higher context
2455 // If we stopped earlier because we reached the root of the style tree,
2456 // we will start with the default generic font from the presentation
2457 // context. Otherwise we start with the higher context.
2458 const nsFont* defaultFont = aPresContext->GetDefaultFont(aGenericFontID);
2459 nsStyleFont parentFont(*defaultFont, aPresContext);
2460 if (higherContext) {
2461 const nsStyleFont* tmpFont = higherContext->GetStyleFont();
2462 parentFont = *tmpFont;
2464 *aFont = parentFont;
2466 PRBool dummy;
2467 PRUint32 fontBit = nsCachedStyleData::GetBitForSID(eStyleStruct_Font);
2469 for (PRInt32 i = contextPath.Count() - 1; i >= 0; --i) {
2470 nsStyleContext* context = (nsStyleContext*)contextPath[i];
2471 nsRuleDataFont fontData; // Declare a struct with null CSS values.
2472 nsRuleData ruleData(NS_STYLE_INHERIT_BIT(Font), aPresContext, context);
2473 ruleData.mFontData = &fontData;
2475 // Trimmed down version of ::WalkRuleTree() to re-apply the style rules
2476 // Note that we *do* need to do this for our own data, since what is
2477 // in |fontData| in ComputeFontData is only for the rules below
2478 // aStartStruct.
2479 for (nsRuleNode* ruleNode = context->GetRuleNode(); ruleNode;
2480 ruleNode = ruleNode->GetParent()) {
2481 if (ruleNode->mNoneBits & fontBit)
2482 // no more font rules on this branch, get out
2483 break;
2485 nsIStyleRule *rule = ruleNode->GetRule();
2486 if (rule) {
2487 ruleData.mLevel = ruleNode->GetLevel();
2488 ruleData.mIsImportantRule = ruleNode->IsImportantRule();
2489 rule->MapRuleInfoInto(&ruleData);
2493 // Compute the delta from the information that the rules specified
2495 // Avoid unnecessary operations in SetFont(). But we care if it's
2496 // the final value that we're computing.
2497 if (i != 0)
2498 fontData.mFamily.Reset();
2500 nsRuleNode::SetFont(aPresContext, context, aMinFontSize,
2501 aGenericFontID, fontData, &parentFont, aFont,
2502 PR_FALSE, dummy);
2504 // XXX Not sure if we need to do this here
2505 // If we have a post-resolve callback, handle that now.
2506 if (ruleData.mPostResolveCallback)
2507 (ruleData.mPostResolveCallback)(aFont, &ruleData);
2509 parentFont = *aFont;
2513 static PRBool ExtractGeneric(const nsString& aFamily, PRBool aGeneric,
2514 void *aData)
2516 nsAutoString *data = static_cast<nsAutoString*>(aData);
2518 if (aGeneric) {
2519 *data = aFamily;
2520 return PR_FALSE; // stop enumeration
2522 return PR_TRUE;
2525 const void*
2526 nsRuleNode::ComputeFontData(void* aStartStruct,
2527 const nsRuleDataStruct& aData,
2528 nsStyleContext* aContext,
2529 nsRuleNode* aHighestNode,
2530 const RuleDetail aRuleDetail, PRBool aInherited)
2532 COMPUTE_START_INHERITED(Font, (mPresContext), font, parentFont,
2533 Font, fontData)
2535 // NOTE: The |aRuleDetail| passed in is a little bit conservative due
2536 // to the -moz-system-font property. We really don't need to consider
2537 // it here in determining whether to cache in the rule tree. However,
2538 // we do need to consider it in WalkRuleTree when deciding whether to
2539 // walk further up the tree. So this means that when the font struct
2540 // is fully specified using *longhand* properties (excluding
2541 // -moz-system-font), we won't cache in the rule tree even though we
2542 // could. However, it's pretty unlikely authors will do that
2543 // (although there is a pretty good chance they'll fully specify it
2544 // using the 'font' shorthand).
2546 // See if there is a minimum font-size constraint to honor
2547 nscoord minimumFontSize =
2548 mPresContext->GetCachedIntPref(kPresContext_MinimumFontSize);
2550 if (minimumFontSize < 0)
2551 minimumFontSize = 0;
2553 PRBool useDocumentFonts =
2554 mPresContext->GetCachedBoolPref(kPresContext_UseDocumentFonts);
2556 // See if we are in the chrome
2557 // We only need to know this to determine if we have to use the
2558 // document fonts (overriding the useDocumentFonts flag), or to
2559 // determine if we have to override the minimum font-size constraint.
2560 if ((!useDocumentFonts || minimumFontSize > 0) && mPresContext->IsChrome()) {
2561 // if we are not using document fonts, but this is a XUL document,
2562 // then we use the document fonts anyway
2563 useDocumentFonts = PR_TRUE;
2564 minimumFontSize = 0;
2567 // Figure out if we are a generic font
2568 PRUint8 generic = kGenericFont_NONE;
2569 // XXXldb What if we would have had a string if we hadn't been doing
2570 // the optimization with a non-null aStartStruct?
2571 if (eCSSUnit_String == fontData.mFamily.GetUnit()) {
2572 fontData.mFamily.GetStringValue(font->mFont.name);
2573 // XXXldb Do we want to extract the generic for this if it's not only a
2574 // generic?
2575 nsFont::GetGenericID(font->mFont.name, &generic);
2577 // If we aren't allowed to use document fonts, then we are only entitled
2578 // to use the user's default variable-width font and fixed-width font
2579 if (!useDocumentFonts) {
2580 // Extract the generic from the specified font family...
2581 nsAutoString genericName;
2582 if (!font->mFont.EnumerateFamilies(ExtractGeneric, &genericName)) {
2583 // The specified font had a generic family.
2584 font->mFont.name = genericName;
2585 nsFont::GetGenericID(genericName, &generic);
2587 // ... and only use it if it's -moz-fixed or monospace
2588 if (generic != kGenericFont_moz_fixed &&
2589 generic != kGenericFont_monospace) {
2590 font->mFont.name.Truncate();
2591 generic = kGenericFont_NONE;
2593 } else {
2594 // The specified font did not have a generic family.
2595 font->mFont.name.Truncate();
2596 generic = kGenericFont_NONE;
2601 // Now compute our font struct
2602 if (generic == kGenericFont_NONE) {
2603 // continue the normal processing
2604 nsRuleNode::SetFont(mPresContext, aContext, minimumFontSize, generic,
2605 fontData, parentFont, font,
2606 aStartStruct != nsnull, inherited);
2608 else {
2609 // re-calculate the font as a generic font
2610 inherited = PR_TRUE;
2611 nsRuleNode::SetGenericFont(mPresContext, aContext, generic,
2612 minimumFontSize, font);
2615 COMPUTE_END_INHERITED(Font, font)
2618 already_AddRefed<nsCSSShadowArray>
2619 nsRuleNode::GetShadowData(nsCSSValueList* aList,
2620 nsStyleContext* aContext,
2621 PRBool aUsesSpread,
2622 PRBool& inherited)
2624 PRUint32 arrayLength = 0;
2625 for (nsCSSValueList *list2 = aList; list2; list2 = list2->mNext)
2626 ++arrayLength;
2628 NS_ASSERTION(arrayLength > 0, "Non-null text-shadow list, yet we counted 0 items.");
2629 nsCSSShadowArray* shadowList = new(arrayLength) nsCSSShadowArray(arrayLength);
2631 if (!shadowList)
2632 return nsnull;
2634 for (nsCSSShadowItem* item = shadowList->ShadowAt(0);
2635 aList;
2636 aList = aList->mNext, ++item) {
2637 nsCSSValue::Array *arr = aList->mValue.GetArrayValue();
2638 // OK to pass bad aParentCoord since we're not passing SETCOORD_INHERIT
2639 SetCoord(arr->Item(0), item->mXOffset, nsStyleCoord(),
2640 SETCOORD_LENGTH, aContext, mPresContext, inherited);
2641 SetCoord(arr->Item(1), item->mYOffset, nsStyleCoord(),
2642 SETCOORD_LENGTH, aContext, mPresContext, inherited);
2644 // Blur radius is optional in the current box-shadow spec
2645 if (arr->Item(2).GetUnit() != eCSSUnit_Null) {
2646 SetCoord(arr->Item(2), item->mRadius, nsStyleCoord(),
2647 SETCOORD_LENGTH, aContext, mPresContext, inherited);
2648 } else {
2649 item->mRadius.SetCoordValue(0);
2652 // Find the spread radius
2653 if (aUsesSpread && arr->Item(3).GetUnit() != eCSSUnit_Null) {
2654 SetCoord(arr->Item(3), item->mSpread, nsStyleCoord(),
2655 SETCOORD_LENGTH, aContext, mPresContext, inherited);
2656 } else {
2657 item->mSpread.SetCoordValue(0);
2660 if (arr->Item(4).GetUnit() != eCSSUnit_Null) {
2661 item->mHasColor = PR_TRUE;
2662 // 2nd argument can be bogus since inherit is not a valid color
2663 SetColor(arr->Item(4), 0, mPresContext, aContext, item->mColor,
2664 inherited);
2668 NS_ADDREF(shadowList);
2669 return shadowList;
2672 const void*
2673 nsRuleNode::ComputeTextData(void* aStartStruct,
2674 const nsRuleDataStruct& aData,
2675 nsStyleContext* aContext,
2676 nsRuleNode* aHighestNode,
2677 const RuleDetail aRuleDetail, PRBool aInherited)
2679 COMPUTE_START_INHERITED(Text, (), text, parentText, Text, textData)
2681 // letter-spacing: normal, length, inherit
2682 SetCoord(textData.mLetterSpacing, text->mLetterSpacing, parentText->mLetterSpacing,
2683 SETCOORD_LH | SETCOORD_NORMAL | SETCOORD_INITIAL_NORMAL,
2684 aContext, mPresContext, inherited);
2686 // text-shadow: none, list, inherit, initial
2687 nsCSSValueList* list = textData.mTextShadow;
2688 if (list) {
2689 text->mTextShadow = nsnull;
2691 // Don't need to handle none/initial explicitly: The above assignment
2692 // takes care of that
2693 if (eCSSUnit_Inherit == list->mValue.GetUnit()) {
2694 inherited = PR_TRUE;
2695 text->mTextShadow = parentText->mTextShadow;
2696 } else if (eCSSUnit_Array == list->mValue.GetUnit()) {
2697 // List of arrays
2698 text->mTextShadow = GetShadowData(list, aContext, PR_FALSE, inherited);
2702 // line-height: normal, number, length, percent, inherit
2703 if (eCSSUnit_Percent == textData.mLineHeight.GetUnit()) {
2704 inherited = PR_TRUE;
2705 // Use |mFont.size| to pick up minimum font size.
2706 text->mLineHeight.SetCoordValue(
2707 nscoord(float(aContext->GetStyleFont()->mFont.size) *
2708 textData.mLineHeight.GetPercentValue()));
2710 else if (eCSSUnit_Initial == textData.mLineHeight.GetUnit() ||
2711 eCSSUnit_System_Font == textData.mLineHeight.GetUnit()) {
2712 text->mLineHeight.SetNormalValue();
2714 else {
2715 SetCoord(textData.mLineHeight, text->mLineHeight, parentText->mLineHeight,
2716 SETCOORD_LH | SETCOORD_FACTOR | SETCOORD_NORMAL,
2717 aContext, mPresContext, inherited);
2718 if (textData.mLineHeight.IsFixedLengthUnit() ||
2719 textData.mLineHeight.GetUnit() == eCSSUnit_Pixel) {
2720 nscoord lh = nsStyleFont::ZoomText(mPresContext,
2721 text->mLineHeight.GetCoordValue());
2722 nscoord minimumFontSize =
2723 mPresContext->GetCachedIntPref(kPresContext_MinimumFontSize);
2725 if (minimumFontSize > 0 && !mPresContext->IsChrome()) {
2726 // If we applied a minimum font size, scale the line height by
2727 // the same ratio. (If we *might* have applied a minimum font
2728 // size, we can't cache in the rule tree.)
2729 inherited = PR_TRUE;
2730 const nsStyleFont *font = aContext->GetStyleFont();
2731 if (font->mSize != 0) {
2732 lh = nscoord(float(lh) * float(font->mFont.size) / float(font->mSize));
2733 } else {
2734 lh = minimumFontSize;
2737 text->mLineHeight.SetCoordValue(lh);
2742 // text-align: enum, string, inherit
2743 if (eCSSUnit_Enumerated == textData.mTextAlign.GetUnit()) {
2744 text->mTextAlign = textData.mTextAlign.GetIntValue();
2746 else if (eCSSUnit_String == textData.mTextAlign.GetUnit()) {
2747 NS_NOTYETIMPLEMENTED("align string");
2749 else if (eCSSUnit_Inherit == textData.mTextAlign.GetUnit()) {
2750 inherited = PR_TRUE;
2751 text->mTextAlign = parentText->mTextAlign;
2753 else if (eCSSUnit_Initial == textData.mTextAlign.GetUnit())
2754 text->mTextAlign = NS_STYLE_TEXT_ALIGN_DEFAULT;
2756 // text-indent: length, percent, inherit
2757 SetCoord(textData.mTextIndent, text->mTextIndent, parentText->mTextIndent,
2758 SETCOORD_LPH | SETCOORD_INITIAL_ZERO, aContext,
2759 mPresContext, inherited);
2761 // text-transform: enum, none, inherit
2762 if (eCSSUnit_Enumerated == textData.mTextTransform.GetUnit()) {
2763 text->mTextTransform = textData.mTextTransform.GetIntValue();
2765 else if (eCSSUnit_None == textData.mTextTransform.GetUnit() ||
2766 eCSSUnit_Initial == textData.mTextTransform.GetUnit()) {
2767 text->mTextTransform = NS_STYLE_TEXT_TRANSFORM_NONE;
2769 else if (eCSSUnit_Inherit == textData.mTextTransform.GetUnit()) {
2770 inherited = PR_TRUE;
2771 text->mTextTransform = parentText->mTextTransform;
2774 // white-space: enum, normal, inherit
2775 if (eCSSUnit_Enumerated == textData.mWhiteSpace.GetUnit()) {
2776 text->mWhiteSpace = textData.mWhiteSpace.GetIntValue();
2778 else if (eCSSUnit_Normal == textData.mWhiteSpace.GetUnit() ||
2779 eCSSUnit_Initial == textData.mWhiteSpace.GetUnit()) {
2780 text->mWhiteSpace = NS_STYLE_WHITESPACE_NORMAL;
2782 else if (eCSSUnit_Inherit == textData.mWhiteSpace.GetUnit()) {
2783 inherited = PR_TRUE;
2784 text->mWhiteSpace = parentText->mWhiteSpace;
2787 // word-spacing: normal, length, inherit
2788 SetCoord(textData.mWordSpacing, text->mWordSpacing, parentText->mWordSpacing,
2789 SETCOORD_LH | SETCOORD_NORMAL | SETCOORD_INITIAL_NORMAL,
2790 aContext, mPresContext, inherited);
2792 // word-wrap: enum, normal, inherit
2793 if (eCSSUnit_Enumerated == textData.mWordWrap.GetUnit()) {
2794 text->mWordWrap = textData.mWordWrap.GetIntValue();
2796 else if (eCSSUnit_Normal == textData.mWordWrap.GetUnit() ||
2797 eCSSUnit_Initial == textData.mWordWrap.GetUnit()) {
2798 text->mWordWrap = NS_STYLE_WORDWRAP_NORMAL;
2800 else if (eCSSUnit_Inherit == textData.mWordWrap.GetUnit()) {
2801 inherited = PR_TRUE;
2802 text->mWordWrap = parentText->mWordWrap;
2805 COMPUTE_END_INHERITED(Text, text)
2808 const void*
2809 nsRuleNode::ComputeTextResetData(void* aStartStruct,
2810 const nsRuleDataStruct& aData,
2811 nsStyleContext* aContext,
2812 nsRuleNode* aHighestNode,
2813 const RuleDetail aRuleDetail, PRBool aInherited)
2815 COMPUTE_START_RESET(TextReset, (), text, parentText, Text, textData)
2817 // vertical-align: enum, length, percent, inherit
2818 if (!SetCoord(textData.mVerticalAlign, text->mVerticalAlign,
2819 parentText->mVerticalAlign, SETCOORD_LPH | SETCOORD_ENUMERATED,
2820 aContext, mPresContext, inherited)) {
2821 if (eCSSUnit_Initial == textData.mVerticalAlign.GetUnit()) {
2822 text->mVerticalAlign.SetIntValue(NS_STYLE_VERTICAL_ALIGN_BASELINE,
2823 eStyleUnit_Enumerated);
2827 // text-decoration: none, enum (bit field), inherit
2828 if (eCSSUnit_Enumerated == textData.mDecoration.GetUnit()) {
2829 PRInt32 td = textData.mDecoration.GetIntValue();
2830 text->mTextDecoration = td;
2831 if (td & NS_STYLE_TEXT_DECORATION_PREF_ANCHORS) {
2832 PRBool underlineLinks =
2833 mPresContext->GetCachedBoolPref(kPresContext_UnderlineLinks);
2834 if (underlineLinks) {
2835 text->mTextDecoration |= NS_STYLE_TEXT_DECORATION_UNDERLINE;
2837 else {
2838 text->mTextDecoration &= ~NS_STYLE_TEXT_DECORATION_UNDERLINE;
2842 else if (eCSSUnit_None == textData.mDecoration.GetUnit() ||
2843 eCSSUnit_Initial == textData.mDecoration.GetUnit()) {
2844 text->mTextDecoration = NS_STYLE_TEXT_DECORATION_NONE;
2846 else if (eCSSUnit_Inherit == textData.mDecoration.GetUnit()) {
2847 inherited = PR_TRUE;
2848 text->mTextDecoration = parentText->mTextDecoration;
2851 // unicode-bidi: enum, normal, inherit
2852 if (eCSSUnit_Normal == textData.mUnicodeBidi.GetUnit() ||
2853 eCSSUnit_Initial == textData.mUnicodeBidi.GetUnit()) {
2854 text->mUnicodeBidi = NS_STYLE_UNICODE_BIDI_NORMAL;
2856 else if (eCSSUnit_Enumerated == textData.mUnicodeBidi.GetUnit() ) {
2857 text->mUnicodeBidi = textData.mUnicodeBidi.GetIntValue();
2859 else if (eCSSUnit_Inherit == textData.mUnicodeBidi.GetUnit() ) {
2860 inherited = PR_TRUE;
2861 text->mUnicodeBidi = parentText->mUnicodeBidi;
2864 COMPUTE_END_RESET(TextReset, text)
2867 const void*
2868 nsRuleNode::ComputeUserInterfaceData(void* aStartStruct,
2869 const nsRuleDataStruct& aData,
2870 nsStyleContext* aContext,
2871 nsRuleNode* aHighestNode,
2872 const RuleDetail aRuleDetail,
2873 PRBool aInherited)
2875 COMPUTE_START_INHERITED(UserInterface, (), ui, parentUI,
2876 UserInterface, uiData)
2878 // cursor: enum, auto, url, inherit
2879 nsCSSValueList* list = uiData.mCursor;
2880 if (nsnull != list) {
2881 delete [] ui->mCursorArray;
2882 ui->mCursorArray = nsnull;
2883 ui->mCursorArrayLength = 0;
2885 if (eCSSUnit_Inherit == list->mValue.GetUnit()) {
2886 inherited = PR_TRUE;
2887 ui->mCursor = parentUI->mCursor;
2888 ui->CopyCursorArrayFrom(*parentUI);
2890 else if (eCSSUnit_Initial == list->mValue.GetUnit()) {
2891 ui->mCursor = NS_STYLE_CURSOR_AUTO;
2893 else {
2894 // The parser will never create a list that is *all* URL values --
2895 // that's invalid.
2896 PRUint32 arrayLength = 0;
2897 nsCSSValueList* list2 = list;
2898 for ( ; list->mValue.GetUnit() == eCSSUnit_Array; list = list->mNext)
2899 if (list->mValue.GetArrayValue()->Item(0).GetImageValue())
2900 ++arrayLength;
2902 if (arrayLength != 0) {
2903 ui->mCursorArray = new nsCursorImage[arrayLength];
2904 if (ui->mCursorArray) {
2905 ui->mCursorArrayLength = arrayLength;
2907 for (nsCursorImage *item = ui->mCursorArray;
2908 list2->mValue.GetUnit() == eCSSUnit_Array;
2909 list2 = list2->mNext) {
2910 nsCSSValue::Array *arr = list2->mValue.GetArrayValue();
2911 imgIRequest *req = arr->Item(0).GetImageValue();
2912 if (req) {
2913 item->mImage = req;
2914 if (arr->Item(1).GetUnit() != eCSSUnit_Null) {
2915 item->mHaveHotspot = PR_TRUE;
2916 item->mHotspotX = arr->Item(1).GetFloatValue(),
2917 item->mHotspotY = arr->Item(2).GetFloatValue();
2919 ++item;
2925 NS_ASSERTION(list, "Must have non-array value at the end");
2926 NS_ASSERTION(list->mValue.GetUnit() == eCSSUnit_Enumerated ||
2927 list->mValue.GetUnit() == eCSSUnit_Auto,
2928 "Unexpected fallback value at end of cursor list");
2930 if (eCSSUnit_Enumerated == list->mValue.GetUnit()) {
2931 ui->mCursor = list->mValue.GetIntValue();
2933 else if (eCSSUnit_Auto == list->mValue.GetUnit()) {
2934 ui->mCursor = NS_STYLE_CURSOR_AUTO;
2939 // user-input: auto, none, enum, inherit
2940 if (eCSSUnit_Enumerated == uiData.mUserInput.GetUnit()) {
2941 ui->mUserInput = uiData.mUserInput.GetIntValue();
2943 else if (eCSSUnit_Auto == uiData.mUserInput.GetUnit() ||
2944 eCSSUnit_Initial == uiData.mUserInput.GetUnit()) {
2945 ui->mUserInput = NS_STYLE_USER_INPUT_AUTO;
2947 else if (eCSSUnit_None == uiData.mUserInput.GetUnit()) {
2948 ui->mUserInput = NS_STYLE_USER_INPUT_NONE;
2950 else if (eCSSUnit_Inherit == uiData.mUserInput.GetUnit()) {
2951 inherited = PR_TRUE;
2952 ui->mUserInput = parentUI->mUserInput;
2955 // user-modify: enum, inherit
2956 if (eCSSUnit_Enumerated == uiData.mUserModify.GetUnit()) {
2957 ui->mUserModify = uiData.mUserModify.GetIntValue();
2959 else if (eCSSUnit_Inherit == uiData.mUserModify.GetUnit()) {
2960 inherited = PR_TRUE;
2961 ui->mUserModify = parentUI->mUserModify;
2963 else if (eCSSUnit_Initial == uiData.mUserModify.GetUnit()) {
2964 ui->mUserModify = NS_STYLE_USER_MODIFY_READ_ONLY;
2967 // user-focus: none, normal, enum, inherit
2968 if (eCSSUnit_Enumerated == uiData.mUserFocus.GetUnit()) {
2969 ui->mUserFocus = uiData.mUserFocus.GetIntValue();
2971 else if (eCSSUnit_None == uiData.mUserFocus.GetUnit() ||
2972 eCSSUnit_Initial == uiData.mUserFocus.GetUnit()) {
2973 ui->mUserFocus = NS_STYLE_USER_FOCUS_NONE;
2975 else if (eCSSUnit_Normal == uiData.mUserFocus.GetUnit()) {
2976 ui->mUserFocus = NS_STYLE_USER_FOCUS_NORMAL;
2978 else if (eCSSUnit_Inherit == uiData.mUserFocus.GetUnit()) {
2979 inherited = PR_TRUE;
2980 ui->mUserFocus = parentUI->mUserFocus;
2983 COMPUTE_END_INHERITED(UserInterface, ui)
2986 const void*
2987 nsRuleNode::ComputeUIResetData(void* aStartStruct,
2988 const nsRuleDataStruct& aData,
2989 nsStyleContext* aContext,
2990 nsRuleNode* aHighestNode,
2991 const RuleDetail aRuleDetail, PRBool aInherited)
2993 COMPUTE_START_RESET(UIReset, (), ui, parentUI, UserInterface, uiData)
2995 // user-select: none, enum, inherit
2996 if (eCSSUnit_Enumerated == uiData.mUserSelect.GetUnit()) {
2997 ui->mUserSelect = uiData.mUserSelect.GetIntValue();
2999 else if (eCSSUnit_None == uiData.mUserSelect.GetUnit()) {
3000 ui->mUserSelect = NS_STYLE_USER_SELECT_NONE;
3002 else if (eCSSUnit_Inherit == uiData.mUserSelect.GetUnit()) {
3003 inherited = PR_TRUE;
3004 ui->mUserSelect = parentUI->mUserSelect;
3006 else if (eCSSUnit_Initial == uiData.mUserSelect.GetUnit() ||
3007 eCSSUnit_Auto == uiData.mUserSelect.GetUnit()) {
3008 ui->mUserSelect = NS_STYLE_USER_SELECT_AUTO;
3011 // ime-mode: auto, normal, enum, inherit
3012 if (eCSSUnit_Auto == uiData.mIMEMode.GetUnit() ||
3013 eCSSUnit_Initial == uiData.mIMEMode.GetUnit()) {
3014 ui->mIMEMode = NS_STYLE_IME_MODE_AUTO;
3016 else if (eCSSUnit_Normal == uiData.mIMEMode.GetUnit()) {
3017 ui->mIMEMode = NS_STYLE_IME_MODE_NORMAL;
3019 else if (eCSSUnit_Enumerated == uiData.mIMEMode.GetUnit()) {
3020 ui->mIMEMode = uiData.mIMEMode.GetIntValue();
3022 else if (eCSSUnit_Inherit == uiData.mIMEMode.GetUnit()) {
3023 inherited = PR_TRUE;
3024 ui->mIMEMode = parentUI->mIMEMode;
3027 // force-broken-image-icons: integer
3028 if (eCSSUnit_Integer == uiData.mForceBrokenImageIcon.GetUnit()) {
3029 ui->mForceBrokenImageIcon = uiData.mForceBrokenImageIcon.GetIntValue();
3030 } else if (eCSSUnit_Inherit == uiData.mForceBrokenImageIcon.GetUnit()) {
3031 inherited = PR_TRUE;
3032 ui->mForceBrokenImageIcon = parentUI->mForceBrokenImageIcon;
3033 } else if (eCSSUnit_Initial == uiData.mForceBrokenImageIcon.GetUnit()) {
3034 ui->mForceBrokenImageIcon = 0;
3036 COMPUTE_END_RESET(UIReset, ui)
3039 const void*
3040 nsRuleNode::ComputeDisplayData(void* aStartStruct,
3041 const nsRuleDataStruct& aData,
3042 nsStyleContext* aContext,
3043 nsRuleNode* aHighestNode,
3044 const RuleDetail aRuleDetail, PRBool aInherited)
3046 COMPUTE_START_RESET(Display, (), display, parentDisplay,
3047 Display, displayData)
3048 nsIAtom* pseudoTag = aContext->GetPseudoType();
3049 PRBool generatedContent = (pseudoTag == nsCSSPseudoElements::before ||
3050 pseudoTag == nsCSSPseudoElements::after);
3051 NS_ASSERTION(!generatedContent || parentContext,
3052 "Must have parent context for generated content");
3053 if (parentDisplay == display && generatedContent)
3054 parentDisplay = parentContext->GetStyleDisplay();
3056 // opacity: factor, inherit
3057 if (eCSSUnit_Number == displayData.mOpacity.GetUnit()) {
3058 display->mOpacity = displayData.mOpacity.GetFloatValue();
3059 if (display->mOpacity > 1.0f)
3060 display->mOpacity = 1.0f;
3061 if (display->mOpacity < 0.0f)
3062 display->mOpacity = 0.0f;
3064 else if (eCSSUnit_Inherit == displayData.mOpacity.GetUnit()) {
3065 inherited = PR_TRUE;
3066 display->mOpacity = parentDisplay->mOpacity;
3068 else if (eCSSUnit_Initial == displayData.mOpacity.GetUnit()) {
3069 display->mOpacity = 1.0f;
3072 // display: enum, none, inherit
3073 if (eCSSUnit_Enumerated == displayData.mDisplay.GetUnit()) {
3074 display->mDisplay = displayData.mDisplay.GetIntValue();
3076 else if (eCSSUnit_None == displayData.mDisplay.GetUnit()) {
3077 display->mDisplay = NS_STYLE_DISPLAY_NONE;
3079 else if (eCSSUnit_Inherit == displayData.mDisplay.GetUnit()) {
3080 inherited = PR_TRUE;
3081 display->mDisplay = parentDisplay->mDisplay;
3083 else if (eCSSUnit_Initial == displayData.mDisplay.GetUnit()) {
3084 display->mDisplay = NS_STYLE_DISPLAY_INLINE;
3087 // appearance: enum, none, inherit
3088 if (eCSSUnit_Enumerated == displayData.mAppearance.GetUnit()) {
3089 display->mAppearance = displayData.mAppearance.GetIntValue();
3091 else if (eCSSUnit_None == displayData.mAppearance.GetUnit() ||
3092 eCSSUnit_Initial == displayData.mAppearance.GetUnit()) {
3093 display->mAppearance = NS_THEME_NONE;
3095 else if (eCSSUnit_Inherit == displayData.mAppearance.GetUnit()) {
3096 inherited = PR_TRUE;
3097 display->mAppearance = parentDisplay->mAppearance;
3100 // binding: url, none, inherit
3101 if (eCSSUnit_URL == displayData.mBinding.GetUnit()) {
3102 nsCSSValue::URL* url = displayData.mBinding.GetURLStructValue();
3103 NS_ASSERTION(url, "What's going on here?");
3105 if (NS_LIKELY(url->mURI)) {
3106 display->mBinding = url;
3107 } else {
3108 display->mBinding = nsnull;
3111 else if (eCSSUnit_None == displayData.mBinding.GetUnit() ||
3112 eCSSUnit_Initial == displayData.mBinding.GetUnit()) {
3113 display->mBinding = nsnull;
3115 else if (eCSSUnit_Inherit == displayData.mBinding.GetUnit()) {
3116 inherited = PR_TRUE;
3117 display->mBinding = parentDisplay->mBinding;
3120 // position: enum, inherit
3121 if (eCSSUnit_Enumerated == displayData.mPosition.GetUnit()) {
3122 display->mPosition = displayData.mPosition.GetIntValue();
3124 else if (eCSSUnit_Inherit == displayData.mPosition.GetUnit()) {
3125 inherited = PR_TRUE;
3126 display->mPosition = parentDisplay->mPosition;
3128 else if (eCSSUnit_Initial == displayData.mPosition.GetUnit()) {
3129 display->mPosition = NS_STYLE_POSITION_STATIC;
3132 // clear: enum, none, inherit
3133 if (eCSSUnit_Enumerated == displayData.mClear.GetUnit()) {
3134 display->mBreakType = displayData.mClear.GetIntValue();
3136 else if (eCSSUnit_None == displayData.mClear.GetUnit() ||
3137 eCSSUnit_Initial == displayData.mClear.GetUnit()) {
3138 display->mBreakType = NS_STYLE_CLEAR_NONE;
3140 else if (eCSSUnit_Inherit == displayData.mClear.GetUnit()) {
3141 inherited = PR_TRUE;
3142 display->mBreakType = parentDisplay->mBreakType;
3145 // temp fix for bug 24000
3146 // Map 'auto' and 'avoid' to PR_FALSE, and 'always', 'left', and
3147 // 'right' to PR_TRUE.
3148 // "A conforming user agent may interpret the values 'left' and
3149 // 'right' as 'always'." - CSS2.1, section 13.3.1
3150 if (eCSSUnit_Enumerated == displayData.mBreakBefore.GetUnit()) {
3151 display->mBreakBefore = (NS_STYLE_PAGE_BREAK_AVOID != displayData.mBreakBefore.GetIntValue());
3153 else if (eCSSUnit_Auto == displayData.mBreakBefore.GetUnit() ||
3154 eCSSUnit_Initial == displayData.mBreakBefore.GetUnit()) {
3155 display->mBreakBefore = PR_FALSE;
3157 else if (eCSSUnit_Inherit == displayData.mBreakBefore.GetUnit()) {
3158 inherited = PR_TRUE;
3159 display->mBreakBefore = parentDisplay->mBreakBefore;
3162 if (eCSSUnit_Enumerated == displayData.mBreakAfter.GetUnit()) {
3163 display->mBreakAfter = (NS_STYLE_PAGE_BREAK_AVOID != displayData.mBreakAfter.GetIntValue());
3165 else if (eCSSUnit_Auto == displayData.mBreakAfter.GetUnit() ||
3166 eCSSUnit_Initial == displayData.mBreakAfter.GetUnit()) {
3167 display->mBreakAfter = PR_FALSE;
3169 else if (eCSSUnit_Inherit == displayData.mBreakAfter.GetUnit()) {
3170 inherited = PR_TRUE;
3171 display->mBreakAfter = parentDisplay->mBreakAfter;
3173 // end temp fix
3175 // float: enum, none, inherit
3176 if (eCSSUnit_Enumerated == displayData.mFloat.GetUnit()) {
3177 display->mFloats = displayData.mFloat.GetIntValue();
3179 else if (eCSSUnit_None == displayData.mFloat.GetUnit() ||
3180 eCSSUnit_Initial == displayData.mFloat.GetUnit()) {
3181 display->mFloats = NS_STYLE_FLOAT_NONE;
3183 else if (eCSSUnit_Inherit == displayData.mFloat.GetUnit()) {
3184 inherited = PR_TRUE;
3185 display->mFloats = parentDisplay->mFloats;
3188 // overflow-x: enum, auto, inherit
3189 if (eCSSUnit_Enumerated == displayData.mOverflowX.GetUnit()) {
3190 display->mOverflowX = displayData.mOverflowX.GetIntValue();
3192 else if (eCSSUnit_Auto == displayData.mOverflowX.GetUnit()) {
3193 display->mOverflowX = NS_STYLE_OVERFLOW_AUTO;
3195 else if (eCSSUnit_Inherit == displayData.mOverflowX.GetUnit()) {
3196 inherited = PR_TRUE;
3197 display->mOverflowX = parentDisplay->mOverflowX;
3199 else if (eCSSUnit_Initial == displayData.mOverflowX.GetUnit()) {
3200 display->mOverflowX = NS_STYLE_OVERFLOW_VISIBLE;
3203 // overflow-y: enum, auto, inherit
3204 if (eCSSUnit_Enumerated == displayData.mOverflowY.GetUnit()) {
3205 display->mOverflowY = displayData.mOverflowY.GetIntValue();
3207 else if (eCSSUnit_Auto == displayData.mOverflowY.GetUnit()) {
3208 display->mOverflowY = NS_STYLE_OVERFLOW_AUTO;
3210 else if (eCSSUnit_Inherit == displayData.mOverflowY.GetUnit()) {
3211 inherited = PR_TRUE;
3212 display->mOverflowY = parentDisplay->mOverflowY;
3214 else if (eCSSUnit_Initial == displayData.mOverflowY.GetUnit()) {
3215 display->mOverflowY = NS_STYLE_OVERFLOW_VISIBLE;
3218 // CSS3 overflow-x and overflow-y require some fixup as well in some
3219 // cases. NS_STYLE_OVERFLOW_VISIBLE and NS_STYLE_OVERFLOW_CLIP are
3220 // meaningful only when used in both dimensions.
3221 if (display->mOverflowX != display->mOverflowY &&
3222 (display->mOverflowX == NS_STYLE_OVERFLOW_VISIBLE ||
3223 display->mOverflowX == NS_STYLE_OVERFLOW_CLIP ||
3224 display->mOverflowY == NS_STYLE_OVERFLOW_VISIBLE ||
3225 display->mOverflowY == NS_STYLE_OVERFLOW_CLIP)) {
3226 // We can't store in the rule tree since a more specific rule might
3227 // change these conditions.
3228 inherited = PR_TRUE;
3230 // NS_STYLE_OVERFLOW_CLIP is a deprecated value, so if it's specified
3231 // in only one dimension, convert it to NS_STYLE_OVERFLOW_HIDDEN.
3232 if (display->mOverflowX == NS_STYLE_OVERFLOW_CLIP)
3233 display->mOverflowX = NS_STYLE_OVERFLOW_HIDDEN;
3234 if (display->mOverflowY == NS_STYLE_OVERFLOW_CLIP)
3235 display->mOverflowY = NS_STYLE_OVERFLOW_HIDDEN;
3237 // If 'visible' is specified but doesn't match the other dimension, it
3238 // turns into 'auto'.
3239 if (display->mOverflowX == NS_STYLE_OVERFLOW_VISIBLE)
3240 display->mOverflowX = NS_STYLE_OVERFLOW_AUTO;
3241 if (display->mOverflowY == NS_STYLE_OVERFLOW_VISIBLE)
3242 display->mOverflowY = NS_STYLE_OVERFLOW_AUTO;
3245 // clip property: length, auto, inherit
3246 if (eCSSUnit_Inherit == displayData.mClip.mTop.GetUnit()) { // if one is inherit, they all are
3247 inherited = PR_TRUE;
3248 display->mClipFlags = parentDisplay->mClipFlags;
3249 display->mClip = parentDisplay->mClip;
3251 // if one is initial, they all are
3252 else if (eCSSUnit_Initial == displayData.mClip.mTop.GetUnit()) {
3253 display->mClipFlags = NS_STYLE_CLIP_AUTO;
3254 display->mClip.SetRect(0,0,0,0);
3256 else {
3257 PRBool fullAuto = PR_TRUE;
3259 display->mClipFlags = 0; // clear it
3261 if (eCSSUnit_Auto == displayData.mClip.mTop.GetUnit()) {
3262 display->mClip.y = 0;
3263 display->mClipFlags |= NS_STYLE_CLIP_TOP_AUTO;
3265 else if (displayData.mClip.mTop.IsLengthUnit()) {
3266 display->mClip.y = CalcLength(displayData.mClip.mTop, aContext, mPresContext, inherited);
3267 fullAuto = PR_FALSE;
3269 if (eCSSUnit_Auto == displayData.mClip.mBottom.GetUnit()) {
3270 // Setting to NS_MAXSIZE for the 'auto' case ensures that
3271 // the clip rect is nonempty. It is important that mClip be
3272 // nonempty if the actual clip rect could be nonempty.
3273 display->mClip.height = NS_MAXSIZE;
3274 display->mClipFlags |= NS_STYLE_CLIP_BOTTOM_AUTO;
3276 else if (displayData.mClip.mBottom.IsLengthUnit()) {
3277 display->mClip.height = CalcLength(displayData.mClip.mBottom, aContext, mPresContext, inherited) -
3278 display->mClip.y;
3279 fullAuto = PR_FALSE;
3281 if (eCSSUnit_Auto == displayData.mClip.mLeft.GetUnit()) {
3282 display->mClip.x = 0;
3283 display->mClipFlags |= NS_STYLE_CLIP_LEFT_AUTO;
3285 else if (displayData.mClip.mLeft.IsLengthUnit()) {
3286 display->mClip.x = CalcLength(displayData.mClip.mLeft, aContext, mPresContext, inherited);
3287 fullAuto = PR_FALSE;
3289 if (eCSSUnit_Auto == displayData.mClip.mRight.GetUnit()) {
3290 // Setting to NS_MAXSIZE for the 'auto' case ensures that
3291 // the clip rect is nonempty. It is important that mClip be
3292 // nonempty if the actual clip rect could be nonempty.
3293 display->mClip.width = NS_MAXSIZE;
3294 display->mClipFlags |= NS_STYLE_CLIP_RIGHT_AUTO;
3296 else if (displayData.mClip.mRight.IsLengthUnit()) {
3297 display->mClip.width = CalcLength(displayData.mClip.mRight, aContext, mPresContext, inherited) -
3298 display->mClip.x;
3299 fullAuto = PR_FALSE;
3301 display->mClipFlags &= ~NS_STYLE_CLIP_TYPE_MASK;
3302 if (fullAuto) {
3303 display->mClipFlags |= NS_STYLE_CLIP_AUTO;
3305 else {
3306 display->mClipFlags |= NS_STYLE_CLIP_RECT;
3310 if (display->mDisplay != NS_STYLE_DISPLAY_NONE) {
3311 // CSS2 9.7 specifies display type corrections dealing with 'float'
3312 // and 'position'. Since generated content can't be floated or
3313 // positioned, we can deal with it here.
3315 if (nsCSSPseudoElements::firstLetter == pseudoTag) {
3316 // a non-floating first-letter must be inline
3317 // XXX this fix can go away once bug 103189 is fixed correctly
3318 display->mDisplay = NS_STYLE_DISPLAY_INLINE;
3320 // We can't cache the data in the rule tree since if a more specific
3321 // rule has 'float: left' we'll end up with the wrong 'display'
3322 // property.
3323 inherited = PR_TRUE;
3326 if (display->IsAbsolutelyPositioned()) {
3327 // 1) if position is 'absolute' or 'fixed' then display must be
3328 // block-level and float must be 'none'
3330 // Backup original display value for calculation of a hypothetical
3331 // box (CSS2 10.6.4/10.6.5).
3332 // See nsHTMLReflowState::CalculateHypotheticalBox
3333 display->mOriginalDisplay = display->mDisplay;
3334 EnsureBlockDisplay(display->mDisplay);
3335 display->mFloats = NS_STYLE_FLOAT_NONE;
3337 // We can't cache the data in the rule tree since if a more specific
3338 // rule has 'position: static' we'll end up with problems with the
3339 // 'display' and 'float' properties.
3340 inherited = PR_TRUE;
3341 } else if (display->mFloats != NS_STYLE_FLOAT_NONE) {
3342 // 2) if float is not none, and display is not none, then we must
3343 // set a block-level 'display' type per CSS2.1 section 9.7.
3345 EnsureBlockDisplay(display->mDisplay);
3347 // We can't cache the data in the rule tree since if a more specific
3348 // rule has 'float: none' we'll end up with the wrong 'display'
3349 // property.
3350 inherited = PR_TRUE;
3355 COMPUTE_END_RESET(Display, display)
3358 const void*
3359 nsRuleNode::ComputeVisibilityData(void* aStartStruct,
3360 const nsRuleDataStruct& aData,
3361 nsStyleContext* aContext,
3362 nsRuleNode* aHighestNode,
3363 const RuleDetail aRuleDetail, PRBool aInherited)
3365 COMPUTE_START_INHERITED(Visibility, (mPresContext),
3366 visibility, parentVisibility,
3367 Display, displayData)
3369 // direction: enum, inherit
3370 if (eCSSUnit_Enumerated == displayData.mDirection.GetUnit()) {
3371 visibility->mDirection = displayData.mDirection.GetIntValue();
3372 if (NS_STYLE_DIRECTION_RTL == visibility->mDirection)
3373 mPresContext->SetBidiEnabled();
3375 else if (eCSSUnit_Inherit == displayData.mDirection.GetUnit()) {
3376 inherited = PR_TRUE;
3377 visibility->mDirection = parentVisibility->mDirection;
3379 else if (eCSSUnit_Initial == displayData.mDirection.GetUnit()) {
3380 PRUint32 bidiOptions = mPresContext->GetBidi();
3381 if (GET_BIDI_OPTION_DIRECTION(bidiOptions) == IBMBIDI_TEXTDIRECTION_RTL)
3382 visibility->mDirection = NS_STYLE_DIRECTION_RTL;
3383 else
3384 visibility->mDirection = NS_STYLE_DIRECTION_LTR;
3387 // visibility: enum, inherit
3388 if (eCSSUnit_Enumerated == displayData.mVisibility.GetUnit()) {
3389 visibility->mVisible = displayData.mVisibility.GetIntValue();
3391 else if (eCSSUnit_Inherit == displayData.mVisibility.GetUnit()) {
3392 inherited = PR_TRUE;
3393 visibility->mVisible = parentVisibility->mVisible;
3395 else if (eCSSUnit_Initial == displayData.mVisibility.GetUnit()) {
3396 visibility->mVisible = NS_STYLE_VISIBILITY_VISIBLE;
3399 // lang: string, inherit
3400 // this is not a real CSS property, it is a html attribute mapped to CSS struture
3401 if (eCSSUnit_String == displayData.mLang.GetUnit()) {
3402 if (!gLangService) {
3403 CallGetService(NS_LANGUAGEATOMSERVICE_CONTRACTID, &gLangService);
3406 if (gLangService) {
3407 nsAutoString lang;
3408 displayData.mLang.GetStringValue(lang);
3409 visibility->mLangGroup = gLangService->LookupLanguage(lang);
3413 COMPUTE_END_INHERITED(Visibility, visibility)
3416 const void*
3417 nsRuleNode::ComputeColorData(void* aStartStruct,
3418 const nsRuleDataStruct& aData,
3419 nsStyleContext* aContext,
3420 nsRuleNode* aHighestNode,
3421 const RuleDetail aRuleDetail, PRBool aInherited)
3423 COMPUTE_START_INHERITED(Color, (mPresContext), color, parentColor,
3424 Color, colorData)
3426 // color: color, string, inherit
3427 // Special case for currentColor. According to CSS3, setting color to 'currentColor'
3428 // should behave as if it is inherited
3429 if (colorData.mColor.GetUnit() == eCSSUnit_EnumColor &&
3430 colorData.mColor.GetIntValue() == NS_COLOR_CURRENTCOLOR) {
3431 color->mColor = parentColor->mColor;
3432 inherited = PR_TRUE;
3434 else if (colorData.mColor.GetUnit() == eCSSUnit_Initial) {
3435 color->mColor = mPresContext->DefaultColor();
3437 else {
3438 SetColor(colorData.mColor, parentColor->mColor, mPresContext, aContext, color->mColor,
3439 inherited);
3442 COMPUTE_END_INHERITED(Color, color)
3445 const void*
3446 nsRuleNode::ComputeBackgroundData(void* aStartStruct,
3447 const nsRuleDataStruct& aData,
3448 nsStyleContext* aContext,
3449 nsRuleNode* aHighestNode,
3450 const RuleDetail aRuleDetail, PRBool aInherited)
3452 COMPUTE_START_RESET(Background, (mPresContext), bg, parentBG,
3453 Color, colorData)
3455 // save parentFlags in case bg == parentBG and we clobber them later
3456 PRUint8 parentFlags = parentBG->mBackgroundFlags;
3458 // background-color: color, string, enum (flags), inherit
3459 if (eCSSUnit_Inherit == colorData.mBackColor.GetUnit()) { // do inherit first, so SetColor doesn't do it
3460 bg->mBackgroundColor = parentBG->mBackgroundColor;
3461 bg->mBackgroundFlags &= ~NS_STYLE_BG_COLOR_TRANSPARENT;
3462 bg->mBackgroundFlags |= (parentFlags & NS_STYLE_BG_COLOR_TRANSPARENT);
3463 inherited = PR_TRUE;
3465 else if (SetColor(colorData.mBackColor, parentBG->mBackgroundColor,
3466 mPresContext, aContext, bg->mBackgroundColor, inherited)) {
3467 bg->mBackgroundFlags &= ~NS_STYLE_BG_COLOR_TRANSPARENT;
3469 else if (eCSSUnit_Enumerated == colorData.mBackColor.GetUnit() ||
3470 eCSSUnit_Initial == colorData.mBackColor.GetUnit()) {
3471 bg->mBackgroundFlags |= NS_STYLE_BG_COLOR_TRANSPARENT;
3474 // background-image: url (stored as image), none, inherit
3475 if (eCSSUnit_Image == colorData.mBackImage.GetUnit()) {
3476 bg->mBackgroundImage = colorData.mBackImage.GetImageValue();
3478 else if (eCSSUnit_None == colorData.mBackImage.GetUnit() ||
3479 eCSSUnit_Initial == colorData.mBackImage.GetUnit()) {
3480 bg->mBackgroundImage = nsnull;
3482 else if (eCSSUnit_Inherit == colorData.mBackImage.GetUnit()) {
3483 inherited = PR_TRUE;
3484 bg->mBackgroundImage = parentBG->mBackgroundImage;
3487 if (bg->mBackgroundImage) {
3488 bg->mBackgroundFlags &= ~NS_STYLE_BG_IMAGE_NONE;
3489 } else {
3490 bg->mBackgroundFlags |= NS_STYLE_BG_IMAGE_NONE;
3493 // background-repeat: enum, inherit
3494 if (eCSSUnit_Enumerated == colorData.mBackRepeat.GetUnit()) {
3495 bg->mBackgroundRepeat = colorData.mBackRepeat.GetIntValue();
3497 else if (eCSSUnit_Inherit == colorData.mBackRepeat.GetUnit()) {
3498 inherited = PR_TRUE;
3499 bg->mBackgroundRepeat = parentBG->mBackgroundRepeat;
3501 else if (eCSSUnit_Initial == colorData.mBackRepeat.GetUnit()) {
3502 bg->mBackgroundRepeat = NS_STYLE_BG_REPEAT_XY;
3505 // background-attachment: enum, inherit
3506 if (eCSSUnit_Enumerated == colorData.mBackAttachment.GetUnit()) {
3507 bg->mBackgroundAttachment = colorData.mBackAttachment.GetIntValue();
3509 else if (eCSSUnit_Inherit == colorData.mBackAttachment.GetUnit()) {
3510 inherited = PR_TRUE;
3511 bg->mBackgroundAttachment = parentBG->mBackgroundAttachment;
3513 else if (eCSSUnit_Initial == colorData.mBackAttachment.GetUnit()) {
3514 bg->mBackgroundAttachment = NS_STYLE_BG_ATTACHMENT_SCROLL;
3517 // background-clip: enum, inherit, initial
3518 if (eCSSUnit_Enumerated == colorData.mBackClip.GetUnit()) {
3519 bg->mBackgroundClip = colorData.mBackClip.GetIntValue();
3521 else if (eCSSUnit_Inherit == colorData.mBackClip.GetUnit()) {
3522 bg->mBackgroundClip = parentBG->mBackgroundClip;
3524 else if (eCSSUnit_Initial == colorData.mBackClip.GetUnit()) {
3525 bg->mBackgroundClip = NS_STYLE_BG_CLIP_BORDER;
3528 // background-inline-policy: enum, inherit, initial
3529 if (eCSSUnit_Enumerated == colorData.mBackInlinePolicy.GetUnit()) {
3530 bg->mBackgroundInlinePolicy = colorData.mBackInlinePolicy.GetIntValue();
3532 else if (eCSSUnit_Inherit == colorData.mBackInlinePolicy.GetUnit()) {
3533 bg->mBackgroundInlinePolicy = parentBG->mBackgroundInlinePolicy;
3535 else if (eCSSUnit_Initial == colorData.mBackInlinePolicy.GetUnit()) {
3536 bg->mBackgroundInlinePolicy = NS_STYLE_BG_INLINE_POLICY_CONTINUOUS;
3539 // background-origin: enum, inherit, initial
3540 if (eCSSUnit_Enumerated == colorData.mBackOrigin.GetUnit()) {
3541 bg->mBackgroundOrigin = colorData.mBackOrigin.GetIntValue();
3543 else if (eCSSUnit_Inherit == colorData.mBackOrigin.GetUnit()) {
3544 bg->mBackgroundOrigin = parentBG->mBackgroundOrigin;
3546 else if (eCSSUnit_Initial == colorData.mBackOrigin.GetUnit()) {
3547 bg->mBackgroundOrigin = NS_STYLE_BG_ORIGIN_PADDING;
3550 // background-position: enum, length, percent (flags), inherit
3551 if (eCSSUnit_Percent == colorData.mBackPosition.mXValue.GetUnit()) {
3552 bg->mBackgroundXPosition.mFloat = colorData.mBackPosition.mXValue.GetPercentValue();
3553 bg->mBackgroundFlags |= NS_STYLE_BG_X_POSITION_PERCENT;
3554 bg->mBackgroundFlags &= ~NS_STYLE_BG_X_POSITION_LENGTH;
3556 else if (colorData.mBackPosition.mXValue.IsLengthUnit()) {
3557 bg->mBackgroundXPosition.mCoord = CalcLength(colorData.mBackPosition.mXValue,
3558 aContext, mPresContext, inherited);
3559 bg->mBackgroundFlags |= NS_STYLE_BG_X_POSITION_LENGTH;
3560 bg->mBackgroundFlags &= ~NS_STYLE_BG_X_POSITION_PERCENT;
3562 else if (eCSSUnit_Enumerated == colorData.mBackPosition.mXValue.GetUnit()) {
3563 switch (colorData.mBackPosition.mXValue.GetIntValue()) {
3564 case NS_STYLE_BG_POSITION_LEFT:
3565 bg->mBackgroundXPosition.mFloat = 0.0f;
3566 break;
3567 case NS_STYLE_BG_POSITION_RIGHT:
3568 bg->mBackgroundXPosition.mFloat = 1.0f;
3569 break;
3570 default:
3571 NS_NOTREACHED("unexpected value");
3572 // fall through
3573 case NS_STYLE_BG_POSITION_CENTER:
3574 bg->mBackgroundXPosition.mFloat = 0.5f;
3575 break;
3577 bg->mBackgroundFlags |= NS_STYLE_BG_X_POSITION_PERCENT;
3578 bg->mBackgroundFlags &= ~NS_STYLE_BG_X_POSITION_LENGTH;
3580 else if (eCSSUnit_Inherit == colorData.mBackPosition.mXValue.GetUnit()) {
3581 inherited = PR_TRUE;
3582 bg->mBackgroundXPosition = parentBG->mBackgroundXPosition;
3583 bg->mBackgroundFlags &= ~(NS_STYLE_BG_X_POSITION_LENGTH | NS_STYLE_BG_X_POSITION_PERCENT);
3584 bg->mBackgroundFlags |= (parentFlags & (NS_STYLE_BG_X_POSITION_LENGTH | NS_STYLE_BG_X_POSITION_PERCENT));
3586 else if (eCSSUnit_Initial == colorData.mBackPosition.mXValue.GetUnit()) {
3587 bg->mBackgroundFlags &= ~(NS_STYLE_BG_X_POSITION_LENGTH | NS_STYLE_BG_X_POSITION_PERCENT);
3590 if (eCSSUnit_Percent == colorData.mBackPosition.mYValue.GetUnit()) {
3591 bg->mBackgroundYPosition.mFloat = colorData.mBackPosition.mYValue.GetPercentValue();
3592 bg->mBackgroundFlags |= NS_STYLE_BG_Y_POSITION_PERCENT;
3593 bg->mBackgroundFlags &= ~NS_STYLE_BG_Y_POSITION_LENGTH;
3595 else if (colorData.mBackPosition.mYValue.IsLengthUnit()) {
3596 bg->mBackgroundYPosition.mCoord = CalcLength(colorData.mBackPosition.mYValue,
3597 aContext, mPresContext, inherited);
3598 bg->mBackgroundFlags |= NS_STYLE_BG_Y_POSITION_LENGTH;
3599 bg->mBackgroundFlags &= ~NS_STYLE_BG_Y_POSITION_PERCENT;
3601 else if (eCSSUnit_Enumerated == colorData.mBackPosition.mYValue.GetUnit()) {
3602 switch (colorData.mBackPosition.mYValue.GetIntValue()) {
3603 case NS_STYLE_BG_POSITION_TOP:
3604 bg->mBackgroundYPosition.mFloat = 0.0f;
3605 break;
3606 case NS_STYLE_BG_POSITION_BOTTOM:
3607 bg->mBackgroundYPosition.mFloat = 1.0f;
3608 break;
3609 default:
3610 NS_NOTREACHED("unexpected value");
3611 // fall through
3612 case NS_STYLE_BG_POSITION_CENTER:
3613 bg->mBackgroundYPosition.mFloat = 0.5f;
3614 break;
3616 bg->mBackgroundFlags |= NS_STYLE_BG_Y_POSITION_PERCENT;
3617 bg->mBackgroundFlags &= ~NS_STYLE_BG_Y_POSITION_LENGTH;
3619 else if (eCSSUnit_Inherit == colorData.mBackPosition.mYValue.GetUnit()) {
3620 inherited = PR_TRUE;
3621 bg->mBackgroundYPosition = parentBG->mBackgroundYPosition;
3622 bg->mBackgroundFlags &= ~(NS_STYLE_BG_Y_POSITION_LENGTH | NS_STYLE_BG_Y_POSITION_PERCENT);
3623 bg->mBackgroundFlags |= (parentFlags & (NS_STYLE_BG_Y_POSITION_LENGTH | NS_STYLE_BG_Y_POSITION_PERCENT));
3625 else if (eCSSUnit_Initial == colorData.mBackPosition.mYValue.GetUnit()) {
3626 bg->mBackgroundFlags &= ~(NS_STYLE_BG_Y_POSITION_LENGTH | NS_STYLE_BG_Y_POSITION_PERCENT);
3629 COMPUTE_END_RESET(Background, bg)
3632 const void*
3633 nsRuleNode::ComputeMarginData(void* aStartStruct,
3634 const nsRuleDataStruct& aData,
3635 nsStyleContext* aContext,
3636 nsRuleNode* aHighestNode,
3637 const RuleDetail aRuleDetail, PRBool aInherited)
3639 COMPUTE_START_RESET(Margin, (), margin, parentMargin, Margin, marginData)
3641 // margin: length, percent, auto, inherit
3642 nsStyleCoord coord;
3643 nsCSSRect ourMargin(marginData.mMargin);
3644 AdjustLogicalBoxProp(aContext,
3645 marginData.mMarginLeftLTRSource,
3646 marginData.mMarginLeftRTLSource,
3647 marginData.mMarginStart, marginData.mMarginEnd,
3648 NS_SIDE_LEFT, ourMargin, inherited);
3649 AdjustLogicalBoxProp(aContext,
3650 marginData.mMarginRightLTRSource,
3651 marginData.mMarginRightRTLSource,
3652 marginData.mMarginEnd, marginData.mMarginStart,
3653 NS_SIDE_RIGHT, ourMargin, inherited);
3654 NS_FOR_CSS_SIDES(side) {
3655 nsStyleCoord parentCoord = parentMargin->mMargin.Get(side);
3656 if (SetCoord(ourMargin.*(nsCSSRect::sides[side]),
3657 coord, parentCoord, SETCOORD_LPAH | SETCOORD_INITIAL_ZERO,
3658 aContext, mPresContext, inherited)) {
3659 margin->mMargin.Set(side, coord);
3663 margin->RecalcData();
3664 COMPUTE_END_RESET(Margin, margin)
3667 const void*
3668 nsRuleNode::ComputeBorderData(void* aStartStruct,
3669 const nsRuleDataStruct& aData,
3670 nsStyleContext* aContext,
3671 nsRuleNode* aHighestNode,
3672 const RuleDetail aRuleDetail, PRBool aInherited)
3674 COMPUTE_START_RESET(Border, (mPresContext), border, parentBorder,
3675 Margin, marginData)
3677 // -moz-box-shadow: none, list, inherit, initial
3678 nsCSSValueList* list = marginData.mBoxShadow;
3679 if (list) {
3680 // This handles 'none' and 'initial'
3681 border->mBoxShadow = nsnull;
3683 if (eCSSUnit_Inherit == list->mValue.GetUnit()) {
3684 inherited = PR_TRUE;
3685 border->mBoxShadow = parentBorder->mBoxShadow;
3686 } else if (eCSSUnit_Array == list->mValue.GetUnit()) {
3687 // List of arrays
3688 border->mBoxShadow = GetShadowData(list, aContext, PR_TRUE, inherited);
3692 // border-width, border-*-width: length, enum, inherit
3693 nsStyleCoord coord;
3694 nsCSSRect ourBorderWidth(marginData.mBorderWidth);
3695 AdjustLogicalBoxProp(aContext,
3696 marginData.mBorderLeftWidthLTRSource,
3697 marginData.mBorderLeftWidthRTLSource,
3698 marginData.mBorderStartWidth,
3699 marginData.mBorderEndWidth,
3700 NS_SIDE_LEFT, ourBorderWidth, inherited);
3701 AdjustLogicalBoxProp(aContext,
3702 marginData.mBorderRightWidthLTRSource,
3703 marginData.mBorderRightWidthRTLSource,
3704 marginData.mBorderEndWidth,
3705 marginData.mBorderStartWidth,
3706 NS_SIDE_RIGHT, ourBorderWidth, inherited);
3707 { // scope for compilers with broken |for| loop scoping
3708 NS_FOR_CSS_SIDES(side) {
3709 const nsCSSValue &value = ourBorderWidth.*(nsCSSRect::sides[side]);
3710 NS_ASSERTION(eCSSUnit_Percent != value.GetUnit(),
3711 "Percentage borders not implemented yet "
3712 "If implementing, make sure to fix all consumers of "
3713 "nsStyleBorder, the IsPercentageAwareChild method, "
3714 "the nsAbsoluteContainingBlock::FrameDependsOnContainer "
3715 "method, the "
3716 "nsLineLayout::IsPercentageAwareReplacedElement method "
3717 "and probably some other places");
3718 if (eCSSUnit_Enumerated == value.GetUnit()) {
3719 NS_ASSERTION(value.GetIntValue() == NS_STYLE_BORDER_WIDTH_THIN ||
3720 value.GetIntValue() == NS_STYLE_BORDER_WIDTH_MEDIUM ||
3721 value.GetIntValue() == NS_STYLE_BORDER_WIDTH_THICK,
3722 "Unexpected enum value");
3723 border->SetBorderWidth(side,
3724 (mPresContext->GetBorderWidthTable())[value.GetIntValue()]);
3726 // OK to pass bad aParentCoord since we're not passing SETCOORD_INHERIT
3727 else if (SetCoord(value, coord, nsStyleCoord(), SETCOORD_LENGTH,
3728 aContext, mPresContext, inherited)) {
3729 NS_ASSERTION(coord.GetUnit() == eStyleUnit_Coord, "unexpected unit");
3730 border->SetBorderWidth(side, coord.GetCoordValue());
3732 else if (eCSSUnit_Inherit == value.GetUnit()) {
3733 inherited = PR_TRUE;
3734 border->SetBorderWidth(side,
3735 parentBorder->GetComputedBorder().side(side));
3737 else if (eCSSUnit_Initial == value.GetUnit()) {
3738 border->SetBorderWidth(side,
3739 (mPresContext->GetBorderWidthTable())[NS_STYLE_BORDER_WIDTH_MEDIUM]);
3741 else {
3742 NS_ASSERTION(eCSSUnit_Null == value.GetUnit(),
3743 "missing case handling border width");
3748 // border-style, border-*-style: enum, none, inherit
3749 nsCSSRect ourStyle(marginData.mBorderStyle);
3750 AdjustLogicalBoxProp(aContext,
3751 marginData.mBorderLeftStyleLTRSource,
3752 marginData.mBorderLeftStyleRTLSource,
3753 marginData.mBorderStartStyle, marginData.mBorderEndStyle,
3754 NS_SIDE_LEFT, ourStyle, inherited);
3755 AdjustLogicalBoxProp(aContext,
3756 marginData.mBorderRightStyleLTRSource,
3757 marginData.mBorderRightStyleRTLSource,
3758 marginData.mBorderEndStyle, marginData.mBorderStartStyle,
3759 NS_SIDE_RIGHT, ourStyle, inherited);
3760 { // scope for compilers with broken |for| loop scoping
3761 NS_FOR_CSS_SIDES(side) {
3762 const nsCSSValue &value = ourStyle.*(nsCSSRect::sides[side]);
3763 nsCSSUnit unit = value.GetUnit();
3764 if (eCSSUnit_Enumerated == unit) {
3765 border->SetBorderStyle(side, value.GetIntValue());
3767 else if (eCSSUnit_None == unit || eCSSUnit_Initial == unit) {
3768 border->SetBorderStyle(side, NS_STYLE_BORDER_STYLE_NONE);
3770 else if (eCSSUnit_Inherit == unit) {
3771 inherited = PR_TRUE;
3772 border->SetBorderStyle(side, parentBorder->GetBorderStyle(side));
3777 // -moz-border-*-colors: color, string, enum
3778 nscolor borderColor;
3779 nscolor unused = NS_RGB(0,0,0);
3781 { // scope for compilers with broken |for| loop scoping
3782 NS_FOR_CSS_SIDES(side) {
3783 nsCSSValueList* list =
3784 marginData.mBorderColors.*(nsCSSValueListRect::sides[side]);
3785 // FIXME Bug 389404: Implement inherit and -moz-initial.
3786 if (list) {
3787 // Some composite border color information has been specified for this
3788 // border side.
3789 border->EnsureBorderColors();
3790 border->ClearBorderColors(side);
3791 while (list) {
3792 if (SetColor(list->mValue, unused, mPresContext, aContext, borderColor, inherited))
3793 border->AppendBorderColor(side, borderColor, PR_FALSE);
3794 else if (eCSSUnit_Enumerated == list->mValue.GetUnit() &&
3795 NS_STYLE_COLOR_TRANSPARENT == list->mValue.GetIntValue())
3796 border->AppendBorderColor(side, nsnull, PR_TRUE);
3797 list = list->mNext;
3803 // border-color, border-*-color: color, string, enum, inherit
3804 nsCSSRect ourBorderColor(marginData.mBorderColor);
3805 PRBool transparent;
3806 PRBool foreground;
3807 AdjustLogicalBoxProp(aContext,
3808 marginData.mBorderLeftColorLTRSource,
3809 marginData.mBorderLeftColorRTLSource,
3810 marginData.mBorderStartColor, marginData.mBorderEndColor,
3811 NS_SIDE_LEFT, ourBorderColor, inherited);
3812 AdjustLogicalBoxProp(aContext,
3813 marginData.mBorderRightColorLTRSource,
3814 marginData.mBorderRightColorRTLSource,
3815 marginData.mBorderEndColor, marginData.mBorderStartColor,
3816 NS_SIDE_RIGHT, ourBorderColor, inherited);
3817 { // scope for compilers with broken |for| loop scoping
3818 NS_FOR_CSS_SIDES(side) {
3819 const nsCSSValue &value = ourBorderColor.*(nsCSSRect::sides[side]);
3820 if (eCSSUnit_Inherit == value.GetUnit()) {
3821 if (parentContext) {
3822 inherited = PR_TRUE;
3823 parentBorder->GetBorderColor(side, borderColor,
3824 transparent, foreground);
3825 if (transparent)
3826 border->SetBorderTransparent(side);
3827 else if (foreground) {
3828 // We want to inherit the color from the parent, not use the
3829 // color on the element where this chunk of style data will be
3830 // used. We can ensure that the data for the parent are fully
3831 // computed (unlike for the element where this will be used, for
3832 // which the color could be specified on a more specific rule).
3833 border->SetBorderColor(side, parentContext->GetStyleColor()->mColor);
3834 } else
3835 border->SetBorderColor(side, borderColor);
3836 } else {
3837 // We're the root
3838 border->SetBorderToForeground(side);
3841 else if (SetColor(value, unused, mPresContext, aContext, borderColor, inherited)) {
3842 border->SetBorderColor(side, borderColor);
3844 else if (eCSSUnit_Enumerated == value.GetUnit()) {
3845 switch (value.GetIntValue()) {
3846 case NS_STYLE_COLOR_TRANSPARENT:
3847 border->SetBorderTransparent(side);
3848 break;
3849 case NS_STYLE_COLOR_MOZ_USE_TEXT_COLOR:
3850 border->SetBorderToForeground(side);
3851 break;
3854 else if (eCSSUnit_Initial == value.GetUnit()) {
3855 border->SetBorderToForeground(side);
3860 // -moz-border-radius: length, percent, inherit
3861 { // scope for compilers with broken |for| loop scoping
3862 NS_FOR_CSS_SIDES(side) {
3863 nsStyleCoord parentCoord = parentBorder->mBorderRadius.Get(side);
3864 if (SetCoord(marginData.mBorderRadius.*(nsCSSRect::sides[side]), coord,
3865 parentCoord, SETCOORD_LPH | SETCOORD_INITIAL_ZERO,
3866 aContext, mPresContext, inherited))
3867 border->mBorderRadius.Set(side, coord);
3871 // float-edge: enum, inherit
3872 if (eCSSUnit_Enumerated == marginData.mFloatEdge.GetUnit())
3873 border->mFloatEdge = marginData.mFloatEdge.GetIntValue();
3874 else if (eCSSUnit_Inherit == marginData.mFloatEdge.GetUnit()) {
3875 inherited = PR_TRUE;
3876 border->mFloatEdge = parentBorder->mFloatEdge;
3878 else if (eCSSUnit_Initial == marginData.mFloatEdge.GetUnit()) {
3879 border->mFloatEdge = NS_STYLE_FLOAT_EDGE_CONTENT;
3882 // border-image
3883 if (eCSSUnit_Array == marginData.mBorderImage.GetUnit()) {
3884 nsCSSValue::Array *arr = marginData.mBorderImage.GetArrayValue();
3886 // the image
3887 if (eCSSUnit_Image == arr->Item(0).GetUnit()) {
3888 border->SetBorderImage(arr->Item(0).GetImageValue());
3891 // the numbers saying where to split the image
3892 NS_FOR_CSS_SIDES(side) {
3893 // an uninitialized parentCoord is ok because I'm not passing SETCOORD_INHERIT
3894 if (SetCoord(arr->Item(1 + side), coord, nsStyleCoord(),
3895 SETCOORD_FACTOR | SETCOORD_PERCENT, aContext,
3896 mPresContext, inherited)) {
3897 border->mBorderImageSplit.Set(side, coord);
3901 // possible replacement for border-width
3902 // if have one - have all four (see CSSParserImpl::ParseBorderImage())
3903 if (eCSSUnit_Null != arr->Item(5).GetUnit()) {
3904 NS_FOR_CSS_SIDES(side) {
3905 // an uninitialized parentCoord is ok because I'm not passing SETCOORD_INHERIT
3906 if (!SetCoord(arr->Item(5 + side), coord, nsStyleCoord(),
3907 SETCOORD_LENGTH, aContext, mPresContext, inherited)) {
3908 NS_NOTREACHED("SetCoord for border-width replacement from border-image failed");
3910 if (coord.GetUnit() == eStyleUnit_Coord) {
3911 border->SetBorderImageWidthOverride(side, coord.GetCoordValue());
3912 } else {
3913 NS_WARNING("a border-width replacement from border-image "
3914 "has a unit that's not eStyleUnit_Coord");
3915 border->SetBorderImageWidthOverride(side, 0);
3918 border->mHaveBorderImageWidth = PR_TRUE;
3919 } else {
3920 border->mHaveBorderImageWidth = PR_FALSE;
3923 // stretch/round/repeat keywords
3924 if (eCSSUnit_Null == arr->Item(9).GetUnit()) {
3925 // default, both horizontal and vertical are stretch
3926 border->mBorderImageHFill = NS_STYLE_BORDER_IMAGE_STRETCH;
3927 border->mBorderImageVFill = NS_STYLE_BORDER_IMAGE_STRETCH;
3928 } else {
3929 // have horizontal value
3930 border->mBorderImageHFill = arr->Item(9).GetIntValue();
3931 if (eCSSUnit_Null == arr->Item(10).GetUnit()) {
3932 // vertical same as horizontal
3933 border->mBorderImageVFill = border->mBorderImageHFill;
3934 } else {
3935 // have vertical value
3936 border->mBorderImageVFill = arr->Item(10).GetIntValue();
3939 } else if (eCSSUnit_None == marginData.mBorderImage.GetUnit() ||
3940 eCSSUnit_Initial == marginData.mBorderImage.GetUnit()) {
3941 border->mHaveBorderImageWidth = PR_FALSE;
3942 border->SetBorderImage(nsnull);
3943 } else if (eCSSUnit_Inherit == marginData.mBorderImage.GetUnit()) {
3944 NS_FOR_CSS_SIDES(side) {
3945 border->SetBorderImageWidthOverride(side, parentBorder->mBorderImageWidth.side(side));
3947 border->mBorderImageSplit = parentBorder->mBorderImageSplit;
3948 border->mBorderImageHFill = parentBorder->mBorderImageHFill;
3949 border->mBorderImageVFill = parentBorder->mBorderImageVFill;
3950 border->mHaveBorderImageWidth = parentBorder->mHaveBorderImageWidth;
3951 border->SetBorderImage(parentBorder->GetBorderImage());
3954 COMPUTE_END_RESET(Border, border)
3957 const void*
3958 nsRuleNode::ComputePaddingData(void* aStartStruct,
3959 const nsRuleDataStruct& aData,
3960 nsStyleContext* aContext,
3961 nsRuleNode* aHighestNode,
3962 const RuleDetail aRuleDetail, PRBool aInherited)
3964 COMPUTE_START_RESET(Padding, (), padding, parentPadding, Margin, marginData)
3966 // padding: length, percent, inherit
3967 nsStyleCoord coord;
3968 nsCSSRect ourPadding(marginData.mPadding);
3969 AdjustLogicalBoxProp(aContext,
3970 marginData.mPaddingLeftLTRSource,
3971 marginData.mPaddingLeftRTLSource,
3972 marginData.mPaddingStart, marginData.mPaddingEnd,
3973 NS_SIDE_LEFT, ourPadding, inherited);
3974 AdjustLogicalBoxProp(aContext,
3975 marginData.mPaddingRightLTRSource,
3976 marginData.mPaddingRightRTLSource,
3977 marginData.mPaddingEnd, marginData.mPaddingStart,
3978 NS_SIDE_RIGHT, ourPadding, inherited);
3979 NS_FOR_CSS_SIDES(side) {
3980 nsStyleCoord parentCoord = parentPadding->mPadding.Get(side);
3981 if (SetCoord(ourPadding.*(nsCSSRect::sides[side]),
3982 coord, parentCoord, SETCOORD_LPH | SETCOORD_INITIAL_ZERO,
3983 aContext, mPresContext, inherited)) {
3984 padding->mPadding.Set(side, coord);
3988 padding->RecalcData();
3989 COMPUTE_END_RESET(Padding, padding)
3992 const void*
3993 nsRuleNode::ComputeOutlineData(void* aStartStruct,
3994 const nsRuleDataStruct& aData,
3995 nsStyleContext* aContext,
3996 nsRuleNode* aHighestNode,
3997 const RuleDetail aRuleDetail, PRBool aInherited)
3999 COMPUTE_START_RESET(Outline, (mPresContext), outline, parentOutline,
4000 Margin, marginData)
4002 // outline-width: length, enum, inherit
4003 if (eCSSUnit_Initial == marginData.mOutlineWidth.GetUnit()) {
4004 outline->mOutlineWidth =
4005 nsStyleCoord(NS_STYLE_BORDER_WIDTH_MEDIUM, eStyleUnit_Enumerated);
4007 else {
4008 SetCoord(marginData.mOutlineWidth, outline->mOutlineWidth,
4009 parentOutline->mOutlineWidth, SETCOORD_LEH, aContext,
4010 mPresContext, inherited);
4013 // outline-offset: length, inherit
4014 SetCoord(marginData.mOutlineOffset, outline->mOutlineOffset, parentOutline->mOutlineOffset,
4015 SETCOORD_LH | SETCOORD_INITIAL_ZERO, aContext, mPresContext,
4016 inherited);
4019 // outline-color: color, string, enum, inherit
4020 nscolor outlineColor;
4021 nscolor unused = NS_RGB(0,0,0);
4022 if (eCSSUnit_Inherit == marginData.mOutlineColor.GetUnit()) {
4023 if (parentContext) {
4024 inherited = PR_TRUE;
4025 if (parentOutline->GetOutlineColor(outlineColor))
4026 outline->SetOutlineColor(outlineColor);
4027 else {
4028 #ifdef GFX_HAS_INVERT
4029 outline->SetOutlineInitialColor();
4030 #else
4031 // We want to inherit the color from the parent, not use the
4032 // color on the element where this chunk of style data will be
4033 // used. We can ensure that the data for the parent are fully
4034 // computed (unlike for the element where this will be used, for
4035 // which the color could be specified on a more specific rule).
4036 outline->SetOutlineColor(parentContext->GetStyleColor()->mColor);
4037 #endif
4039 } else {
4040 outline->SetOutlineInitialColor();
4043 else if (SetColor(marginData.mOutlineColor, unused, mPresContext, aContext, outlineColor, inherited))
4044 outline->SetOutlineColor(outlineColor);
4045 else if (eCSSUnit_Enumerated == marginData.mOutlineColor.GetUnit() ||
4046 eCSSUnit_Initial == marginData.mOutlineColor.GetUnit()) {
4047 outline->SetOutlineInitialColor();
4050 // -moz-outline-radius: length, percent, inherit
4051 nsStyleCoord coord;
4052 { // scope for compilers with broken |for| loop scoping
4053 NS_FOR_CSS_SIDES(side) {
4054 nsStyleCoord parentCoord = parentOutline->mOutlineRadius.Get(side);
4055 if (SetCoord(marginData.mOutlineRadius.*(nsCSSRect::sides[side]), coord,
4056 parentCoord, SETCOORD_LPH | SETCOORD_INITIAL_ZERO,
4057 aContext, mPresContext, inherited))
4058 outline->mOutlineRadius.Set(side, coord);
4062 // outline-style: auto, enum, none, inherit
4063 if (eCSSUnit_Enumerated == marginData.mOutlineStyle.GetUnit())
4064 outline->SetOutlineStyle(marginData.mOutlineStyle.GetIntValue());
4065 else if (eCSSUnit_None == marginData.mOutlineStyle.GetUnit() ||
4066 eCSSUnit_Initial == marginData.mOutlineStyle.GetUnit())
4067 outline->SetOutlineStyle(NS_STYLE_BORDER_STYLE_NONE);
4068 else if (eCSSUnit_Auto == marginData.mOutlineStyle.GetUnit()) {
4069 outline->SetOutlineStyle(NS_STYLE_BORDER_STYLE_AUTO);
4070 } else if (eCSSUnit_Inherit == marginData.mOutlineStyle.GetUnit()) {
4071 inherited = PR_TRUE;
4072 outline->SetOutlineStyle(parentOutline->GetOutlineStyle());
4075 outline->RecalcData(mPresContext);
4076 COMPUTE_END_RESET(Outline, outline)
4079 const void*
4080 nsRuleNode::ComputeListData(void* aStartStruct,
4081 const nsRuleDataStruct& aData,
4082 nsStyleContext* aContext,
4083 nsRuleNode* aHighestNode,
4084 const RuleDetail aRuleDetail, PRBool aInherited)
4086 COMPUTE_START_INHERITED(List, (), list, parentList, List, listData)
4088 // list-style-type: enum, none, inherit
4089 if (eCSSUnit_Enumerated == listData.mType.GetUnit()) {
4090 list->mListStyleType = listData.mType.GetIntValue();
4092 else if (eCSSUnit_None == listData.mType.GetUnit()) {
4093 list->mListStyleType = NS_STYLE_LIST_STYLE_NONE;
4095 else if (eCSSUnit_Inherit == listData.mType.GetUnit()) {
4096 inherited = PR_TRUE;
4097 list->mListStyleType = parentList->mListStyleType;
4099 else if (eCSSUnit_Initial == listData.mType.GetUnit()) {
4100 list->mListStyleType = NS_STYLE_LIST_STYLE_DISC;
4103 // list-style-image: url, none, inherit
4104 if (eCSSUnit_Image == listData.mImage.GetUnit()) {
4105 list->mListStyleImage = listData.mImage.GetImageValue();
4107 else if (eCSSUnit_None == listData.mImage.GetUnit() ||
4108 eCSSUnit_Initial == listData.mImage.GetUnit()) {
4109 list->mListStyleImage = nsnull;
4111 else if (eCSSUnit_Inherit == listData.mImage.GetUnit()) {
4112 inherited = PR_TRUE;
4113 list->mListStyleImage = parentList->mListStyleImage;
4116 // list-style-position: enum, inherit
4117 if (eCSSUnit_Enumerated == listData.mPosition.GetUnit()) {
4118 list->mListStylePosition = listData.mPosition.GetIntValue();
4120 else if (eCSSUnit_Inherit == listData.mPosition.GetUnit()) {
4121 inherited = PR_TRUE;
4122 list->mListStylePosition = parentList->mListStylePosition;
4124 else if (eCSSUnit_Initial == listData.mPosition.GetUnit()) {
4125 list->mListStylePosition = NS_STYLE_LIST_STYLE_POSITION_OUTSIDE;
4128 // image region property: length, auto, inherit
4129 if (eCSSUnit_Inherit == listData.mImageRegion.mTop.GetUnit()) { // if one is inherit, they all are
4130 inherited = PR_TRUE;
4131 list->mImageRegion = parentList->mImageRegion;
4133 // if one is -moz-initial, they all are
4134 else if (eCSSUnit_Initial == listData.mImageRegion.mTop.GetUnit()) {
4135 list->mImageRegion.Empty();
4137 else {
4138 if (eCSSUnit_Auto == listData.mImageRegion.mTop.GetUnit())
4139 list->mImageRegion.y = 0;
4140 else if (listData.mImageRegion.mTop.IsLengthUnit())
4141 list->mImageRegion.y = CalcLength(listData.mImageRegion.mTop, aContext, mPresContext, inherited);
4143 if (eCSSUnit_Auto == listData.mImageRegion.mBottom.GetUnit())
4144 list->mImageRegion.height = 0;
4145 else if (listData.mImageRegion.mBottom.IsLengthUnit())
4146 list->mImageRegion.height = CalcLength(listData.mImageRegion.mBottom, aContext,
4147 mPresContext, inherited) - list->mImageRegion.y;
4149 if (eCSSUnit_Auto == listData.mImageRegion.mLeft.GetUnit())
4150 list->mImageRegion.x = 0;
4151 else if (listData.mImageRegion.mLeft.IsLengthUnit())
4152 list->mImageRegion.x = CalcLength(listData.mImageRegion.mLeft, aContext, mPresContext, inherited);
4154 if (eCSSUnit_Auto == listData.mImageRegion.mRight.GetUnit())
4155 list->mImageRegion.width = 0;
4156 else if (listData.mImageRegion.mRight.IsLengthUnit())
4157 list->mImageRegion.width = CalcLength(listData.mImageRegion.mRight, aContext, mPresContext, inherited) -
4158 list->mImageRegion.x;
4161 COMPUTE_END_INHERITED(List, list)
4164 const void*
4165 nsRuleNode::ComputePositionData(void* aStartStruct,
4166 const nsRuleDataStruct& aData,
4167 nsStyleContext* aContext,
4168 nsRuleNode* aHighestNode,
4169 const RuleDetail aRuleDetail, PRBool aInherited)
4171 COMPUTE_START_RESET(Position, (), pos, parentPos, Position, posData)
4173 // box offsets: length, percent, auto, inherit
4174 nsStyleCoord coord;
4175 NS_FOR_CSS_SIDES(side) {
4176 nsStyleCoord parentCoord = parentPos->mOffset.Get(side);
4177 if (SetCoord(posData.mOffset.*(nsCSSRect::sides[side]),
4178 coord, parentCoord, SETCOORD_LPAH | SETCOORD_INITIAL_AUTO,
4179 aContext, mPresContext, inherited)) {
4180 pos->mOffset.Set(side, coord);
4184 SetCoord(posData.mWidth, pos->mWidth, parentPos->mWidth,
4185 SETCOORD_LPAEH | SETCOORD_INITIAL_AUTO, aContext,
4186 mPresContext, inherited);
4187 SetCoord(posData.mMinWidth, pos->mMinWidth, parentPos->mMinWidth,
4188 SETCOORD_LPEH | SETCOORD_INITIAL_ZERO, aContext,
4189 mPresContext, inherited);
4190 SetCoord(posData.mMaxWidth, pos->mMaxWidth, parentPos->mMaxWidth,
4191 SETCOORD_LPOEH | SETCOORD_INITIAL_NONE, aContext,
4192 mPresContext, inherited);
4194 SetCoord(posData.mHeight, pos->mHeight, parentPos->mHeight,
4195 SETCOORD_LPAH | SETCOORD_INITIAL_AUTO, aContext,
4196 mPresContext, inherited);
4197 SetCoord(posData.mMinHeight, pos->mMinHeight, parentPos->mMinHeight,
4198 SETCOORD_LPH | SETCOORD_INITIAL_ZERO, aContext,
4199 mPresContext, inherited);
4200 SetCoord(posData.mMaxHeight, pos->mMaxHeight, parentPos->mMaxHeight,
4201 SETCOORD_LPOH | SETCOORD_INITIAL_NONE, aContext,
4202 mPresContext, inherited);
4204 // box-sizing: enum, inherit
4205 if (eCSSUnit_Enumerated == posData.mBoxSizing.GetUnit()) {
4206 pos->mBoxSizing = posData.mBoxSizing.GetIntValue();
4208 else if (eCSSUnit_Inherit == posData.mBoxSizing.GetUnit()) {
4209 inherited = PR_TRUE;
4210 pos->mBoxSizing = parentPos->mBoxSizing;
4212 else if (eCSSUnit_Initial == posData.mBoxSizing.GetUnit()) {
4213 pos->mBoxSizing = NS_STYLE_BOX_SIZING_CONTENT;
4216 // z-index
4217 if (! SetCoord(posData.mZIndex, pos->mZIndex, parentPos->mZIndex,
4218 SETCOORD_IA | SETCOORD_INITIAL_AUTO, aContext,
4219 nsnull, inherited)) {
4220 if (eCSSUnit_Inherit == posData.mZIndex.GetUnit()) {
4221 // handle inherit, because it's ok to inherit 'auto' here
4222 inherited = PR_TRUE;
4223 pos->mZIndex = parentPos->mZIndex;
4227 COMPUTE_END_RESET(Position, pos)
4230 const void*
4231 nsRuleNode::ComputeTableData(void* aStartStruct,
4232 const nsRuleDataStruct& aData,
4233 nsStyleContext* aContext,
4234 nsRuleNode* aHighestNode,
4235 const RuleDetail aRuleDetail, PRBool aInherited)
4237 COMPUTE_START_RESET(Table, (), table, parentTable, Table, tableData)
4239 // table-layout: auto, enum, inherit
4240 if (eCSSUnit_Enumerated == tableData.mLayout.GetUnit())
4241 table->mLayoutStrategy = tableData.mLayout.GetIntValue();
4242 else if (eCSSUnit_Auto == tableData.mLayout.GetUnit() ||
4243 eCSSUnit_Initial == tableData.mLayout.GetUnit())
4244 table->mLayoutStrategy = NS_STYLE_TABLE_LAYOUT_AUTO;
4245 else if (eCSSUnit_Inherit == tableData.mLayout.GetUnit()) {
4246 inherited = PR_TRUE;
4247 table->mLayoutStrategy = parentTable->mLayoutStrategy;
4250 // rules: enum (not a real CSS prop)
4251 if (eCSSUnit_Enumerated == tableData.mRules.GetUnit())
4252 table->mRules = tableData.mRules.GetIntValue();
4254 // frame: enum (not a real CSS prop)
4255 if (eCSSUnit_Enumerated == tableData.mFrame.GetUnit())
4256 table->mFrame = tableData.mFrame.GetIntValue();
4258 // cols: enum, int (not a real CSS prop)
4259 if (eCSSUnit_Enumerated == tableData.mCols.GetUnit() ||
4260 eCSSUnit_Integer == tableData.mCols.GetUnit())
4261 table->mCols = tableData.mCols.GetIntValue();
4263 // span: pixels (not a real CSS prop)
4264 if (eCSSUnit_Enumerated == tableData.mSpan.GetUnit() ||
4265 eCSSUnit_Integer == tableData.mSpan.GetUnit())
4266 table->mSpan = tableData.mSpan.GetIntValue();
4268 COMPUTE_END_RESET(Table, table)
4271 const void*
4272 nsRuleNode::ComputeTableBorderData(void* aStartStruct,
4273 const nsRuleDataStruct& aData,
4274 nsStyleContext* aContext,
4275 nsRuleNode* aHighestNode,
4276 const RuleDetail aRuleDetail, PRBool aInherited)
4278 COMPUTE_START_INHERITED(TableBorder, (mPresContext), table, parentTable,
4279 Table, tableData)
4281 // border-collapse: enum, inherit
4282 if (eCSSUnit_Enumerated == tableData.mBorderCollapse.GetUnit()) {
4283 table->mBorderCollapse = tableData.mBorderCollapse.GetIntValue();
4285 else if (eCSSUnit_Inherit == tableData.mBorderCollapse.GetUnit()) {
4286 inherited = PR_TRUE;
4287 table->mBorderCollapse = parentTable->mBorderCollapse;
4289 else if (eCSSUnit_Initial == tableData.mBorderCollapse.GetUnit()) {
4290 table->mBorderCollapse = NS_STYLE_BORDER_SEPARATE;
4293 // border-spacing-x: length, inherit
4294 SetCoord(tableData.mBorderSpacing.mXValue, table->mBorderSpacingX,
4295 parentTable->mBorderSpacingX, SETCOORD_LH | SETCOORD_INITIAL_ZERO,
4296 aContext, mPresContext, inherited);
4297 // border-spacing-y: length, inherit
4298 SetCoord(tableData.mBorderSpacing.mYValue, table->mBorderSpacingY,
4299 parentTable->mBorderSpacingY, SETCOORD_LH | SETCOORD_INITIAL_ZERO,
4300 aContext, mPresContext, inherited);
4302 // caption-side: enum, inherit
4303 if (eCSSUnit_Enumerated == tableData.mCaptionSide.GetUnit()) {
4304 table->mCaptionSide = tableData.mCaptionSide.GetIntValue();
4306 else if (eCSSUnit_Inherit == tableData.mCaptionSide.GetUnit()) {
4307 inherited = PR_TRUE;
4308 table->mCaptionSide = parentTable->mCaptionSide;
4310 else if (eCSSUnit_Initial == tableData.mCaptionSide.GetUnit()) {
4311 table->mCaptionSide = NS_STYLE_CAPTION_SIDE_TOP;
4314 // empty-cells: enum, inherit
4315 if (eCSSUnit_Enumerated == tableData.mEmptyCells.GetUnit()) {
4316 table->mEmptyCells = tableData.mEmptyCells.GetIntValue();
4318 else if (eCSSUnit_Inherit == tableData.mEmptyCells.GetUnit()) {
4319 inherited = PR_TRUE;
4320 table->mEmptyCells = parentTable->mEmptyCells;
4322 else if (eCSSUnit_Initial == tableData.mEmptyCells.GetUnit()) {
4323 table->mEmptyCells =
4324 (mPresContext->CompatibilityMode() == eCompatibility_NavQuirks)
4325 ? NS_STYLE_TABLE_EMPTY_CELLS_SHOW_BACKGROUND
4326 : NS_STYLE_TABLE_EMPTY_CELLS_SHOW;
4330 COMPUTE_END_INHERITED(TableBorder, table)
4333 const void*
4334 nsRuleNode::ComputeContentData(void* aStartStruct,
4335 const nsRuleDataStruct& aData,
4336 nsStyleContext* aContext,
4337 nsRuleNode* aHighestNode,
4338 const RuleDetail aRuleDetail, PRBool aInherited)
4340 COMPUTE_START_RESET(Content, (), content, parentContent,
4341 Content, contentData)
4343 // content: [string, url, counter, attr, enum]+, normal, none, inherit
4344 PRUint32 count;
4345 nsAutoString buffer;
4346 nsCSSValueList* contentValue = contentData.mContent;
4347 if (contentValue) {
4348 if (eCSSUnit_Normal == contentValue->mValue.GetUnit() ||
4349 eCSSUnit_None == contentValue->mValue.GetUnit() ||
4350 eCSSUnit_Initial == contentValue->mValue.GetUnit()) {
4351 // "normal", "none", and "initial" all mean no content
4352 content->AllocateContents(0);
4354 else if (eCSSUnit_Inherit == contentValue->mValue.GetUnit()) {
4355 inherited = PR_TRUE;
4356 count = parentContent->ContentCount();
4357 if (NS_SUCCEEDED(content->AllocateContents(count))) {
4358 while (0 < count--) {
4359 content->ContentAt(count) = parentContent->ContentAt(count);
4363 else {
4364 count = 0;
4365 while (contentValue) {
4366 count++;
4367 contentValue = contentValue->mNext;
4369 if (NS_SUCCEEDED(content->AllocateContents(count))) {
4370 const nsAutoString nullStr;
4371 count = 0;
4372 contentValue = contentData.mContent;
4373 while (contentValue) {
4374 const nsCSSValue& value = contentValue->mValue;
4375 nsCSSUnit unit = value.GetUnit();
4376 nsStyleContentType type;
4377 nsStyleContentData &data = content->ContentAt(count++);
4378 switch (unit) {
4379 case eCSSUnit_String: type = eStyleContentType_String; break;
4380 case eCSSUnit_Image: type = eStyleContentType_Image; break;
4381 case eCSSUnit_Attr: type = eStyleContentType_Attr; break;
4382 case eCSSUnit_Counter: type = eStyleContentType_Counter; break;
4383 case eCSSUnit_Counters: type = eStyleContentType_Counters; break;
4384 case eCSSUnit_Enumerated:
4385 switch (value.GetIntValue()) {
4386 case NS_STYLE_CONTENT_OPEN_QUOTE:
4387 type = eStyleContentType_OpenQuote; break;
4388 case NS_STYLE_CONTENT_CLOSE_QUOTE:
4389 type = eStyleContentType_CloseQuote; break;
4390 case NS_STYLE_CONTENT_NO_OPEN_QUOTE:
4391 type = eStyleContentType_NoOpenQuote; break;
4392 case NS_STYLE_CONTENT_NO_CLOSE_QUOTE:
4393 type = eStyleContentType_NoCloseQuote; break;
4394 case NS_STYLE_CONTENT_ALT_CONTENT:
4395 type = eStyleContentType_AltContent; break;
4396 default:
4397 NS_ERROR("bad content value");
4399 break;
4400 default:
4401 NS_ERROR("bad content type");
4403 data.mType = type;
4404 if (type == eStyleContentType_Image) {
4405 data.mContent.mImage = value.GetImageValue();
4406 NS_IF_ADDREF(data.mContent.mImage);
4408 else if (type <= eStyleContentType_Attr) {
4409 value.GetStringValue(buffer);
4410 Unquote(buffer);
4411 data.mContent.mString = NS_strdup(buffer.get());
4413 else if (type <= eStyleContentType_Counters) {
4414 data.mContent.mCounters = value.GetArrayValue();
4415 data.mContent.mCounters->AddRef();
4417 else {
4418 data.mContent.mString = nsnull;
4420 contentValue = contentValue->mNext;
4426 // counter-increment: [string [int]]+, none, inherit
4427 nsCSSValuePairList* ourIncrement = contentData.mCounterIncrement;
4428 if (ourIncrement) {
4429 if (eCSSUnit_None == ourIncrement->mXValue.GetUnit() ||
4430 eCSSUnit_Initial == ourIncrement->mXValue.GetUnit()) {
4431 content->AllocateCounterIncrements(0);
4433 else if (eCSSUnit_Inherit == ourIncrement->mXValue.GetUnit()) {
4434 inherited = PR_TRUE;
4435 count = parentContent->CounterIncrementCount();
4436 if (NS_SUCCEEDED(content->AllocateCounterIncrements(count))) {
4437 while (0 < count--) {
4438 const nsStyleCounterData *data =
4439 parentContent->GetCounterIncrementAt(count);
4440 content->SetCounterIncrementAt(count, data->mCounter, data->mValue);
4444 else if (eCSSUnit_String == ourIncrement->mXValue.GetUnit()) {
4445 count = 0;
4446 while (ourIncrement) {
4447 count++;
4448 ourIncrement = ourIncrement->mNext;
4450 if (NS_SUCCEEDED(content->AllocateCounterIncrements(count))) {
4451 count = 0;
4452 ourIncrement = contentData.mCounterIncrement;
4453 while (ourIncrement) {
4454 PRInt32 increment;
4455 if (eCSSUnit_Integer == ourIncrement->mYValue.GetUnit()) {
4456 increment = ourIncrement->mYValue.GetIntValue();
4458 else {
4459 increment = 1;
4461 ourIncrement->mXValue.GetStringValue(buffer);
4462 content->SetCounterIncrementAt(count++, buffer, increment);
4463 ourIncrement = ourIncrement->mNext;
4469 // counter-reset: [string [int]]+, none, inherit
4470 nsCSSValuePairList* ourReset = contentData.mCounterReset;
4471 if (ourReset) {
4472 if (eCSSUnit_None == ourReset->mXValue.GetUnit() ||
4473 eCSSUnit_Initial == ourReset->mXValue.GetUnit()) {
4474 content->AllocateCounterResets(0);
4476 else if (eCSSUnit_Inherit == ourReset->mXValue.GetUnit()) {
4477 inherited = PR_TRUE;
4478 count = parentContent->CounterResetCount();
4479 if (NS_SUCCEEDED(content->AllocateCounterResets(count))) {
4480 while (0 < count--) {
4481 const nsStyleCounterData *data =
4482 parentContent->GetCounterResetAt(count);
4483 content->SetCounterResetAt(count, data->mCounter, data->mValue);
4487 else if (eCSSUnit_String == ourReset->mXValue.GetUnit()) {
4488 count = 0;
4489 while (ourReset) {
4490 count++;
4491 ourReset = ourReset->mNext;
4493 if (NS_SUCCEEDED(content->AllocateCounterResets(count))) {
4494 count = 0;
4495 ourReset = contentData.mCounterReset;
4496 while (ourReset) {
4497 PRInt32 reset;
4498 if (eCSSUnit_Integer == ourReset->mYValue.GetUnit()) {
4499 reset = ourReset->mYValue.GetIntValue();
4501 else {
4502 reset = 0;
4504 ourReset->mXValue.GetStringValue(buffer);
4505 content->SetCounterResetAt(count++, buffer, reset);
4506 ourReset = ourReset->mNext;
4512 // marker-offset: length, auto, inherit
4513 SetCoord(contentData.mMarkerOffset, content->mMarkerOffset, parentContent->mMarkerOffset,
4514 SETCOORD_LH | SETCOORD_AUTO | SETCOORD_INITIAL_AUTO, aContext,
4515 mPresContext, inherited);
4517 COMPUTE_END_RESET(Content, content)
4520 const void*
4521 nsRuleNode::ComputeQuotesData(void* aStartStruct,
4522 const nsRuleDataStruct& aData,
4523 nsStyleContext* aContext,
4524 nsRuleNode* aHighestNode,
4525 const RuleDetail aRuleDetail, PRBool aInherited)
4527 COMPUTE_START_INHERITED(Quotes, (), quotes, parentQuotes,
4528 Content, contentData)
4530 // quotes: [string string]+, none, inherit
4531 PRUint32 count;
4532 nsAutoString buffer;
4533 nsCSSValuePairList* ourQuotes = contentData.mQuotes;
4534 if (ourQuotes) {
4535 nsAutoString closeBuffer;
4536 // FIXME Bug 389406: Implement eCSSUnit_Initial (correctly, unlike
4537 // style structs), and remove the "initial" value from ua.css.
4538 if (eCSSUnit_Inherit == ourQuotes->mXValue.GetUnit()) {
4539 inherited = PR_TRUE;
4540 count = parentQuotes->QuotesCount();
4541 if (NS_SUCCEEDED(quotes->AllocateQuotes(count))) {
4542 while (0 < count--) {
4543 parentQuotes->GetQuotesAt(count, buffer, closeBuffer);
4544 quotes->SetQuotesAt(count, buffer, closeBuffer);
4548 else if (eCSSUnit_None == ourQuotes->mXValue.GetUnit()) {
4549 quotes->AllocateQuotes(0);
4551 else if (eCSSUnit_String == ourQuotes->mXValue.GetUnit()) {
4552 count = 0;
4553 while (ourQuotes) {
4554 count++;
4555 ourQuotes = ourQuotes->mNext;
4557 if (NS_SUCCEEDED(quotes->AllocateQuotes(count))) {
4558 count = 0;
4559 ourQuotes = contentData.mQuotes;
4560 while (ourQuotes) {
4561 ourQuotes->mXValue.GetStringValue(buffer);
4562 ourQuotes->mYValue.GetStringValue(closeBuffer);
4563 Unquote(buffer);
4564 Unquote(closeBuffer);
4565 quotes->SetQuotesAt(count++, buffer, closeBuffer);
4566 ourQuotes = ourQuotes->mNext;
4572 COMPUTE_END_INHERITED(Quotes, quotes)
4575 const void*
4576 nsRuleNode::ComputeXULData(void* aStartStruct,
4577 const nsRuleDataStruct& aData,
4578 nsStyleContext* aContext,
4579 nsRuleNode* aHighestNode,
4580 const RuleDetail aRuleDetail, PRBool aInherited)
4582 COMPUTE_START_RESET(XUL, (), xul, parentXUL, XUL, xulData)
4584 // box-align: enum, inherit
4585 if (eCSSUnit_Enumerated == xulData.mBoxAlign.GetUnit()) {
4586 xul->mBoxAlign = xulData.mBoxAlign.GetIntValue();
4588 else if (eCSSUnit_Inherit == xulData.mBoxAlign.GetUnit()) {
4589 inherited = PR_TRUE;
4590 xul->mBoxAlign = parentXUL->mBoxAlign;
4592 else if (eCSSUnit_Initial == xulData.mBoxAlign.GetUnit()) {
4593 xul->mBoxAlign = NS_STYLE_BOX_ALIGN_STRETCH;
4596 // box-direction: enum, inherit
4597 if (eCSSUnit_Enumerated == xulData.mBoxDirection.GetUnit()) {
4598 xul->mBoxDirection = xulData.mBoxDirection.GetIntValue();
4600 else if (eCSSUnit_Inherit == xulData.mBoxDirection.GetUnit()) {
4601 inherited = PR_TRUE;
4602 xul->mBoxDirection = parentXUL->mBoxDirection;
4604 else if (eCSSUnit_Initial == xulData.mBoxDirection.GetUnit()) {
4605 xul->mBoxDirection = NS_STYLE_BOX_DIRECTION_NORMAL;
4608 // box-flex: factor, inherit
4609 if (eCSSUnit_Number == xulData.mBoxFlex.GetUnit()) {
4610 xul->mBoxFlex = xulData.mBoxFlex.GetFloatValue();
4612 else if (eCSSUnit_Inherit == xulData.mBoxFlex.GetUnit()) {
4613 inherited = PR_TRUE;
4614 xul->mBoxFlex = parentXUL->mBoxFlex;
4616 else if (eCSSUnit_Initial == xulData.mBoxFlex.GetUnit()) {
4617 xul->mBoxFlex = 0.0f;
4620 // box-orient: enum, inherit
4621 if (eCSSUnit_Enumerated == xulData.mBoxOrient.GetUnit()) {
4622 xul->mBoxOrient = xulData.mBoxOrient.GetIntValue();
4624 else if (eCSSUnit_Inherit == xulData.mBoxOrient.GetUnit()) {
4625 inherited = PR_TRUE;
4626 xul->mBoxOrient = parentXUL->mBoxOrient;
4628 else if (eCSSUnit_Initial == xulData.mBoxOrient.GetUnit()) {
4629 xul->mBoxOrient = NS_STYLE_BOX_ORIENT_HORIZONTAL;
4632 // box-pack: enum, inherit
4633 if (eCSSUnit_Enumerated == xulData.mBoxPack.GetUnit()) {
4634 xul->mBoxPack = xulData.mBoxPack.GetIntValue();
4636 else if (eCSSUnit_Inherit == xulData.mBoxPack.GetUnit()) {
4637 inherited = PR_TRUE;
4638 xul->mBoxPack = parentXUL->mBoxPack;
4640 else if (eCSSUnit_Initial == xulData.mBoxPack.GetUnit()) {
4641 xul->mBoxPack = NS_STYLE_BOX_PACK_START;
4644 // box-ordinal-group: integer
4645 if (eCSSUnit_Integer == xulData.mBoxOrdinal.GetUnit()) {
4646 xul->mBoxOrdinal = xulData.mBoxOrdinal.GetIntValue();
4647 } else if (eCSSUnit_Inherit == xulData.mBoxOrdinal.GetUnit()) {
4648 inherited = PR_TRUE;
4649 xul->mBoxOrdinal = parentXUL->mBoxOrdinal;
4650 } else if (eCSSUnit_Initial == xulData.mBoxOrdinal.GetUnit()) {
4651 xul->mBoxOrdinal = 1;
4654 if (eCSSUnit_Inherit == xulData.mStackSizing.GetUnit()) {
4655 inherited = PR_TRUE;
4656 xul->mStretchStack = parentXUL->mStretchStack;
4657 } else if (eCSSUnit_Initial == xulData.mStackSizing.GetUnit()) {
4658 xul->mStretchStack = PR_TRUE;
4659 } else if (eCSSUnit_Enumerated == xulData.mStackSizing.GetUnit()) {
4660 xul->mStretchStack = xulData.mStackSizing.GetIntValue() ==
4661 NS_STYLE_STACK_SIZING_STRETCH_TO_FIT;
4664 COMPUTE_END_RESET(XUL, xul)
4667 const void*
4668 nsRuleNode::ComputeColumnData(void* aStartStruct,
4669 const nsRuleDataStruct& aData,
4670 nsStyleContext* aContext,
4671 nsRuleNode* aHighestNode,
4672 const RuleDetail aRuleDetail, PRBool aInherited)
4674 COMPUTE_START_RESET(Column, (mPresContext), column, parent, Column, columnData)
4676 // column-width: length, auto, inherit
4677 SetCoord(columnData.mColumnWidth,
4678 column->mColumnWidth, parent->mColumnWidth,
4679 SETCOORD_LAH | SETCOORD_INITIAL_AUTO,
4680 aContext, mPresContext, inherited);
4682 // column-gap: length, percentage, inherit, normal
4683 SetCoord(columnData.mColumnGap,
4684 column->mColumnGap, parent->mColumnGap,
4685 SETCOORD_LPH | SETCOORD_NORMAL | SETCOORD_INITIAL_NORMAL,
4686 aContext, mPresContext, inherited);
4688 // column-count: auto, integer, inherit
4689 if (eCSSUnit_Auto == columnData.mColumnCount.GetUnit() ||
4690 eCSSUnit_Initial == columnData.mColumnCount.GetUnit()) {
4691 column->mColumnCount = NS_STYLE_COLUMN_COUNT_AUTO;
4692 } else if (eCSSUnit_Integer == columnData.mColumnCount.GetUnit()) {
4693 column->mColumnCount = columnData.mColumnCount.GetIntValue();
4694 // Max 1000 columns - wallpaper for bug 345583.
4695 column->mColumnCount = PR_MIN(column->mColumnCount, 1000);
4696 } else if (eCSSUnit_Inherit == columnData.mColumnCount.GetUnit()) {
4697 inherited = PR_TRUE;
4698 column->mColumnCount = parent->mColumnCount;
4701 // column-rule-width: length, enum, inherit
4702 const nsCSSValue& widthValue = columnData.mColumnRuleWidth;
4703 if (eCSSUnit_Initial == widthValue.GetUnit()) {
4704 column->SetColumnRuleWidth(
4705 (mPresContext->GetBorderWidthTable())[NS_STYLE_BORDER_WIDTH_MEDIUM]);
4707 else if (eCSSUnit_Enumerated == widthValue.GetUnit()) {
4708 NS_ASSERTION(widthValue.GetIntValue() == NS_STYLE_BORDER_WIDTH_THIN ||
4709 widthValue.GetIntValue() == NS_STYLE_BORDER_WIDTH_MEDIUM ||
4710 widthValue.GetIntValue() == NS_STYLE_BORDER_WIDTH_THICK,
4711 "Unexpected enum value");
4712 column->SetColumnRuleWidth(
4713 (mPresContext->GetBorderWidthTable())[widthValue.GetIntValue()]);
4715 else if (eCSSUnit_Inherit == widthValue.GetUnit()) {
4716 column->SetColumnRuleWidth(parent->GetComputedColumnRuleWidth());
4717 inherited = PR_TRUE;
4719 else if (widthValue.IsLengthUnit()) {
4720 column->SetColumnRuleWidth(CalcLength(widthValue, aContext,
4721 mPresContext, inherited));
4724 // column-rule-style: enum, none, inherit
4725 const nsCSSValue& styleValue = columnData.mColumnRuleStyle;
4726 if (eCSSUnit_Enumerated == styleValue.GetUnit()) {
4727 column->mColumnRuleStyle = styleValue.GetIntValue();
4729 else if (eCSSUnit_None == styleValue.GetUnit() ||
4730 eCSSUnit_Initial == styleValue.GetUnit()) {
4731 column->mColumnRuleStyle = NS_STYLE_BORDER_STYLE_NONE;
4733 else if (eCSSUnit_Inherit == styleValue.GetUnit()) {
4734 inherited = PR_TRUE;
4735 column->mColumnRuleStyle = parent->mColumnRuleStyle;
4738 // column-rule-color: color, inherit
4739 const nsCSSValue& colorValue = columnData.mColumnRuleColor;
4740 if (eCSSUnit_Inherit == colorValue.GetUnit()) {
4741 inherited = PR_TRUE;
4742 column->mColumnRuleColorIsForeground = PR_FALSE;
4743 if (parent->mColumnRuleColorIsForeground) {
4744 column->mColumnRuleColor = parentContext->GetStyleColor()->mColor;
4745 } else {
4746 column->mColumnRuleColor = parent->mColumnRuleColor;
4749 else if (eCSSUnit_Initial == colorValue.GetUnit()) {
4750 column->mColumnRuleColorIsForeground = PR_TRUE;
4752 else if (SetColor(colorValue, 0, mPresContext, aContext, column->mColumnRuleColor, inherited)) {
4753 column->mColumnRuleColorIsForeground = PR_FALSE;
4756 COMPUTE_END_RESET(Column, column)
4759 #ifdef MOZ_SVG
4760 static void
4761 SetSVGPaint(const nsCSSValuePair& aValue, const nsStyleSVGPaint& parentPaint,
4762 nsPresContext* aPresContext, nsStyleContext *aContext,
4763 nsStyleSVGPaint& aResult, nsStyleSVGPaintType aInitialPaintType,
4764 PRBool& aInherited)
4766 nscolor color;
4768 if (aValue.mXValue.GetUnit() == eCSSUnit_Inherit) {
4769 aResult = parentPaint;
4770 aInherited = PR_TRUE;
4771 } else if (aValue.mXValue.GetUnit() == eCSSUnit_None) {
4772 aResult.SetType(eStyleSVGPaintType_None);
4773 } else if (aValue.mXValue.GetUnit() == eCSSUnit_Initial) {
4774 aResult.SetType(aInitialPaintType);
4775 aResult.mPaint.mColor = NS_RGB(0, 0, 0);
4776 aResult.mFallbackColor = NS_RGB(0, 0, 0);
4777 } else if (aValue.mXValue.GetUnit() == eCSSUnit_URL) {
4778 aResult.SetType(eStyleSVGPaintType_Server);
4779 aResult.mPaint.mPaintServer = aValue.mXValue.GetURLValue();
4780 NS_IF_ADDREF(aResult.mPaint.mPaintServer);
4781 if (aValue.mYValue.GetUnit() == eCSSUnit_None) {
4782 aResult.mFallbackColor = NS_RGBA(0, 0, 0, 0);
4783 } else {
4784 NS_ASSERTION(aValue.mYValue.GetUnit() != eCSSUnit_Inherit, "cannot inherit fallback colour");
4785 SetColor(aValue.mYValue, NS_RGB(0, 0, 0), aPresContext, aContext, aResult.mFallbackColor, aInherited);
4787 } else if (SetColor(aValue.mXValue, parentPaint.mPaint.mColor, aPresContext, aContext, color, aInherited)) {
4788 aResult.SetType(eStyleSVGPaintType_Color);
4789 aResult.mPaint.mColor = color;
4793 static void
4794 SetSVGOpacity(const nsCSSValue& aValue, float parentOpacity, float& opacity, PRBool& aInherited)
4796 if (aValue.GetUnit() == eCSSUnit_Inherit) {
4797 opacity = parentOpacity;
4798 aInherited = PR_TRUE;
4800 else if (aValue.GetUnit() == eCSSUnit_Number) {
4801 opacity = aValue.GetFloatValue();
4802 opacity = PR_MAX(opacity, 0.0f);
4803 opacity = PR_MIN(opacity, 1.0f);
4805 else if (aValue.GetUnit() == eCSSUnit_Initial) {
4806 opacity = 1.0f;
4810 const void*
4811 nsRuleNode::ComputeSVGData(void* aStartStruct,
4812 const nsRuleDataStruct& aData,
4813 nsStyleContext* aContext,
4814 nsRuleNode* aHighestNode,
4815 const RuleDetail aRuleDetail, PRBool aInherited)
4817 COMPUTE_START_INHERITED(SVG, (), svg, parentSVG, SVG, SVGData)
4819 // clip-rule: enum, inherit
4820 if (eCSSUnit_Enumerated == SVGData.mClipRule.GetUnit()) {
4821 svg->mClipRule = SVGData.mClipRule.GetIntValue();
4823 else if (eCSSUnit_Inherit == SVGData.mClipRule.GetUnit()) {
4824 inherited = PR_TRUE;
4825 svg->mClipRule = parentSVG->mClipRule;
4827 else if (eCSSUnit_Initial == SVGData.mClipRule.GetUnit()) {
4828 svg->mClipRule = NS_STYLE_FILL_RULE_NONZERO;
4831 // color-interpolation: auto, sRGB, linearRGB, inherit
4832 if (eCSSUnit_Enumerated == SVGData.mColorInterpolation.GetUnit()) {
4833 svg->mColorInterpolation = SVGData.mColorInterpolation.GetIntValue();
4835 else if (eCSSUnit_Auto == SVGData.mColorInterpolation.GetUnit()) {
4836 svg->mColorInterpolation = NS_STYLE_COLOR_INTERPOLATION_AUTO;
4838 else if (eCSSUnit_Inherit == SVGData.mColorInterpolation.GetUnit()) {
4839 inherited = PR_TRUE;
4840 svg->mColorInterpolation = parentSVG->mColorInterpolation;
4842 else if (eCSSUnit_Initial == SVGData.mColorInterpolation.GetUnit()) {
4843 svg->mColorInterpolation = NS_STYLE_COLOR_INTERPOLATION_SRGB;
4846 // color-interpolation-filters: auto, sRGB, linearRGB, inherit
4847 if (eCSSUnit_Enumerated == SVGData.mColorInterpolationFilters.GetUnit()) {
4848 svg->mColorInterpolationFilters = SVGData.mColorInterpolationFilters.GetIntValue();
4850 else if (eCSSUnit_Auto == SVGData.mColorInterpolationFilters.GetUnit()) {
4851 svg->mColorInterpolationFilters = NS_STYLE_COLOR_INTERPOLATION_AUTO;
4853 else if (eCSSUnit_Inherit == SVGData.mColorInterpolationFilters.GetUnit()) {
4854 inherited = PR_TRUE;
4855 svg->mColorInterpolationFilters = parentSVG->mColorInterpolationFilters;
4857 else if (eCSSUnit_Initial == SVGData.mColorInterpolationFilters.GetUnit()) {
4858 svg->mColorInterpolationFilters = NS_STYLE_COLOR_INTERPOLATION_LINEARRGB;
4861 // fill:
4862 SetSVGPaint(SVGData.mFill, parentSVG->mFill, mPresContext, aContext,
4863 svg->mFill, eStyleSVGPaintType_Color, inherited);
4865 // fill-opacity:
4866 SetSVGOpacity(SVGData.mFillOpacity, parentSVG->mFillOpacity,
4867 svg->mFillOpacity, inherited);
4869 // fill-rule: enum, inherit
4870 if (eCSSUnit_Enumerated == SVGData.mFillRule.GetUnit()) {
4871 svg->mFillRule = SVGData.mFillRule.GetIntValue();
4873 else if (eCSSUnit_Inherit == SVGData.mFillRule.GetUnit()) {
4874 inherited = PR_TRUE;
4875 svg->mFillRule = parentSVG->mFillRule;
4877 else if (eCSSUnit_Initial == SVGData.mFillRule.GetUnit()) {
4878 svg->mFillRule = NS_STYLE_FILL_RULE_NONZERO;
4881 // marker-end: url, none, inherit
4882 if (eCSSUnit_URL == SVGData.mMarkerEnd.GetUnit()) {
4883 svg->mMarkerEnd = SVGData.mMarkerEnd.GetURLValue();
4884 } else if (eCSSUnit_None == SVGData.mMarkerEnd.GetUnit() ||
4885 eCSSUnit_Initial == SVGData.mMarkerEnd.GetUnit()) {
4886 svg->mMarkerEnd = nsnull;
4887 } else if (eCSSUnit_Inherit == SVGData.mMarkerEnd.GetUnit()) {
4888 inherited = PR_TRUE;
4889 svg->mMarkerEnd = parentSVG->mMarkerEnd;
4892 // marker-mid: url, none, inherit
4893 if (eCSSUnit_URL == SVGData.mMarkerMid.GetUnit()) {
4894 svg->mMarkerMid = SVGData.mMarkerMid.GetURLValue();
4895 } else if (eCSSUnit_None == SVGData.mMarkerMid.GetUnit() ||
4896 eCSSUnit_Initial == SVGData.mMarkerMid.GetUnit()) {
4897 svg->mMarkerMid = nsnull;
4898 } else if (eCSSUnit_Inherit == SVGData.mMarkerMid.GetUnit()) {
4899 inherited = PR_TRUE;
4900 svg->mMarkerMid = parentSVG->mMarkerMid;
4903 // marker-start: url, none, inherit
4904 if (eCSSUnit_URL == SVGData.mMarkerStart.GetUnit()) {
4905 svg->mMarkerStart = SVGData.mMarkerStart.GetURLValue();
4906 } else if (eCSSUnit_None == SVGData.mMarkerStart.GetUnit() ||
4907 eCSSUnit_Initial == SVGData.mMarkerStart.GetUnit()) {
4908 svg->mMarkerStart = nsnull;
4909 } else if (eCSSUnit_Inherit == SVGData.mMarkerStart.GetUnit()) {
4910 inherited = PR_TRUE;
4911 svg->mMarkerStart = parentSVG->mMarkerStart;
4914 // pointer-events: enum, inherit
4915 if (eCSSUnit_Enumerated == SVGData.mPointerEvents.GetUnit()) {
4916 svg->mPointerEvents = SVGData.mPointerEvents.GetIntValue();
4917 } else if (eCSSUnit_None == SVGData.mPointerEvents.GetUnit()) {
4918 svg->mPointerEvents = NS_STYLE_POINTER_EVENTS_NONE;
4919 } else if (eCSSUnit_Inherit == SVGData.mPointerEvents.GetUnit()) {
4920 inherited = PR_TRUE;
4921 svg->mPointerEvents = parentSVG->mPointerEvents;
4922 } else if (eCSSUnit_Initial == SVGData.mPointerEvents.GetUnit()) {
4923 svg->mPointerEvents = NS_STYLE_POINTER_EVENTS_VISIBLEPAINTED;
4926 // shape-rendering: enum, auto, inherit
4927 if (eCSSUnit_Enumerated == SVGData.mShapeRendering.GetUnit()) {
4928 svg->mShapeRendering = SVGData.mShapeRendering.GetIntValue();
4930 else if (eCSSUnit_Auto == SVGData.mShapeRendering.GetUnit() ||
4931 eCSSUnit_Initial == SVGData.mShapeRendering.GetUnit()) {
4932 svg->mShapeRendering = NS_STYLE_SHAPE_RENDERING_AUTO;
4934 else if (eCSSUnit_Inherit == SVGData.mShapeRendering.GetUnit()) {
4935 inherited = PR_TRUE;
4936 svg->mShapeRendering = parentSVG->mShapeRendering;
4939 // stroke:
4940 SetSVGPaint(SVGData.mStroke, parentSVG->mStroke, mPresContext, aContext,
4941 svg->mStroke, eStyleSVGPaintType_None, inherited);
4943 // stroke-dasharray: <dasharray>, none, inherit
4944 nsCSSValueList *list = SVGData.mStrokeDasharray;
4945 if (list) {
4946 if (eCSSUnit_Inherit == list->mValue.GetUnit()) {
4947 // only do the copy if weren't already set up by the copy constructor
4948 // FIXME Bug 389408: This is broken when aStartStruct is non-null!
4949 if (!svg->mStrokeDasharray) {
4950 inherited = PR_TRUE;
4951 svg->mStrokeDasharrayLength = parentSVG->mStrokeDasharrayLength;
4952 if (svg->mStrokeDasharrayLength) {
4953 svg->mStrokeDasharray = new nsStyleCoord[svg->mStrokeDasharrayLength];
4954 if (svg->mStrokeDasharray)
4955 memcpy(svg->mStrokeDasharray,
4956 parentSVG->mStrokeDasharray,
4957 svg->mStrokeDasharrayLength * sizeof(nsStyleCoord));
4958 else
4959 svg->mStrokeDasharrayLength = 0;
4962 } else {
4963 delete [] svg->mStrokeDasharray;
4964 svg->mStrokeDasharray = nsnull;
4965 svg->mStrokeDasharrayLength = 0;
4967 if (eCSSUnit_Initial != list->mValue.GetUnit() &&
4968 eCSSUnit_None != list->mValue.GetUnit()) {
4969 // count number of values
4970 nsCSSValueList *value = SVGData.mStrokeDasharray;
4971 while (nsnull != value) {
4972 ++svg->mStrokeDasharrayLength;
4973 value = value->mNext;
4976 NS_ASSERTION(svg->mStrokeDasharrayLength != 0, "no dasharray items");
4978 svg->mStrokeDasharray = new nsStyleCoord[svg->mStrokeDasharrayLength];
4980 if (svg->mStrokeDasharray) {
4981 value = SVGData.mStrokeDasharray;
4982 PRUint32 i = 0;
4983 while (nsnull != value) {
4984 SetCoord(value->mValue,
4985 svg->mStrokeDasharray[i++], nsnull,
4986 SETCOORD_LP | SETCOORD_FACTOR,
4987 aContext, mPresContext, inherited);
4988 value = value->mNext;
4990 } else
4991 svg->mStrokeDasharrayLength = 0;
4996 // stroke-dashoffset: <dashoffset>, inherit
4997 SetCoord(SVGData.mStrokeDashoffset,
4998 svg->mStrokeDashoffset, parentSVG->mStrokeDashoffset,
4999 SETCOORD_LPH | SETCOORD_FACTOR | SETCOORD_INITIAL_ZERO,
5000 aContext, mPresContext, inherited);
5002 // stroke-linecap: enum, inherit
5003 if (eCSSUnit_Enumerated == SVGData.mStrokeLinecap.GetUnit()) {
5004 svg->mStrokeLinecap = SVGData.mStrokeLinecap.GetIntValue();
5006 else if (eCSSUnit_Inherit == SVGData.mStrokeLinecap.GetUnit()) {
5007 inherited = PR_TRUE;
5008 svg->mStrokeLinecap = parentSVG->mStrokeLinecap;
5010 else if (eCSSUnit_Initial == SVGData.mStrokeLinecap.GetUnit()) {
5011 svg->mStrokeLinecap = NS_STYLE_STROKE_LINECAP_BUTT;
5014 // stroke-linejoin: enum, inherit
5015 if (eCSSUnit_Enumerated == SVGData.mStrokeLinejoin.GetUnit()) {
5016 svg->mStrokeLinejoin = SVGData.mStrokeLinejoin.GetIntValue();
5018 else if (eCSSUnit_Inherit == SVGData.mStrokeLinejoin.GetUnit()) {
5019 inherited = PR_TRUE;
5020 svg->mStrokeLinejoin = parentSVG->mStrokeLinejoin;
5022 else if (eCSSUnit_Initial == SVGData.mStrokeLinejoin.GetUnit()) {
5023 svg->mStrokeLinejoin = NS_STYLE_STROKE_LINEJOIN_MITER;
5026 // stroke-miterlimit: <miterlimit>, inherit
5027 if (eCSSUnit_Number == SVGData.mStrokeMiterlimit.GetUnit()) {
5028 svg->mStrokeMiterlimit = SVGData.mStrokeMiterlimit.GetFloatValue();
5030 else if (eCSSUnit_Inherit == SVGData.mStrokeMiterlimit.GetUnit()) {
5031 svg->mStrokeMiterlimit = parentSVG->mStrokeMiterlimit;
5032 inherited = PR_TRUE;
5034 else if (eCSSUnit_Initial == SVGData.mStrokeMiterlimit.GetUnit()) {
5035 svg->mStrokeMiterlimit = 4.0f;
5038 // stroke-opacity:
5039 SetSVGOpacity(SVGData.mStrokeOpacity, parentSVG->mStrokeOpacity,
5040 svg->mStrokeOpacity, inherited);
5042 // stroke-width:
5043 if (eCSSUnit_Initial == SVGData.mStrokeWidth.GetUnit()) {
5044 svg->mStrokeWidth.SetCoordValue(nsPresContext::CSSPixelsToAppUnits(1));
5045 } else {
5046 SetCoord(SVGData.mStrokeWidth,
5047 svg->mStrokeWidth, parentSVG->mStrokeWidth,
5048 SETCOORD_LPH | SETCOORD_FACTOR,
5049 aContext, mPresContext, inherited);
5052 // text-anchor: enum, inherit
5053 if (eCSSUnit_Enumerated == SVGData.mTextAnchor.GetUnit()) {
5054 svg->mTextAnchor = SVGData.mTextAnchor.GetIntValue();
5056 else if (eCSSUnit_Inherit == SVGData.mTextAnchor.GetUnit()) {
5057 inherited = PR_TRUE;
5058 svg->mTextAnchor = parentSVG->mTextAnchor;
5060 else if (eCSSUnit_Initial == SVGData.mTextAnchor.GetUnit()) {
5061 svg->mTextAnchor = NS_STYLE_TEXT_ANCHOR_START;
5064 // text-rendering: enum, auto, inherit
5065 if (eCSSUnit_Enumerated == SVGData.mTextRendering.GetUnit()) {
5066 svg->mTextRendering = SVGData.mTextRendering.GetIntValue();
5068 else if (eCSSUnit_Auto == SVGData.mTextRendering.GetUnit() ||
5069 eCSSUnit_Initial == SVGData.mTextRendering.GetUnit()) {
5070 svg->mTextRendering = NS_STYLE_TEXT_RENDERING_AUTO;
5072 else if (eCSSUnit_Inherit == SVGData.mTextRendering.GetUnit()) {
5073 inherited = PR_TRUE;
5074 svg->mTextRendering = parentSVG->mTextRendering;
5077 COMPUTE_END_INHERITED(SVG, svg)
5080 const void*
5081 nsRuleNode::ComputeSVGResetData(void* aStartStruct,
5082 const nsRuleDataStruct& aData,
5083 nsStyleContext* aContext,
5084 nsRuleNode* aHighestNode,
5085 const RuleDetail aRuleDetail, PRBool aInherited)
5087 COMPUTE_START_RESET(SVGReset, (), svgReset, parentSVGReset, SVG, SVGData)
5089 // stop-color:
5090 if (eCSSUnit_Initial == SVGData.mStopColor.GetUnit()) {
5091 svgReset->mStopColor = NS_RGB(0, 0, 0);
5092 } else {
5093 SetColor(SVGData.mStopColor, parentSVGReset->mStopColor,
5094 mPresContext, aContext, svgReset->mStopColor, inherited);
5097 // flood-color:
5098 if (eCSSUnit_Initial == SVGData.mFloodColor.GetUnit()) {
5099 svgReset->mFloodColor = NS_RGB(0, 0, 0);
5100 } else {
5101 SetColor(SVGData.mFloodColor, parentSVGReset->mFloodColor,
5102 mPresContext, aContext, svgReset->mFloodColor, inherited);
5105 // lighting-color:
5106 if (eCSSUnit_Initial == SVGData.mLightingColor.GetUnit()) {
5107 svgReset->mLightingColor = NS_RGB(255, 255, 255);
5108 } else {
5109 SetColor(SVGData.mLightingColor, parentSVGReset->mLightingColor,
5110 mPresContext, aContext, svgReset->mLightingColor, inherited);
5113 // clip-path: url, none, inherit
5114 if (eCSSUnit_URL == SVGData.mClipPath.GetUnit()) {
5115 svgReset->mClipPath = SVGData.mClipPath.GetURLValue();
5116 } else if (eCSSUnit_None == SVGData.mClipPath.GetUnit() ||
5117 eCSSUnit_Initial == SVGData.mClipPath.GetUnit()) {
5118 svgReset->mClipPath = nsnull;
5119 } else if (eCSSUnit_Inherit == SVGData.mClipPath.GetUnit()) {
5120 inherited = PR_TRUE;
5121 svgReset->mClipPath = parentSVGReset->mClipPath;
5124 // stop-opacity:
5125 SetSVGOpacity(SVGData.mStopOpacity, parentSVGReset->mStopOpacity,
5126 svgReset->mStopOpacity, inherited);
5128 // flood-opacity:
5129 SetSVGOpacity(SVGData.mFloodOpacity, parentSVGReset->mFloodOpacity,
5130 svgReset->mFloodOpacity, inherited);
5132 // dominant-baseline: enum, auto, inherit
5133 if (eCSSUnit_Enumerated == SVGData.mDominantBaseline.GetUnit()) {
5134 svgReset->mDominantBaseline = SVGData.mDominantBaseline.GetIntValue();
5136 else if (eCSSUnit_Auto == SVGData.mDominantBaseline.GetUnit() ||
5137 eCSSUnit_Initial == SVGData.mDominantBaseline.GetUnit()) {
5138 svgReset->mDominantBaseline = NS_STYLE_DOMINANT_BASELINE_AUTO;
5140 else if (eCSSUnit_Inherit == SVGData.mDominantBaseline.GetUnit()) {
5141 inherited = PR_TRUE;
5142 svgReset->mDominantBaseline = parentSVGReset->mDominantBaseline;
5145 // filter: url, none, inherit
5146 if (eCSSUnit_URL == SVGData.mFilter.GetUnit()) {
5147 svgReset->mFilter = SVGData.mFilter.GetURLValue();
5148 } else if (eCSSUnit_None == SVGData.mFilter.GetUnit() ||
5149 eCSSUnit_Initial == SVGData.mFilter.GetUnit()) {
5150 svgReset->mFilter = nsnull;
5151 } else if (eCSSUnit_Inherit == SVGData.mFilter.GetUnit()) {
5152 inherited = PR_TRUE;
5153 svgReset->mFilter = parentSVGReset->mFilter;
5156 // mask: url, none, inherit
5157 if (eCSSUnit_URL == SVGData.mMask.GetUnit()) {
5158 svgReset->mMask = SVGData.mMask.GetURLValue();
5159 } else if (eCSSUnit_None == SVGData.mMask.GetUnit() ||
5160 eCSSUnit_Initial == SVGData.mMask.GetUnit()) {
5161 svgReset->mMask = nsnull;
5162 } else if (eCSSUnit_Inherit == SVGData.mMask.GetUnit()) {
5163 inherited = PR_TRUE;
5164 svgReset->mMask = parentSVGReset->mMask;
5167 COMPUTE_END_RESET(SVGReset, svgReset)
5169 #endif
5171 inline const void*
5172 nsRuleNode::GetParentData(const nsStyleStructID aSID)
5174 NS_PRECONDITION(mDependentBits & nsCachedStyleData::GetBitForSID(aSID),
5175 "should be called when node depends on parent data");
5176 NS_ASSERTION(mStyleData.GetStyleData(aSID) == nsnull,
5177 "both struct and dependent bits present");
5178 // Walk up the rule tree from this rule node (towards less specific
5179 // rules).
5180 PRUint32 bit = nsCachedStyleData::GetBitForSID(aSID);
5181 nsRuleNode *ruleNode = mParent;
5182 while (ruleNode->mDependentBits & bit) {
5183 NS_ASSERTION(ruleNode->mStyleData.GetStyleData(aSID) == nsnull,
5184 "both struct and dependent bits present");
5185 ruleNode = ruleNode->mParent;
5188 return ruleNode->mStyleData.GetStyleData(aSID);
5191 #define STYLE_STRUCT(name_, checkdata_cb_, ctor_args_) \
5192 inline const nsStyle##name_ * \
5193 nsRuleNode::GetParent##name_() \
5195 NS_PRECONDITION(mDependentBits & \
5196 nsCachedStyleData::GetBitForSID(eStyleStruct_##name_), \
5197 "should be called when node depends on parent data"); \
5198 NS_ASSERTION(mStyleData.GetStyle##name_() == nsnull, \
5199 "both struct and dependent bits present"); \
5200 /* Walk up the rule tree from this rule node (towards less specific */ \
5201 /* rules). */ \
5202 PRUint32 bit = nsCachedStyleData::GetBitForSID(eStyleStruct_##name_); \
5203 nsRuleNode *ruleNode = mParent; \
5204 while (ruleNode->mDependentBits & bit) { \
5205 NS_ASSERTION(ruleNode->mStyleData.GetStyle##name_() == nsnull, \
5206 "both struct and dependent bits present"); \
5207 ruleNode = ruleNode->mParent; \
5210 return ruleNode->mStyleData.GetStyle##name_(); \
5212 #include "nsStyleStructList.h"
5213 #undef STYLE_STRUCT
5215 const void*
5216 nsRuleNode::GetStyleData(nsStyleStructID aSID,
5217 nsStyleContext* aContext,
5218 PRBool aComputeData)
5220 const void *data;
5221 if (mDependentBits & nsCachedStyleData::GetBitForSID(aSID)) {
5222 // We depend on an ancestor for this struct since the cached struct
5223 // it has is also appropriate for this rule node. Just go up the
5224 // rule tree and return the first cached struct we find.
5225 data = GetParentData(aSID);
5226 NS_ASSERTION(data, "dependent bits set but no cached struct present");
5227 return data;
5230 data = mStyleData.GetStyleData(aSID);
5231 if (NS_LIKELY(data != nsnull))
5232 return data; // We have a fully specified struct. Just return it.
5234 if (NS_UNLIKELY(!aComputeData))
5235 return nsnull;
5237 // Nothing is cached. We'll have to delve further and examine our rules.
5238 #define STYLE_STRUCT_TEST aSID
5239 #define STYLE_STRUCT(name, checkdata_cb, ctor_args) \
5240 data = Get##name##Data(aContext);
5241 #include "nsStyleStructList.h"
5242 #undef STYLE_STRUCT
5243 #undef STYLE_STRUCT_TEST
5245 if (NS_LIKELY(data != nsnull))
5246 return data;
5248 NS_NOTREACHED("could not create style struct");
5249 // To ensure that |GetStyleData| never returns null (even when we're
5250 // out of memory), we'll get the style set and get a copy of the
5251 // default values for the given style struct from the set. Note that
5252 // this works fine even if |this| is a rule node that has been
5253 // destroyed (leftover from a previous rule tree) but is somehow still
5254 // used.
5255 return mPresContext->PresShell()->StyleSet()->
5256 DefaultStyleData()->GetStyleData(aSID);
5259 // See comments above in GetStyleData for an explanation of what the
5260 // code below does.
5261 #define STYLE_STRUCT(name_, checkdata_cb_, ctor_args_) \
5262 const nsStyle##name_* \
5263 nsRuleNode::GetStyle##name_(nsStyleContext* aContext, PRBool aComputeData) \
5265 const nsStyle##name_ *data; \
5266 if (mDependentBits & \
5267 nsCachedStyleData::GetBitForSID(eStyleStruct_##name_)) { \
5268 data = GetParent##name_(); \
5269 NS_ASSERTION(data, "dependent bits set but no cached struct present"); \
5270 return data; \
5273 data = mStyleData.GetStyle##name_(); \
5274 if (NS_LIKELY(data != nsnull)) \
5275 return data; \
5277 if (NS_UNLIKELY(!aComputeData)) \
5278 return nsnull; \
5280 data = \
5281 static_cast<const nsStyle##name_ *>(Get##name_##Data(aContext)); \
5283 if (NS_LIKELY(data != nsnull)) \
5284 return data; \
5286 NS_NOTREACHED("could not create style struct"); \
5287 return \
5288 static_cast<const nsStyle##name_ *>( \
5289 mPresContext->PresShell()->StyleSet()-> \
5290 DefaultStyleData()->GetStyleData(eStyleStruct_##name_)); \
5292 #include "nsStyleStructList.h"
5293 #undef STYLE_STRUCT
5295 void
5296 nsRuleNode::Mark()
5298 for (nsRuleNode *node = this;
5299 node && !(node->mDependentBits & NS_RULE_NODE_GC_MARK);
5300 node = node->mParent)
5301 node->mDependentBits |= NS_RULE_NODE_GC_MARK;
5304 PR_STATIC_CALLBACK(PLDHashOperator)
5305 SweepRuleNodeChildren(PLDHashTable *table, PLDHashEntryHdr *hdr,
5306 PRUint32 number, void *arg)
5308 ChildrenHashEntry *entry = static_cast<ChildrenHashEntry*>(hdr);
5309 if (entry->mRuleNode->Sweep())
5310 return PL_DHASH_REMOVE; // implies NEXT, unless |ed with STOP
5311 return PL_DHASH_NEXT;
5314 PRBool
5315 nsRuleNode::Sweep()
5317 // If we're not marked, then we have to delete ourself.
5318 // However, we never allow the root node to GC itself, because nsStyleSet
5319 // wants to hold onto the root node and not worry about re-creating a
5320 // rule walker if the root node is deleted.
5321 if (!(mDependentBits & NS_RULE_NODE_GC_MARK) && !IsRoot()) {
5322 Destroy();
5323 return PR_TRUE;
5326 // Clear our mark, for the next time around.
5327 mDependentBits &= ~NS_RULE_NODE_GC_MARK;
5329 // Call sweep on the children, since some may not be marked, and
5330 // remove any deleted children from the child lists.
5331 if (HaveChildren()) {
5332 if (ChildrenAreHashed()) {
5333 PLDHashTable *children = ChildrenHash();
5334 PL_DHashTableEnumerate(children, SweepRuleNodeChildren, nsnull);
5335 } else {
5336 for (nsRuleNode **children = ChildrenListPtr(); *children; ) {
5337 nsRuleNode *next = (*children)->mNextSibling;
5338 if ((*children)->Sweep()) {
5339 // This rule node was destroyed, so implicitly advance by
5340 // making *children point to the next entry.
5341 *children = next;
5342 } else {
5343 // Advance.
5344 children = &(*children)->mNextSibling;
5349 return PR_FALSE;
5352 /* static */ PRBool
5353 nsRuleNode::HasAuthorSpecifiedRules(nsStyleContext* aStyleContext,
5354 PRUint32 ruleTypeMask)
5356 nsRuleDataColor colorData;
5357 nsRuleDataMargin marginData;
5358 PRUint32 nValues = 0;
5360 PRUint32 inheritBits = 0;
5361 if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BACKGROUND)
5362 inheritBits |= NS_STYLE_INHERIT_BIT(Background);
5364 if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BORDER)
5365 inheritBits |= NS_STYLE_INHERIT_BIT(Border);
5367 if (ruleTypeMask & NS_AUTHOR_SPECIFIED_PADDING)
5368 inheritBits |= NS_STYLE_INHERIT_BIT(Padding);
5370 /* We're relying on the use of |aStyleContext| not mutating it! */
5371 nsRuleData ruleData(inheritBits,
5372 aStyleContext->PresContext(), aStyleContext);
5373 ruleData.mColorData = &colorData;
5374 ruleData.mMarginData = &marginData;
5376 nsCSSValue* backgroundValues[] = {
5377 &colorData.mBackColor,
5378 &colorData.mBackImage
5381 nsCSSValue* borderValues[] = {
5382 &marginData.mBorderColor.mTop,
5383 &marginData.mBorderStyle.mTop,
5384 &marginData.mBorderWidth.mTop,
5385 &marginData.mBorderColor.mRight,
5386 &marginData.mBorderStyle.mRight,
5387 &marginData.mBorderWidth.mRight,
5388 &marginData.mBorderColor.mBottom,
5389 &marginData.mBorderStyle.mBottom,
5390 &marginData.mBorderWidth.mBottom,
5391 &marginData.mBorderColor.mLeft,
5392 &marginData.mBorderStyle.mLeft,
5393 &marginData.mBorderWidth.mLeft
5394 // XXX add &marginData.mBorder{Start,End}{Width,Color,Style}
5397 nsCSSValue* paddingValues[] = {
5398 &marginData.mPadding.mTop,
5399 &marginData.mPadding.mRight,
5400 &marginData.mPadding.mBottom,
5401 &marginData.mPadding.mLeft,
5402 &marginData.mPaddingStart,
5403 &marginData.mPaddingEnd
5406 nsCSSValue* values[NS_ARRAY_LENGTH(backgroundValues) +
5407 NS_ARRAY_LENGTH(borderValues) +
5408 NS_ARRAY_LENGTH(paddingValues)];
5410 if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BACKGROUND) {
5411 memcpy(&values[nValues], backgroundValues, NS_ARRAY_LENGTH(backgroundValues) * sizeof(nsCSSValue*));
5412 nValues += NS_ARRAY_LENGTH(backgroundValues);
5415 if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BORDER) {
5416 memcpy(&values[nValues], borderValues, NS_ARRAY_LENGTH(borderValues) * sizeof(nsCSSValue*));
5417 nValues += NS_ARRAY_LENGTH(borderValues);
5420 if (ruleTypeMask & NS_AUTHOR_SPECIFIED_PADDING) {
5421 memcpy(&values[nValues], paddingValues, NS_ARRAY_LENGTH(paddingValues) * sizeof(nsCSSValue*));
5422 nValues += NS_ARRAY_LENGTH(paddingValues);
5425 // We need to be careful not to count styles covered up by
5426 // user-important or UA-important declarations.
5427 for (nsRuleNode* ruleNode = aStyleContext->GetRuleNode(); ruleNode;
5428 ruleNode = ruleNode->GetParent()) {
5429 nsIStyleRule *rule = ruleNode->GetRule();
5430 if (rule) {
5431 ruleData.mLevel = ruleNode->GetLevel();
5432 ruleData.mIsImportantRule = ruleNode->IsImportantRule();
5433 rule->MapRuleInfoInto(&ruleData);
5434 // Do the same nulling out as in GetBorderData, GetBackgroundData
5435 // or GetPaddingData.
5436 // We are sharing with some style rule. It really owns the data.
5437 marginData.mBoxShadow = nsnull;
5439 if (ruleData.mLevel == nsStyleSet::eAgentSheet ||
5440 ruleData.mLevel == nsStyleSet::eUserSheet) {
5441 // This is a rule whose effect we want to ignore, so if any of
5442 // the properties we care about were set, set them to the dummy
5443 // value that they'll never otherwise get.
5444 for (PRUint32 i = 0; i < nValues; ++i)
5445 if (values[i]->GetUnit() != eCSSUnit_Null)
5446 values[i]->SetDummyValue();
5447 } else {
5448 // If any of the values we care about was set by the above rule,
5449 // we have author style.
5450 for (PRUint32 i = 0; i < nValues; ++i)
5451 if (values[i]->GetUnit() != eCSSUnit_Null &&
5452 values[i]->GetUnit() != eCSSUnit_Dummy) // see above
5453 return PR_TRUE;
5458 return PR_FALSE;