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
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.
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"
52 #include "nsIServiceManager.h"
53 #include "nsIDeviceContext.h"
54 #include "nsILookAndFeel.h"
55 #include "nsIPresShell.h"
56 #include "nsIThebesFontMetrics.h"
58 #include "nsStyleUtil.h"
59 #include "nsCSSPseudoElements.h"
60 #include "nsThemeConstants.h"
63 #include "nsStyleContext.h"
64 #include "nsStyleSet.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
,
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.
113 ChildrenHashMatchEntry
,
114 PL_DHashMoveEntryStub
,
115 PL_DHashClearEntryStub
,
116 PL_DHashFinalizeStub
,
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
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?)
139 case NS_STYLE_DISPLAY_INLINE_TABLE
:
140 // make inline tables into tables
141 display
= NS_STYLE_DISPLAY_TABLE
;
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);
166 static nscoord
CalcLengthWith(const nsCSSValue
& aValue
,
168 const nsStyleFont
* aStyleFont
,
169 nsStyleContext
* aStyleContext
,
170 nsPresContext
* aPresContext
,
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
;
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
;
196 return NSToCoordRound(aValue
.GetFloatValue() * float(aFontSize
));
197 // XXX scale against font metrics height instead?
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
);
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() *
228 NS_NOTREACHED("unexpected unit");
234 static nscoord
CalcLength(const nsCSSValue
& aValue
,
235 nsStyleContext
* aStyleContext
,
236 nsPresContext
* aPresContext
,
239 NS_ASSERTION(aStyleContext
, "Must have style data");
241 return CalcLengthWith(aValue
, -1, nsnull
, aStyleContext
, aPresContext
, aInherited
);
245 nsRuleNode::CalcLengthWithInitialFont(nsPresContext
* aPresContext
,
246 const nsCSSValue
& aValue
)
248 nsStyleFont
defaultFont(aPresContext
);
250 return CalcLengthWith(aValue
, -1, &defaultFont
, nsnull
, aPresContext
,
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
) {
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();
347 result
= PR_FALSE
; // didn't set anything
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();
363 else if (eCSSUnit_String
== unit
) {
365 aValue
.GetStringValue(value
);
367 if (NS_ColorNameToRGB(value
, &rgba
)) {
372 else if (eCSSUnit_EnumColor
== unit
) {
373 PRInt32 intValue
= aValue
.GetIntValue();
375 nsILookAndFeel
* look
= aPresContext
->LookAndFeel();
376 nsILookAndFeel::nsColorID colorID
= (nsILookAndFeel::nsColorID
) intValue
;
377 if (NS_SUCCEEDED(look
->GetColor(colorID
, aResult
))) {
383 case NS_COLOR_MOZ_HYPERLINKTEXT
:
384 aResult
= aPresContext
->DefaultLinkColor();
386 case NS_COLOR_MOZ_VISITEDHYPERLINKTEXT
:
387 aResult
= aPresContext
->DefaultVisitedLinkColor();
389 case NS_COLOR_MOZ_ACTIVEHYPERLINKTEXT
:
390 aResult
= aPresContext
->DefaultActiveLinkColor();
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
;
399 NS_NOTREACHED("Should never have an unknown negative colorID.");
405 else if (eCSSUnit_Inherit
== unit
) {
406 aResult
= aParentColor
;
408 aInherited
= PR_TRUE
;
413 // Overloaded new operator. Initializes the memory to 0 and relies on an arena
414 // (which comes from the presShell) to perform the allocation.
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.
436 nsRuleNode::DestroyInternal(nsRuleNode
***aDestroyQueueTail
)
438 nsRuleNode
*destroyQueue
, **destroyQueueTail
;
439 if (aDestroyQueueTail
) {
440 destroyQueueTail
= *aDestroyQueueTail
;
442 destroyQueue
= nsnull
;
443 destroyQueueTail
= &destroyQueue
;
446 if (ChildrenAreHashed()) {
447 PLDHashTable
*children
= ChildrenHash();
448 PL_DHashTableEnumerate(children
, EnqueueRuleNodeChildren
,
450 *destroyQueueTail
= nsnull
; // ensure null-termination
451 PL_DHashTableDestroy(children
);
452 } else if (HaveChildren()) {
453 *destroyQueueTail
= ChildrenList();
455 destroyQueueTail
= &(*destroyQueueTail
)->mNextSibling
;
456 } while (*destroyQueueTail
);
458 mChildrenTaggedPtr
= nsnull
;
460 if (aDestroyQueueTail
) {
461 // Our caller destroys the queue.
462 *aDestroyQueueTail
= destroyQueueTail
;
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
;
470 NS_ASSERTION(destroyQueueTail
== &cur
->mNextSibling
, "mangled list");
471 destroyQueueTail
= &destroyQueue
;
473 cur
->DestroyInternal(&destroyQueueTail
);
477 // Destroy ourselves.
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
,
496 : mPresContext(aContext
),
499 mChildrenTaggedPtr(nsnull
),
500 mDependentBits((PRUint32(aLevel
) << NS_RULE_NODE_LEVEL_SHIFT
) |
501 (aIsImportant
? NS_RULE_NODE_IS_IMPORTANT
: 0)),
504 MOZ_COUNT_CTOR(nsRuleNode
);
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
);
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()) {
528 nsRuleNode
* curr
= ChildrenList();
529 while (curr
&& curr
->GetKey() != key
) {
530 curr
= curr
->mNextSibling
;
535 else if (numKids
>= kMaxChildrenInList
)
536 ConvertChildrenToHash();
539 if (ChildrenAreHashed()) {
540 ChildrenHashEntry
*entry
= static_cast<ChildrenHashEntry
*>
541 (PL_DHashTableOperate(ChildrenHash(), &key
, PL_DHASH_ADD
));
545 if (entry
->mRuleNode
)
546 next
= entry
->mRuleNode
;
548 next
= entry
->mRuleNode
= new (mPresContext
)
549 nsRuleNode(mPresContext
, this, aRule
, aLevel
, aIsImportantRule
);
551 PL_DHashTableRawRemove(ChildrenHash(), entry
);
556 // Create the new entry in our list.
557 next
= new (mPresContext
)
558 nsRuleNode(mPresContext
, this, aRule
, aLevel
, aIsImportantRule
);
562 next
->mNextSibling
= ChildrenList();
563 SetChildrenList(next
);
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);
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
);
590 nsRuleNode::PropagateNoneBit(PRUint32 aBit
, nsRuleNode
* aHighestNode
)
592 nsRuleNode
* curr
= this;
594 NS_ASSERTION(!(curr
->mNoneBits
& aBit
), "propagating too far");
595 curr
->mNoneBits
|= aBit
;
596 if (curr
== aHighestNode
)
598 curr
= curr
->mParent
;
603 nsRuleNode::PropagateDependentBit(PRUint32 aBit
, nsRuleNode
* aHighestNode
)
605 for (nsRuleNode
* curr
= this; curr
!= aHighestNode
; curr
= curr
->mParent
) {
606 if (curr
->mDependentBits
& aBit
) {
608 while (curr
!= aHighestNode
) {
609 NS_ASSERTION(curr
->mDependentBits
& aBit
, "bit not set");
610 curr
= curr
->mParent
;
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
628 struct PropertyCheckData
{
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
;
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
656 ExamineCSSValue(const nsCSSValue
& aValue
,
657 PRUint32
& aSpecifiedCount
, PRUint32
& aInheritedCount
)
659 if (aValue
.GetUnit() != eCSSUnit_Null
) {
661 if (aValue
.GetUnit() == eCSSUnit_Inherit
) {
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
);
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
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
)) ||
708 fontData
.mScriptLevel
.GetUnit() == eCSSUnit_Integer
||
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
;
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
;
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"
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"
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"
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"
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"
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
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), \
924 #include "nsStyleStructList.h"
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)
978 AreAllMathMLPropertiesUndefined(const nsCSSFont
& aRuleData
)
980 return aRuleData
.mScriptLevel
.GetUnit() == eCSSUnit_Null
&&
981 aRuleData
.mScriptSizeMultiplier
.GetUnit() == eCSSUnit_Null
&&
982 aRuleData
.mScriptMinSize
.GetUnit() == eCSSUnit_Null
;
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
;
1002 switch (prop
->type
) {
1004 case eCSSType_Value
:
1006 ExamineCSSValue(ValueAtOffset(aRuleDataStruct
, prop
->offset
),
1007 specified
, inherited
);
1012 ExamineCSSRect(RectAtOffset(aRuleDataStruct
, prop
->offset
),
1013 specified
, inherited
);
1016 case eCSSType_ValuePair
:
1018 ExamineCSSValuePair(ValuePairAtOffset(aRuleDataStruct
, prop
->offset
),
1019 specified
, inherited
);
1022 case eCSSType_ValueList
:
1025 const nsCSSValueList
* valueList
=
1026 ValueListAtOffset(aRuleDataStruct
, prop
->offset
);
1029 if (eCSSUnit_Inherit
== valueList
->mValue
.GetUnit()) {
1036 case eCSSType_ValuePairList
:
1039 const nsCSSValuePairList
* quotes
=
1040 ValuePairListAtOffset(aRuleDataStruct
, prop
->offset
);
1043 if (eCSSUnit_Inherit
== quotes
->mXValue
.GetUnit()) {
1051 NS_NOTREACHED("unknown type");
1057 printf("CheckSpecifiedProperties: SID=%d total=%d spec=%d inh=%d.\n",
1058 aSID
, total
, specified
, inherited
);
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");
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
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())
1089 result
= eRuleFullReset
;
1091 result
= eRuleFullMixed
;
1092 } else if (specified
== 0)
1094 else if (specified
== inherited
)
1095 result
= eRulePartialInherited
;
1096 else if (inherited
== 0)
1097 result
= eRulePartialReset
;
1099 result
= eRulePartialMixed
;
1101 if (structData
->callback
) {
1102 result
= (*structData
->callback
)(aRuleDataStruct
, result
);
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
);
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
);
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.
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
);
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.
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
);
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
);
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
);
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
);
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
);
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
;
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
);
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
);
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
);
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
);
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
);
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
);
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.
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.
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
);
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
);
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.
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
);
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
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
);
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
)
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
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
1408 startStruct
= ruleNode
->mStyleData
.GetStyleData(aSID
);
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
;
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
);
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
1460 PropagateDependentBit(bit
, ruleNode
);
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
;
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.
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"
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.
1519 nsRuleNode::SetDefaultOnRoot(const nsStyleStructID aSID
, nsStyleContext
* aContext
)
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
);
1533 fontData
->mFont
.size
= fontData
->mSize
;
1535 aContext
->SetStyle(eStyleStruct_Font
, fontData
);
1539 case eStyleStruct_Display
:
1541 nsStyleDisplay
* disp
= new (mPresContext
) nsStyleDisplay();
1542 if (NS_LIKELY(disp
!= nsnull
)) {
1543 aContext
->SetStyle(eStyleStruct_Display
, disp
);
1547 case eStyleStruct_Visibility
:
1549 nsStyleVisibility
* vis
= new (mPresContext
) nsStyleVisibility(mPresContext
);
1550 if (NS_LIKELY(vis
!= nsnull
)) {
1551 aContext
->SetStyle(eStyleStruct_Visibility
, vis
);
1555 case eStyleStruct_Text
:
1557 nsStyleText
* text
= new (mPresContext
) nsStyleText();
1558 if (NS_LIKELY(text
!= nsnull
)) {
1559 aContext
->SetStyle(eStyleStruct_Text
, text
);
1563 case eStyleStruct_TextReset
:
1565 nsStyleTextReset
* text
= new (mPresContext
) nsStyleTextReset();
1566 if (NS_LIKELY(text
!= nsnull
)) {
1567 aContext
->SetStyle(eStyleStruct_TextReset
, text
);
1571 case eStyleStruct_Color
:
1573 nsStyleColor
* color
= new (mPresContext
) nsStyleColor(mPresContext
);
1574 if (NS_LIKELY(color
!= nsnull
)) {
1575 aContext
->SetStyle(eStyleStruct_Color
, color
);
1579 case eStyleStruct_Background
:
1581 nsStyleBackground
* bg
= new (mPresContext
) nsStyleBackground(mPresContext
);
1582 if (NS_LIKELY(bg
!= nsnull
)) {
1583 aContext
->SetStyle(eStyleStruct_Background
, bg
);
1587 case eStyleStruct_Margin
:
1589 nsStyleMargin
* margin
= new (mPresContext
) nsStyleMargin();
1590 if (NS_LIKELY(margin
!= nsnull
)) {
1591 aContext
->SetStyle(eStyleStruct_Margin
, margin
);
1595 case eStyleStruct_Border
:
1597 nsStyleBorder
* border
= new (mPresContext
) nsStyleBorder(mPresContext
);
1598 if (NS_LIKELY(border
!= nsnull
)) {
1599 aContext
->SetStyle(eStyleStruct_Border
, border
);
1603 case eStyleStruct_Padding
:
1605 nsStylePadding
* padding
= new (mPresContext
) nsStylePadding();
1606 if (NS_LIKELY(padding
!= nsnull
)) {
1607 aContext
->SetStyle(eStyleStruct_Padding
, padding
);
1611 case eStyleStruct_Outline
:
1613 nsStyleOutline
* outline
= new (mPresContext
) nsStyleOutline(mPresContext
);
1614 if (NS_LIKELY(outline
!= nsnull
)) {
1615 aContext
->SetStyle(eStyleStruct_Outline
, outline
);
1619 case eStyleStruct_List
:
1621 nsStyleList
* list
= new (mPresContext
) nsStyleList();
1622 if (NS_LIKELY(list
!= nsnull
)) {
1623 aContext
->SetStyle(eStyleStruct_List
, list
);
1627 case eStyleStruct_Position
:
1629 nsStylePosition
* pos
= new (mPresContext
) nsStylePosition();
1630 if (NS_LIKELY(pos
!= nsnull
)) {
1631 aContext
->SetStyle(eStyleStruct_Position
, pos
);
1635 case eStyleStruct_Table
:
1637 nsStyleTable
* table
= new (mPresContext
) nsStyleTable();
1638 if (NS_LIKELY(table
!= nsnull
)) {
1639 aContext
->SetStyle(eStyleStruct_Table
, table
);
1643 case eStyleStruct_TableBorder
:
1645 nsStyleTableBorder
* table
= new (mPresContext
) nsStyleTableBorder(mPresContext
);
1646 if (NS_LIKELY(table
!= nsnull
)) {
1647 aContext
->SetStyle(eStyleStruct_TableBorder
, table
);
1651 case eStyleStruct_Content
:
1653 nsStyleContent
* content
= new (mPresContext
) nsStyleContent();
1654 if (NS_LIKELY(content
!= nsnull
)) {
1655 aContext
->SetStyle(eStyleStruct_Content
, content
);
1659 case eStyleStruct_Quotes
:
1661 nsStyleQuotes
* quotes
= new (mPresContext
) nsStyleQuotes();
1662 if (NS_LIKELY(quotes
!= nsnull
)) {
1663 aContext
->SetStyle(eStyleStruct_Quotes
, quotes
);
1667 case eStyleStruct_UserInterface
:
1669 nsStyleUserInterface
* ui
= new (mPresContext
) nsStyleUserInterface();
1670 if (NS_LIKELY(ui
!= nsnull
)) {
1671 aContext
->SetStyle(eStyleStruct_UserInterface
, ui
);
1675 case eStyleStruct_UIReset
:
1677 nsStyleUIReset
* ui
= new (mPresContext
) nsStyleUIReset();
1678 if (NS_LIKELY(ui
!= nsnull
)) {
1679 aContext
->SetStyle(eStyleStruct_UIReset
, ui
);
1684 case eStyleStruct_XUL
:
1686 nsStyleXUL
* xul
= new (mPresContext
) nsStyleXUL();
1687 if (NS_LIKELY(xul
!= nsnull
)) {
1688 aContext
->SetStyle(eStyleStruct_XUL
, xul
);
1693 case eStyleStruct_Column
:
1695 nsStyleColumn
* column
= new (mPresContext
) nsStyleColumn(mPresContext
);
1696 if (NS_LIKELY(column
!= nsnull
)) {
1697 aContext
->SetStyle(eStyleStruct_Column
, column
);
1703 case eStyleStruct_SVG
:
1705 nsStyleSVG
* svg
= new (mPresContext
) nsStyleSVG();
1706 if (NS_LIKELY(svg
!= nsnull
)) {
1707 aContext
->SetStyle(eStyleStruct_SVG
, svg
);
1712 case eStyleStruct_SVGReset
:
1714 nsStyleSVGReset
* svgReset
= new (mPresContext
) nsStyleSVGReset();
1715 if (NS_LIKELY(svgReset
!= nsnull
)) {
1716 aContext
->SetStyle(eStyleStruct_SVGReset
, svgReset
);
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
1748 nsRuleNode::AdjustLogicalBoxProp(nsStyleContext
* aContext
,
1749 const nsCSSValue
& aLTRSource
,
1750 const nsCSSValue
& aRTLSource
,
1751 const nsCSSValue
& aLTRLogicalValue
,
1752 const nsCSSValue
& aRTLLogicalValue
,
1754 nsCSSRect
& aValueRect
,
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
) {
1770 aValueRect
.*(nsCSSRect::sides
[aSide
]) = aLTRLogicalValue
;
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
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_(); \
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)); \
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; \
1820 data_ = new (mPresContext) nsStyle##type_(*parentdata_); \
1822 data_ = new (mPresContext) nsStyle##type_ ctorargs_; \
1825 data_ = new (mPresContext) nsStyle##type_ ctorargs_; \
1828 if (NS_UNLIKELY(!data_)) \
1829 return nsnull; /* Out Of Memory */ \
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
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_; \
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)); \
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_) \
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_); \
1893 /* We were fully specified and can therefore be cached right on the */ \
1895 if (!aHighestNode->mStyleData.mInheritedData) { \
1896 aHighestNode->mStyleData.mInheritedData = \
1897 new (mPresContext) nsInheritedStyleData; \
1898 if (NS_UNLIKELY(!aHighestNode->mStyleData.mInheritedData)) { \
1899 data_->Destroy(mPresContext); \
1903 aHighestNode->mStyleData.mInheritedData->m##type_##Data = data_; \
1904 /* Propagate the bit down. */ \
1905 PropagateDependentBit(NS_STYLE_INHERIT_BIT(type_), aHighestNode); \
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_) \
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_); \
1922 /* We were fully specified and can therefore be cached right on the */ \
1924 if (!aHighestNode->mStyleData.mResetData) { \
1925 aHighestNode->mStyleData.mResetData = \
1926 new (mPresContext) nsResetStyleData; \
1927 if (NS_UNLIKELY(!aHighestNode->mStyleData.mResetData)) { \
1928 data_->Destroy(mPresContext); \
1932 aHighestNode->mStyleData.mResetData->m##type_##Data = data_; \
1933 /* Propagate the bit down. */ \
1934 PropagateDependentBit(NS_STYLE_INHERIT_BIT(type_), aHighestNode); \
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.
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
,
1978 // Compute the size we could get via scriptlevel change
1979 nscoord scriptLevelSize
=
1980 NSToCoordRound(PR_MIN(aParentFont
->mSize
*scriptLevelScale
,
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
1987 return aParentFont
->mSize
;
1989 // We can decrease, so apply constraint #1
1990 return PR_MAX(minScriptSize
, scriptLevelSize
);
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
));
2001 nsRuleNode::SetFontSize(nsPresContext
* aPresContext
,
2002 const nsRuleDataFont
& aFontData
,
2003 const nsStyleFont
* aFont
,
2004 const nsStyleFont
* aParentFont
,
2006 const nsFont
& aSystemFont
,
2007 nscoord aParentSize
,
2008 nscoord aScriptLevelAdjustedParentSize
,
2009 PRBool aUsedStartStruct
,
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
);
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");
2050 *aSize
= nsStyleUtil::FindNextSmallerFontSize(parentSize
,
2051 baseSize
, scaleFactor
, aPresContext
, eFontSize_CSS
);
2052 NS_ASSERTION(*aSize
< parentSize
||
2053 parentSize
<= nsPresContext::CSSPixelsToAppUnits(1),
2054 "FindNextSmallerFontSize failed");
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
2074 *aSize
= NSToCoordRound(aParentSize
*
2075 aFontData
.mSize
.GetPercentValue());
2078 else if (eCSSUnit_System_Font
== aFontData
.mSize
.GetUnit()) {
2079 // this becomes our cascading size
2080 *aSize
= aSystemFont
.size
;
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
2088 *aSize
= aScriptLevelAdjustedParentSize
;
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.
2097 NS_ASSERTION(eCSSUnit_Null
== aFontData
.mSize
.GetUnit(),
2098 "What kind of font-size value is this?");
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
;
2114 // We want to zoom the cascaded size so that em-based measurements,
2115 // line-heights, etc., work.
2117 *aSize
= nsStyleFont::ZoomText(aPresContext
, *aSize
);
2121 static PRInt8
ClampTo8Bit(PRInt32 aValue
) {
2126 return PRInt8(aValue
);
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
,
2137 const nsFont
* defaultVariableFont
=
2138 aPresContext
->GetDefaultFont(kPresContext_DefaultVariableFont_ID
);
2140 // -moz-system-font: enum (never inherit!)
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
,
2170 systemFont
.name
= defaultVariableFont
->name
;
2173 // XXXldb All of this platform-specific stuff should be in the
2174 // nsIDeviceContext implementations, not here.
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.
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
2195 PR_MAX(defaultVariableFont
->size
- aPresContext
->PointsToAppUnits(2), 0);
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
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();
2301 case NS_STYLE_FONT_WEIGHT_NORMAL
:
2302 case NS_STYLE_FONT_WEIGHT_BOLD
:
2303 aFont
->mFont
.weight
= value
;
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
);
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
;
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()) {
2356 aFont
->mScriptLevel
= ClampTo8Bit(aParentFont
->mScriptLevel
+ aFontData
.mScriptLevel
.GetIntValue());
2358 else if (eCSSUnit_Number
== aFontData
.mScriptLevel
.GetUnit()) {
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;
2371 // font-size: enum, length, percent, inherit
2372 nscoord scriptLevelAdjustedParentSize
= aParentFont
->mSize
;
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");
2381 SetFontSize(aPresContext
, aFontData
, aFont
, aParentFont
, &aFont
->mSize
,
2382 systemFont
, aParentFont
->mSize
, scriptLevelAdjustedParentSize
,
2383 aUsedStartStruct
, aInherited
);
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
;
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");
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
;
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
;
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
2435 nsRuleNode::SetGenericFont(nsPresContext
* aPresContext
,
2436 nsStyleContext
* aContext
,
2437 PRUint8 aGenericFontID
, nscoord aMinFontSize
,
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
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
;
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
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
2485 nsIStyleRule
*rule
= ruleNode
->GetRule();
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.
2498 fontData
.mFamily
.Reset();
2500 nsRuleNode::SetFont(aPresContext
, context
, aMinFontSize
,
2501 aGenericFontID
, fontData
, &parentFont
, aFont
,
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
,
2516 nsAutoString
*data
= static_cast<nsAutoString
*>(aData
);
2520 return PR_FALSE
; // stop enumeration
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
,
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
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
;
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
);
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
,
2624 PRUint32 arrayLength
= 0;
2625 for (nsCSSValueList
*list2
= aList
; list2
; list2
= list2
->mNext
)
2628 NS_ASSERTION(arrayLength
> 0, "Non-null text-shadow list, yet we counted 0 items.");
2629 nsCSSShadowArray
* shadowList
= new(arrayLength
) nsCSSShadowArray(arrayLength
);
2634 for (nsCSSShadowItem
* item
= shadowList
->ShadowAt(0);
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
);
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
);
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
,
2668 NS_ADDREF(shadowList
);
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
;
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()) {
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();
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
));
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
)
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
;
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
)
2868 nsRuleNode::ComputeUserInterfaceData(void* aStartStruct
,
2869 const nsRuleDataStruct
& aData
,
2870 nsStyleContext
* aContext
,
2871 nsRuleNode
* aHighestNode
,
2872 const RuleDetail aRuleDetail
,
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
;
2894 // The parser will never create a list that is *all* URL values --
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())
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();
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();
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
)
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
)
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
;
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
;
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);
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
) -
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
) -
3299 fullAuto
= PR_FALSE
;
3301 display
->mClipFlags
&= ~NS_STYLE_CLIP_TYPE_MASK
;
3303 display
->mClipFlags
|= NS_STYLE_CLIP_AUTO
;
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'
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'
3350 inherited
= PR_TRUE
;
3355 COMPUTE_END_RESET(Display
, display
)
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
;
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
);
3408 displayData
.mLang
.GetStringValue(lang
);
3409 visibility
->mLangGroup
= gLangService
->LookupLanguage(lang
);
3413 COMPUTE_END_INHERITED(Visibility
, visibility
)
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
,
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();
3438 SetColor(colorData
.mColor
, parentColor
->mColor
, mPresContext
, aContext
, color
->mColor
,
3442 COMPUTE_END_INHERITED(Color
, color
)
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
,
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
;
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
;
3567 case NS_STYLE_BG_POSITION_RIGHT
:
3568 bg
->mBackgroundXPosition
.mFloat
= 1.0f
;
3571 NS_NOTREACHED("unexpected value");
3573 case NS_STYLE_BG_POSITION_CENTER
:
3574 bg
->mBackgroundXPosition
.mFloat
= 0.5f
;
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
;
3606 case NS_STYLE_BG_POSITION_BOTTOM
:
3607 bg
->mBackgroundYPosition
.mFloat
= 1.0f
;
3610 NS_NOTREACHED("unexpected value");
3612 case NS_STYLE_BG_POSITION_CENTER
:
3613 bg
->mBackgroundYPosition
.mFloat
= 0.5f
;
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
)
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
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
)
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
,
3677 // -moz-box-shadow: none, list, inherit, initial
3678 nsCSSValueList
* list
= marginData
.mBoxShadow
;
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()) {
3688 border
->mBoxShadow
= GetShadowData(list
, aContext
, PR_TRUE
, inherited
);
3692 // border-width, border-*-width: length, enum, inherit
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 "
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
]);
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.
3787 // Some composite border color information has been specified for this
3789 border
->EnsureBorderColors();
3790 border
->ClearBorderColors(side
);
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
);
3803 // border-color, border-*-color: color, string, enum, inherit
3804 nsCSSRect
ourBorderColor(marginData
.mBorderColor
);
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
);
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
);
3835 border
->SetBorderColor(side
, borderColor
);
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
);
3849 case NS_STYLE_COLOR_MOZ_USE_TEXT_COLOR
:
3850 border
->SetBorderToForeground(side
);
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
;
3883 if (eCSSUnit_Array
== marginData
.mBorderImage
.GetUnit()) {
3884 nsCSSValue::Array
*arr
= marginData
.mBorderImage
.GetArrayValue();
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());
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
;
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
;
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
;
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
)
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
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
)
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
,
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
);
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
,
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
);
4028 #ifdef GFX_HAS_INVERT
4029 outline
->SetOutlineInitialColor();
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
);
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
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
)
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();
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
)
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
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
;
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
)
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
)
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
,
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
)
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
4345 nsAutoString buffer
;
4346 nsCSSValueList
* contentValue
= contentData
.mContent
;
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
);
4365 while (contentValue
) {
4367 contentValue
= contentValue
->mNext
;
4369 if (NS_SUCCEEDED(content
->AllocateContents(count
))) {
4370 const nsAutoString nullStr
;
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
++);
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;
4397 NS_ERROR("bad content value");
4401 NS_ERROR("bad content 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
);
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();
4418 data
.mContent
.mString
= nsnull
;
4420 contentValue
= contentValue
->mNext
;
4426 // counter-increment: [string [int]]+, none, inherit
4427 nsCSSValuePairList
* ourIncrement
= contentData
.mCounterIncrement
;
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()) {
4446 while (ourIncrement
) {
4448 ourIncrement
= ourIncrement
->mNext
;
4450 if (NS_SUCCEEDED(content
->AllocateCounterIncrements(count
))) {
4452 ourIncrement
= contentData
.mCounterIncrement
;
4453 while (ourIncrement
) {
4455 if (eCSSUnit_Integer
== ourIncrement
->mYValue
.GetUnit()) {
4456 increment
= ourIncrement
->mYValue
.GetIntValue();
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
;
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()) {
4491 ourReset
= ourReset
->mNext
;
4493 if (NS_SUCCEEDED(content
->AllocateCounterResets(count
))) {
4495 ourReset
= contentData
.mCounterReset
;
4498 if (eCSSUnit_Integer
== ourReset
->mYValue
.GetUnit()) {
4499 reset
= ourReset
->mYValue
.GetIntValue();
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
)
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
4532 nsAutoString buffer
;
4533 nsCSSValuePairList
* ourQuotes
= contentData
.mQuotes
;
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()) {
4555 ourQuotes
= ourQuotes
->mNext
;
4557 if (NS_SUCCEEDED(quotes
->AllocateQuotes(count
))) {
4559 ourQuotes
= contentData
.mQuotes
;
4561 ourQuotes
->mXValue
.GetStringValue(buffer
);
4562 ourQuotes
->mYValue
.GetStringValue(closeBuffer
);
4564 Unquote(closeBuffer
);
4565 quotes
->SetQuotesAt(count
++, buffer
, closeBuffer
);
4566 ourQuotes
= ourQuotes
->mNext
;
4572 COMPUTE_END_INHERITED(Quotes
, quotes
)
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
)
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
;
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
)
4761 SetSVGPaint(const nsCSSValuePair
& aValue
, const nsStyleSVGPaint
& parentPaint
,
4762 nsPresContext
* aPresContext
, nsStyleContext
*aContext
,
4763 nsStyleSVGPaint
& aResult
, nsStyleSVGPaintType aInitialPaintType
,
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);
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
;
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
) {
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
;
4862 SetSVGPaint(SVGData
.mFill
, parentSVG
->mFill
, mPresContext
, aContext
,
4863 svg
->mFill
, eStyleSVGPaintType_Color
, inherited
);
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
;
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
;
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
));
4959 svg
->mStrokeDasharrayLength
= 0;
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
;
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
;
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
;
5039 SetSVGOpacity(SVGData
.mStrokeOpacity
, parentSVG
->mStrokeOpacity
,
5040 svg
->mStrokeOpacity
, inherited
);
5043 if (eCSSUnit_Initial
== SVGData
.mStrokeWidth
.GetUnit()) {
5044 svg
->mStrokeWidth
.SetCoordValue(nsPresContext::CSSPixelsToAppUnits(1));
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
)
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
)
5090 if (eCSSUnit_Initial
== SVGData
.mStopColor
.GetUnit()) {
5091 svgReset
->mStopColor
= NS_RGB(0, 0, 0);
5093 SetColor(SVGData
.mStopColor
, parentSVGReset
->mStopColor
,
5094 mPresContext
, aContext
, svgReset
->mStopColor
, inherited
);
5098 if (eCSSUnit_Initial
== SVGData
.mFloodColor
.GetUnit()) {
5099 svgReset
->mFloodColor
= NS_RGB(0, 0, 0);
5101 SetColor(SVGData
.mFloodColor
, parentSVGReset
->mFloodColor
,
5102 mPresContext
, aContext
, svgReset
->mFloodColor
, inherited
);
5106 if (eCSSUnit_Initial
== SVGData
.mLightingColor
.GetUnit()) {
5107 svgReset
->mLightingColor
= NS_RGB(255, 255, 255);
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
;
5125 SetSVGOpacity(SVGData
.mStopOpacity
, parentSVGReset
->mStopOpacity
,
5126 svgReset
->mStopOpacity
, inherited
);
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
)
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
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 */ \
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"
5216 nsRuleNode::GetStyleData(nsStyleStructID aSID
,
5217 nsStyleContext
* aContext
,
5218 PRBool aComputeData
)
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");
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
))
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"
5243 #undef STYLE_STRUCT_TEST
5245 if (NS_LIKELY(data
!= nsnull
))
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
5255 return mPresContext
->PresShell()->StyleSet()->
5256 DefaultStyleData()->GetStyleData(aSID
);
5259 // See comments above in GetStyleData for an explanation of what the
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"); \
5273 data = mStyleData.GetStyle##name_(); \
5274 if (NS_LIKELY(data != nsnull)) \
5277 if (NS_UNLIKELY(!aComputeData)) \
5281 static_cast<const nsStyle##name_ *>(Get##name_##Data(aContext)); \
5283 if (NS_LIKELY(data != nsnull)) \
5286 NS_NOTREACHED("could not create style struct"); \
5288 static_cast<const nsStyle##name_ *>( \
5289 mPresContext->PresShell()->StyleSet()-> \
5290 DefaultStyleData()->GetStyleData(eStyleStruct_##name_)); \
5292 #include "nsStyleStructList.h"
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
;
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()) {
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
);
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.
5344 children
= &(*children
)->mNextSibling
;
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();
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();
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