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"
72 #include "nsStyleTransformMatrix.h"
73 #include "nsCSSKeywords.h"
74 #include "nsCSSProps.h"
77 * For storage of an |nsRuleNode|'s children in a PLDHashTable.
80 struct ChildrenHashEntry
: public PLDHashEntryHdr
{
81 // key is |mRuleNode->GetKey()|
82 nsRuleNode
*mRuleNode
;
85 /* static */ PLDHashNumber
86 nsRuleNode::ChildrenHashHashKey(PLDHashTable
*aTable
, const void *aKey
)
88 const nsRuleNode::Key
*key
=
89 static_cast<const nsRuleNode::Key
*>(aKey
);
90 // Disagreement on importance and level for the same rule is extremely
91 // rare, so hash just on the rule.
92 return PL_DHashVoidPtrKeyStub(aTable
, key
->mRule
);
96 nsRuleNode::ChildrenHashMatchEntry(PLDHashTable
*aTable
,
97 const PLDHashEntryHdr
*aHdr
,
100 const ChildrenHashEntry
*entry
=
101 static_cast<const ChildrenHashEntry
*>(aHdr
);
102 const nsRuleNode::Key
*key
=
103 static_cast<const nsRuleNode::Key
*>(aKey
);
104 return entry
->mRuleNode
->GetKey() == *key
;
107 /* static */ PLDHashTableOps
108 nsRuleNode::ChildrenHashOps
= {
109 // It's probably better to allocate the table itself using malloc and
110 // free rather than the pres shell's arena because the table doesn't
111 // grow very often and the pres shell's arena doesn't recycle very
112 // large size allocations.
116 ChildrenHashMatchEntry
,
117 PL_DHashMoveEntryStub
,
118 PL_DHashClearEntryStub
,
119 PL_DHashFinalizeStub
,
124 // EnsureBlockDisplay:
125 // - if the display value (argument) is not a block-type
126 // then we set it to a valid block display value
127 // - For enforcing the floated/positioned element CSS2 rules
128 static void EnsureBlockDisplay(PRUint8
& display
)
130 // see if the display value is already a block
132 case NS_STYLE_DISPLAY_NONE
:
133 // never change display:none *ever*
134 case NS_STYLE_DISPLAY_TABLE
:
135 case NS_STYLE_DISPLAY_BLOCK
:
136 case NS_STYLE_DISPLAY_LIST_ITEM
:
137 // do not muck with these at all - already blocks
138 // This is equivalent to nsStyleDisplay::IsBlockOutside. (XXX Maybe we
139 // should just call that?)
142 case NS_STYLE_DISPLAY_INLINE_TABLE
:
143 // make inline tables into tables
144 display
= NS_STYLE_DISPLAY_TABLE
;
149 display
= NS_STYLE_DISPLAY_BLOCK
;
153 // XXX This should really be done in the CSS parser.
154 static nsString
& Unquote(nsString
& aString
)
156 PRUnichar start
= aString
.First();
157 PRUnichar end
= aString
.Last();
159 if ((start
== end
) &&
160 ((start
== PRUnichar('\"')) ||
161 (start
== PRUnichar('\'')))) {
162 PRInt32 length
= aString
.Length();
163 aString
.Truncate(length
- 1);
169 static nscoord
CalcLengthWith(const nsCSSValue
& aValue
,
171 const nsStyleFont
* aStyleFont
,
172 nsStyleContext
* aStyleContext
,
173 nsPresContext
* aPresContext
,
176 NS_ASSERTION(aValue
.IsLengthUnit(), "not a length unit");
177 NS_ASSERTION(aStyleFont
|| aStyleContext
, "Must have style data");
178 NS_ASSERTION(aPresContext
, "Must have prescontext");
180 if (aValue
.IsFixedLengthUnit()) {
181 return aPresContext
->TwipsToAppUnits(aValue
.GetLengthTwips());
183 nsCSSUnit unit
= aValue
.GetUnit();
184 if (unit
== eCSSUnit_Pixel
) {
185 return nsPresContext::CSSPixelsToAppUnits(aValue
.GetFloatValue());
187 // Common code for all units other than pixels:
188 aInherited
= PR_TRUE
;
190 aStyleFont
= aStyleContext
->GetStyleFont();
192 if (aFontSize
== -1) {
193 // XXX Should this be aStyleFont->mSize instead to avoid taking minfontsize
194 // prefs into account?
195 aFontSize
= aStyleFont
->mFont
.size
;
199 return NSToCoordRoundWithClamp(aValue
.GetFloatValue() * float(aFontSize
));
200 // XXX scale against font metrics height instead?
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 NSToCoordRoundWithClamp(aValue
.GetFloatValue() * float(xHeight
));
210 case eCSSUnit_Char
: {
211 nsFont font
= aStyleFont
->mFont
;
212 font
.size
= aFontSize
;
213 nsCOMPtr
<nsIFontMetrics
> fm
= aPresContext
->GetMetricsFor(font
);
214 nsCOMPtr
<nsIThebesFontMetrics
> tfm(do_QueryInterface(fm
));
215 gfxFloat zeroWidth
= (tfm
->GetThebesFontGroup()->GetFontAt(0)
216 ->GetMetrics().zeroOrAveCharWidth
);
218 return NSToCoordRoundWithClamp(aValue
.GetFloatValue() *
219 NS_ceil(aPresContext
->AppUnitsPerDevPixel() *
223 NS_NOTREACHED("unexpected unit");
230 nsRuleNode::CalcLength(const nsCSSValue
& aValue
,
231 nsStyleContext
* aStyleContext
,
232 nsPresContext
* aPresContext
,
235 NS_ASSERTION(aStyleContext
, "Must have style data");
237 return CalcLengthWith(aValue
, -1, nsnull
, aStyleContext
, aPresContext
, aInherited
);
240 /* Inline helper function to redirect requests to CalcLength. */
241 static inline nscoord
CalcLength(const nsCSSValue
& aValue
,
242 nsStyleContext
* aStyleContext
,
243 nsPresContext
* aPresContext
,
246 return nsRuleNode::CalcLength(aValue
, aStyleContext
,
247 aPresContext
, aInherited
);
251 nsRuleNode::CalcLengthWithInitialFont(nsPresContext
* aPresContext
,
252 const nsCSSValue
& aValue
)
254 nsStyleFont
defaultFont(aPresContext
);
256 return CalcLengthWith(aValue
, -1, &defaultFont
, nsnull
, aPresContext
,
260 #define SETCOORD_NORMAL 0x01 // N
261 #define SETCOORD_AUTO 0x02 // A
262 #define SETCOORD_INHERIT 0x04 // H
263 #define SETCOORD_PERCENT 0x08 // P
264 #define SETCOORD_FACTOR 0x10 // F
265 #define SETCOORD_LENGTH 0x20 // L
266 #define SETCOORD_INTEGER 0x40 // I
267 #define SETCOORD_ENUMERATED 0x80 // E
268 #define SETCOORD_NONE 0x100 // O
269 #define SETCOORD_INITIAL_ZERO 0x200
270 #define SETCOORD_INITIAL_AUTO 0x400
271 #define SETCOORD_INITIAL_NONE 0x800
272 #define SETCOORD_INITIAL_NORMAL 0x1000
273 #define SETCOORD_INITIAL_HALF 0x2000
275 #define SETCOORD_LP (SETCOORD_LENGTH | SETCOORD_PERCENT)
276 #define SETCOORD_LH (SETCOORD_LENGTH | SETCOORD_INHERIT)
277 #define SETCOORD_AH (SETCOORD_AUTO | SETCOORD_INHERIT)
278 #define SETCOORD_LAH (SETCOORD_AUTO | SETCOORD_LENGTH | SETCOORD_INHERIT)
279 #define SETCOORD_LPH (SETCOORD_LP | SETCOORD_INHERIT)
280 #define SETCOORD_LPAH (SETCOORD_LP | SETCOORD_AH)
281 #define SETCOORD_LPEH (SETCOORD_LP | SETCOORD_ENUMERATED | SETCOORD_INHERIT)
282 #define SETCOORD_LPAEH (SETCOORD_LPAH | SETCOORD_ENUMERATED)
283 #define SETCOORD_LPOH (SETCOORD_LPH | SETCOORD_NONE)
284 #define SETCOORD_LPOEH (SETCOORD_LPOH | SETCOORD_ENUMERATED)
285 #define SETCOORD_LE (SETCOORD_LENGTH | SETCOORD_ENUMERATED)
286 #define SETCOORD_LEH (SETCOORD_LE | SETCOORD_INHERIT)
287 #define SETCOORD_IA (SETCOORD_INTEGER | SETCOORD_AUTO)
288 #define SETCOORD_LAE (SETCOORD_LENGTH | SETCOORD_AUTO | SETCOORD_ENUMERATED)
290 // changes aCoord iff it returns PR_TRUE
291 static PRBool
SetCoord(const nsCSSValue
& aValue
, nsStyleCoord
& aCoord
,
292 const nsStyleCoord
& aParentCoord
,
293 PRInt32 aMask
, nsStyleContext
* aStyleContext
,
294 nsPresContext
* aPresContext
, PRBool
& aInherited
)
296 PRBool result
= PR_TRUE
;
297 if (aValue
.GetUnit() == eCSSUnit_Null
) {
300 else if (((aMask
& SETCOORD_LENGTH
) != 0) &&
301 aValue
.IsLengthUnit()) {
302 aCoord
.SetCoordValue(CalcLength(aValue
, aStyleContext
, aPresContext
, aInherited
));
304 else if (((aMask
& SETCOORD_PERCENT
) != 0) &&
305 (aValue
.GetUnit() == eCSSUnit_Percent
)) {
306 aCoord
.SetPercentValue(aValue
.GetPercentValue());
308 else if (((aMask
& SETCOORD_INTEGER
) != 0) &&
309 (aValue
.GetUnit() == eCSSUnit_Integer
)) {
310 aCoord
.SetIntValue(aValue
.GetIntValue(), eStyleUnit_Integer
);
312 else if (((aMask
& SETCOORD_ENUMERATED
) != 0) &&
313 (aValue
.GetUnit() == eCSSUnit_Enumerated
)) {
314 aCoord
.SetIntValue(aValue
.GetIntValue(), eStyleUnit_Enumerated
);
316 else if (((aMask
& SETCOORD_AUTO
) != 0) &&
317 (aValue
.GetUnit() == eCSSUnit_Auto
)) {
318 aCoord
.SetAutoValue();
320 else if (((aMask
& SETCOORD_INHERIT
) != 0) &&
321 (aValue
.GetUnit() == eCSSUnit_Inherit
)) {
322 aCoord
= aParentCoord
; // just inherit value from parent
323 aInherited
= PR_TRUE
;
325 else if (((aMask
& SETCOORD_NORMAL
) != 0) &&
326 (aValue
.GetUnit() == eCSSUnit_Normal
)) {
327 aCoord
.SetNormalValue();
329 else if (((aMask
& SETCOORD_NONE
) != 0) &&
330 (aValue
.GetUnit() == eCSSUnit_None
)) {
331 aCoord
.SetNoneValue();
333 else if (((aMask
& SETCOORD_FACTOR
) != 0) &&
334 (aValue
.GetUnit() == eCSSUnit_Number
)) {
335 aCoord
.SetFactorValue(aValue
.GetFloatValue());
337 else if (((aMask
& SETCOORD_INITIAL_AUTO
) != 0) &&
338 (aValue
.GetUnit() == eCSSUnit_Initial
)) {
339 aCoord
.SetAutoValue();
341 else if (((aMask
& SETCOORD_INITIAL_ZERO
) != 0) &&
342 (aValue
.GetUnit() == eCSSUnit_Initial
)) {
343 aCoord
.SetCoordValue(0);
345 else if (((aMask
& SETCOORD_INITIAL_NONE
) != 0) &&
346 (aValue
.GetUnit() == eCSSUnit_Initial
)) {
347 aCoord
.SetNoneValue();
349 else if (((aMask
& SETCOORD_INITIAL_NORMAL
) != 0) &&
350 (aValue
.GetUnit() == eCSSUnit_Initial
)) {
351 aCoord
.SetNormalValue();
353 else if (((aMask
& SETCOORD_INITIAL_HALF
) != 0) &&
354 (aValue
.GetUnit() == eCSSUnit_Initial
)) {
355 aCoord
.SetPercentValue(0.5f
);
358 result
= PR_FALSE
; // didn't set anything
363 /* Given an enumerated value that represents a box position, converts it to
364 * a float representing the percentage of the box it corresponds to. For
365 * example, "center" becomes 0.5f.
367 * @param aEnumValue The enumerated value.
368 * @return The float percent it corresponds to.
370 static float GetFloatFromBoxPosition(PRInt32 aEnumValue
)
372 switch (aEnumValue
) {
373 case NS_STYLE_BG_POSITION_LEFT
:
374 case NS_STYLE_BG_POSITION_TOP
:
376 case NS_STYLE_BG_POSITION_RIGHT
:
377 case NS_STYLE_BG_POSITION_BOTTOM
:
380 NS_NOTREACHED("unexpected value");
382 case NS_STYLE_BG_POSITION_CENTER
:
387 static PRBool
SetColor(const nsCSSValue
& aValue
, const nscolor aParentColor
,
388 nsPresContext
* aPresContext
, nsStyleContext
*aContext
,
389 nscolor
& aResult
, PRBool
& aInherited
)
391 PRBool result
= PR_FALSE
;
392 nsCSSUnit unit
= aValue
.GetUnit();
394 if (eCSSUnit_Color
== unit
) {
395 aResult
= aValue
.GetColorValue();
398 else if (eCSSUnit_String
== unit
) {
400 aValue
.GetStringValue(value
);
402 if (NS_ColorNameToRGB(value
, &rgba
)) {
407 else if (eCSSUnit_EnumColor
== unit
) {
408 PRInt32 intValue
= aValue
.GetIntValue();
410 nsILookAndFeel
* look
= aPresContext
->LookAndFeel();
411 nsILookAndFeel::nsColorID colorID
= (nsILookAndFeel::nsColorID
) intValue
;
412 if (NS_SUCCEEDED(look
->GetColor(colorID
, aResult
))) {
418 case NS_COLOR_MOZ_HYPERLINKTEXT
:
419 aResult
= aPresContext
->DefaultLinkColor();
421 case NS_COLOR_MOZ_VISITEDHYPERLINKTEXT
:
422 aResult
= aPresContext
->DefaultVisitedLinkColor();
424 case NS_COLOR_MOZ_ACTIVEHYPERLINKTEXT
:
425 aResult
= aPresContext
->DefaultActiveLinkColor();
427 case NS_COLOR_CURRENTCOLOR
:
428 // The data computed from this can't be shared in the rule tree
429 // because they could be used on a node with a different color
430 aInherited
= PR_TRUE
;
431 aResult
= aContext
->GetStyleColor()->mColor
;
434 NS_NOTREACHED("Should never have an unknown negative colorID.");
440 else if (eCSSUnit_Inherit
== unit
) {
441 aResult
= aParentColor
;
443 aInherited
= PR_TRUE
;
448 // flags for SetDiscrete - align values with SETCOORD_* constants
451 #define SETDSC_NORMAL 0x01 // N
452 #define SETDSC_AUTO 0x02 // A
453 #define SETDSC_INTEGER 0x40 // I
454 #define SETDSC_ENUMERATED 0x80 // E
455 #define SETDSC_NONE 0x100 // O
456 #define SETDSC_SYSTEM_FONT 0x2000
458 // no caller cares whether aField was changed or not
459 template <typename FieldT
,
460 typename T1
, typename T2
, typename T3
, typename T4
, typename T5
>
462 SetDiscrete(const nsCSSValue
& aValue
, FieldT
& aField
,
463 PRBool
& aInherited
, PRUint32 aMask
,
471 switch (aValue
.GetUnit()) {
475 // every caller of SetDiscrete provides inherit and initial
476 // alternatives, so we don't require them to say so in the mask
477 case eCSSUnit_Inherit
:
478 aInherited
= PR_TRUE
;
479 aField
= aParentValue
;
482 case eCSSUnit_Initial
:
483 aField
= aInitialValue
;
486 // every caller provides one or other of these alternatives,
487 // but they have to say which
488 case eCSSUnit_Enumerated
:
489 if (aMask
& SETDSC_ENUMERATED
) {
490 aField
= aValue
.GetIntValue();
495 case eCSSUnit_Integer
:
496 if (aMask
& SETDSC_INTEGER
) {
497 aField
= aValue
.GetIntValue();
502 // remaining possibilities in descending order of frequency of use
504 if (aMask
& SETDSC_AUTO
) {
511 if (aMask
& SETDSC_NONE
) {
517 case eCSSUnit_Normal
:
518 if (aMask
& SETDSC_NORMAL
) {
519 aField
= aNormalValue
;
524 case eCSSUnit_System_Font
:
525 if (aMask
& SETDSC_SYSTEM_FONT
) {
526 aField
= aSystemFontValue
;
535 NS_NOTREACHED("SetDiscrete: inappropriate unit");
538 // flags for SetFactor
539 #define SETFCT_POSITIVE 0x01 // assert value is >= 0.0f
540 #define SETFCT_OPACITY 0x02 // clamp value to [0.0f .. 1.0f]
541 #define SETFCT_NONE 0x04 // allow _None (uses aInitialValue).
544 SetFactor(const nsCSSValue
& aValue
, float& aField
, PRBool
& aInherited
,
545 float aParentValue
, float aInitialValue
, PRUint32 aFlags
= 0)
547 switch (aValue
.GetUnit()) {
551 case eCSSUnit_Number
:
552 aField
= aValue
.GetFloatValue();
553 if (aFlags
& SETFCT_POSITIVE
) {
554 NS_ASSERTION(aField
>= 0.0f
, "negative value for positive-only property");
558 if (aFlags
& SETFCT_OPACITY
) {
566 case eCSSUnit_Inherit
:
567 aInherited
= PR_TRUE
;
568 aField
= aParentValue
;
571 case eCSSUnit_Initial
:
572 aField
= aInitialValue
;
576 if (aFlags
& SETFCT_NONE
) {
577 aField
= aInitialValue
;
586 NS_NOTREACHED("SetFactor: inappropriate unit");
589 // Overloaded new operator. Initializes the memory to 0 and relies on an arena
590 // (which comes from the presShell) to perform the allocation.
592 nsRuleNode::operator new(size_t sz
, nsPresContext
* aPresContext
) CPP_THROW_NEW
594 // Check the recycle list first.
595 return aPresContext
->AllocateFromShell(sz
);
598 /* static */ PLDHashOperator
599 nsRuleNode::EnqueueRuleNodeChildren(PLDHashTable
*table
, PLDHashEntryHdr
*hdr
,
600 PRUint32 number
, void *arg
)
602 ChildrenHashEntry
*entry
= static_cast<ChildrenHashEntry
*>(hdr
);
603 nsRuleNode
***destroyQueueTail
= static_cast<nsRuleNode
***>(arg
);
604 **destroyQueueTail
= entry
->mRuleNode
;
605 *destroyQueueTail
= &entry
->mRuleNode
->mNextSibling
;
606 return PL_DHASH_NEXT
;
609 // Overridden to prevent the global delete from being called, since the memory
610 // came out of an nsIArena instead of the global delete operator's heap.
612 nsRuleNode::DestroyInternal(nsRuleNode
***aDestroyQueueTail
)
614 nsRuleNode
*destroyQueue
, **destroyQueueTail
;
615 if (aDestroyQueueTail
) {
616 destroyQueueTail
= *aDestroyQueueTail
;
618 destroyQueue
= nsnull
;
619 destroyQueueTail
= &destroyQueue
;
622 if (ChildrenAreHashed()) {
623 PLDHashTable
*children
= ChildrenHash();
624 PL_DHashTableEnumerate(children
, EnqueueRuleNodeChildren
,
626 *destroyQueueTail
= nsnull
; // ensure null-termination
627 PL_DHashTableDestroy(children
);
628 } else if (HaveChildren()) {
629 *destroyQueueTail
= ChildrenList();
631 destroyQueueTail
= &(*destroyQueueTail
)->mNextSibling
;
632 } while (*destroyQueueTail
);
634 mChildren
.asVoid
= nsnull
;
636 if (aDestroyQueueTail
) {
637 // Our caller destroys the queue.
638 *aDestroyQueueTail
= destroyQueueTail
;
640 // We have to do destroy the queue. When we destroy each node, it
641 // will add its children to the queue.
642 while (destroyQueue
) {
643 nsRuleNode
*cur
= destroyQueue
;
644 destroyQueue
= destroyQueue
->mNextSibling
;
646 NS_ASSERTION(destroyQueueTail
== &cur
->mNextSibling
, "mangled list");
647 destroyQueueTail
= &destroyQueue
;
649 cur
->DestroyInternal(&destroyQueueTail
);
653 // Destroy ourselves.
656 // Don't let the memory be freed, since it will be recycled
657 // instead. Don't call the global operator delete.
658 mPresContext
->FreeToShell(sizeof(nsRuleNode
), this);
661 nsRuleNode
* nsRuleNode::CreateRootNode(nsPresContext
* aPresContext
)
663 return new (aPresContext
)
664 nsRuleNode(aPresContext
, nsnull
, nsnull
, 0xff, PR_FALSE
);
667 nsILanguageAtomService
* nsRuleNode::gLangService
= nsnull
;
669 nsRuleNode::nsRuleNode(nsPresContext
* aContext
, nsRuleNode
* aParent
,
670 nsIStyleRule
* aRule
, PRUint8 aLevel
,
672 : mPresContext(aContext
),
675 mDependentBits((PRUint32(aLevel
) << NS_RULE_NODE_LEVEL_SHIFT
) |
676 (aIsImportant
? NS_RULE_NODE_IS_IMPORTANT
: 0)),
679 mChildren
.asVoid
= nsnull
;
680 MOZ_COUNT_CTOR(nsRuleNode
);
683 NS_ASSERTION(IsRoot() || GetLevel() == aLevel
, "not enough bits");
684 NS_ASSERTION(IsRoot() || IsImportantRule() == aIsImportant
, "yikes");
687 nsRuleNode::~nsRuleNode()
689 MOZ_COUNT_DTOR(nsRuleNode
);
690 if (mStyleData
.mResetData
|| mStyleData
.mInheritedData
)
691 mStyleData
.Destroy(0, mPresContext
);
692 NS_IF_RELEASE(mRule
);
696 nsRuleNode::Transition(nsIStyleRule
* aRule
, PRUint8 aLevel
,
697 PRPackedBool aIsImportantRule
)
699 nsRuleNode
* next
= nsnull
;
700 nsRuleNode::Key
key(aRule
, aLevel
, aIsImportantRule
);
702 if (HaveChildren() && !ChildrenAreHashed()) {
704 nsRuleNode
* curr
= ChildrenList();
705 while (curr
&& curr
->GetKey() != key
) {
706 curr
= curr
->mNextSibling
;
711 else if (numKids
>= kMaxChildrenInList
)
712 ConvertChildrenToHash();
715 if (ChildrenAreHashed()) {
716 ChildrenHashEntry
*entry
= static_cast<ChildrenHashEntry
*>
717 (PL_DHashTableOperate(ChildrenHash(), &key
, PL_DHASH_ADD
));
721 if (entry
->mRuleNode
)
722 next
= entry
->mRuleNode
;
724 next
= entry
->mRuleNode
= new (mPresContext
)
725 nsRuleNode(mPresContext
, this, aRule
, aLevel
, aIsImportantRule
);
727 PL_DHashTableRawRemove(ChildrenHash(), entry
);
732 // Create the new entry in our list.
733 next
= new (mPresContext
)
734 nsRuleNode(mPresContext
, this, aRule
, aLevel
, aIsImportantRule
);
738 next
->mNextSibling
= ChildrenList();
739 SetChildrenList(next
);
746 nsRuleNode::ConvertChildrenToHash()
748 NS_ASSERTION(!ChildrenAreHashed() && HaveChildren(),
749 "must have a non-empty list of children");
750 PLDHashTable
*hash
= PL_NewDHashTable(&ChildrenHashOps
, nsnull
,
751 sizeof(ChildrenHashEntry
),
752 kMaxChildrenInList
* 4);
755 for (nsRuleNode
* curr
= ChildrenList(); curr
; curr
= curr
->mNextSibling
) {
756 // This will never fail because of the initial size we gave the table.
757 ChildrenHashEntry
*entry
= static_cast<ChildrenHashEntry
*>(
758 PL_DHashTableOperate(hash
, curr
->mRule
, PL_DHASH_ADD
));
759 NS_ASSERTION(!entry
->mRuleNode
, "duplicate entries in list");
760 entry
->mRuleNode
= curr
;
762 SetChildrenHash(hash
);
766 nsRuleNode::PropagateNoneBit(PRUint32 aBit
, nsRuleNode
* aHighestNode
)
768 nsRuleNode
* curr
= this;
770 NS_ASSERTION(!(curr
->mNoneBits
& aBit
), "propagating too far");
771 curr
->mNoneBits
|= aBit
;
772 if (curr
== aHighestNode
)
774 curr
= curr
->mParent
;
779 nsRuleNode::PropagateDependentBit(PRUint32 aBit
, nsRuleNode
* aHighestNode
)
781 for (nsRuleNode
* curr
= this; curr
!= aHighestNode
; curr
= curr
->mParent
) {
782 if (curr
->mDependentBits
& aBit
) {
784 while (curr
!= aHighestNode
) {
785 NS_ASSERTION(curr
->mDependentBits
& aBit
, "bit not set");
786 curr
= curr
->mParent
;
792 curr
->mDependentBits
|= aBit
;
797 * The following "Check" functions are used for determining what type of
798 * sharing can be used for the data on this rule node. MORE HERE...
801 /* the information for a property (or in some cases, a rect group of
804 struct PropertyCheckData
{
806 // These duplicate the same data in nsCSSProps::kTypeTable and
807 // kFlagsTable, except that we have some extra entries for
808 // CSS_PROP_INCLUDE_NOT_CSS.
814 * a callback function that that can revise the result of
815 * CheckSpecifiedProperties before finishing; aResult is the current
816 * result, and it returns the revised one.
818 typedef nsRuleNode::RuleDetail
819 (* CheckCallbackFn
)(const nsRuleDataStruct
& aData
,
820 nsRuleNode::RuleDetail aResult
);
822 /* the information for all the properties in a style struct */
823 struct StructCheckData
{
824 const PropertyCheckData
* props
;
826 CheckCallbackFn callback
;
831 * @param aValue the value being examined
832 * @param aSpecifiedCount to be incremented by one if the value is specified
833 * @param aInherited to be incremented by one if the value is set to inherit
836 ExamineCSSValue(const nsCSSValue
& aValue
,
837 PRUint32
& aSpecifiedCount
, PRUint32
& aInheritedCount
)
839 if (aValue
.GetUnit() != eCSSUnit_Null
) {
841 if (aValue
.GetUnit() == eCSSUnit_Inherit
) {
848 ExamineCSSValuePair(const nsCSSValuePair
* aValuePair
,
849 PRUint32
& aSpecifiedCount
, PRUint32
& aInheritedCount
)
851 NS_PRECONDITION(aValuePair
, "Must have a value pair");
853 ExamineCSSValue(aValuePair
->mXValue
, aSpecifiedCount
, aInheritedCount
);
854 ExamineCSSValue(aValuePair
->mYValue
, aSpecifiedCount
, aInheritedCount
);
858 ExamineCSSRect(const nsCSSRect
* aRect
,
859 PRUint32
& aSpecifiedCount
, PRUint32
& aInheritedCount
)
861 NS_PRECONDITION(aRect
, "Must have a rect");
863 NS_FOR_CSS_SIDES(side
) {
864 ExamineCSSValue(aRect
->*(nsCSSRect::sides
[side
]),
865 aSpecifiedCount
, aInheritedCount
);
869 static nsRuleNode::RuleDetail
870 CheckFontCallback(const nsRuleDataStruct
& aData
,
871 nsRuleNode::RuleDetail aResult
)
873 const nsRuleDataFont
& fontData
=
874 static_cast<const nsRuleDataFont
&>(aData
);
876 // em, ex, percent, 'larger', and 'smaller' values on font-size depend
877 // on the parent context's font-size
878 // Likewise, 'lighter' and 'bolder' values of 'font-weight' depend on
880 const nsCSSValue
& size
= fontData
.mSize
;
881 const nsCSSValue
& weight
= fontData
.mWeight
;
882 if ((size
.IsRelativeLengthUnit() && size
.GetUnit() != eCSSUnit_Pixel
) ||
883 size
.GetUnit() == eCSSUnit_Percent
||
884 (size
.GetUnit() == eCSSUnit_Enumerated
&&
885 (size
.GetIntValue() == NS_STYLE_FONT_SIZE_SMALLER
||
886 size
.GetIntValue() == NS_STYLE_FONT_SIZE_LARGER
)) ||
888 fontData
.mScriptLevel
.GetUnit() == eCSSUnit_Integer
||
890 (weight
.GetUnit() == eCSSUnit_Enumerated
&&
891 (weight
.GetIntValue() == NS_STYLE_FONT_WEIGHT_BOLDER
||
892 weight
.GetIntValue() == NS_STYLE_FONT_WEIGHT_LIGHTER
))) {
893 NS_ASSERTION(aResult
== nsRuleNode::eRulePartialReset
||
894 aResult
== nsRuleNode::eRuleFullReset
||
895 aResult
== nsRuleNode::eRulePartialMixed
||
896 aResult
== nsRuleNode::eRuleFullMixed
,
897 "we know we already have a reset-counted property");
898 // Promote reset to mixed since we have something that depends on
899 // the parent. But never promote to inherited since that could
900 // cause inheritance of the exact value.
901 if (aResult
== nsRuleNode::eRulePartialReset
)
902 aResult
= nsRuleNode::eRulePartialMixed
;
903 else if (aResult
== nsRuleNode::eRuleFullReset
)
904 aResult
= nsRuleNode::eRuleFullMixed
;
910 static nsRuleNode::RuleDetail
911 CheckColorCallback(const nsRuleDataStruct
& aData
,
912 nsRuleNode::RuleDetail aResult
)
914 const nsRuleDataColor
& colorData
=
915 static_cast<const nsRuleDataColor
&>(aData
);
917 // currentColor values for color require inheritance
918 if (colorData
.mColor
.GetUnit() == eCSSUnit_EnumColor
&&
919 colorData
.mColor
.GetIntValue() == NS_COLOR_CURRENTCOLOR
) {
920 NS_ASSERTION(aResult
== nsRuleNode::eRuleFullReset
,
921 "we should already be counted as full-reset");
922 aResult
= nsRuleNode::eRuleFullInherited
;
929 // for nsCSSPropList.h, so we get information on things in the style
930 // structs but not nsCSS*
931 #define CSS_PROP_INCLUDE_NOT_CSS
933 #define CHECK_DATA_FOR_PROPERTY(name_, id_, method_, flags_, datastruct_, member_, type_, kwtable_) \
934 { offsetof(nsRuleData##datastruct_, member_), type_, flags_ },
936 static const PropertyCheckData FontCheckProperties
[] = {
937 #define CSS_PROP_FONT CHECK_DATA_FOR_PROPERTY
938 #include "nsCSSPropList.h"
942 static const PropertyCheckData DisplayCheckProperties
[] = {
943 #define CSS_PROP_DISPLAY CHECK_DATA_FOR_PROPERTY
944 #include "nsCSSPropList.h"
945 #undef CSS_PROP_DISPLAY
948 static const PropertyCheckData VisibilityCheckProperties
[] = {
949 #define CSS_PROP_VISIBILITY CHECK_DATA_FOR_PROPERTY
950 #include "nsCSSPropList.h"
951 #undef CSS_PROP_VISIBILITY
954 static const PropertyCheckData MarginCheckProperties
[] = {
955 #define CSS_PROP_MARGIN CHECK_DATA_FOR_PROPERTY
956 #include "nsCSSPropList.h"
957 #undef CSS_PROP_MARGIN
960 static const PropertyCheckData BorderCheckProperties
[] = {
961 #define CSS_PROP_BORDER CHECK_DATA_FOR_PROPERTY
962 #include "nsCSSPropList.h"
963 #undef CSS_PROP_BORDER
966 static const PropertyCheckData PaddingCheckProperties
[] = {
967 #define CSS_PROP_PADDING CHECK_DATA_FOR_PROPERTY
968 #include "nsCSSPropList.h"
969 #undef CSS_PROP_PADDING
972 static const PropertyCheckData OutlineCheckProperties
[] = {
973 #define CSS_PROP_OUTLINE CHECK_DATA_FOR_PROPERTY
974 #include "nsCSSPropList.h"
975 #undef CSS_PROP_OUTLINE
978 static const PropertyCheckData ListCheckProperties
[] = {
979 #define CSS_PROP_LIST CHECK_DATA_FOR_PROPERTY
980 #include "nsCSSPropList.h"
984 static const PropertyCheckData ColorCheckProperties
[] = {
985 #define CSS_PROP_COLOR CHECK_DATA_FOR_PROPERTY
986 #include "nsCSSPropList.h"
987 #undef CSS_PROP_COLOR
990 static const PropertyCheckData BackgroundCheckProperties
[] = {
991 #define CSS_PROP_BACKGROUND CHECK_DATA_FOR_PROPERTY
992 #include "nsCSSPropList.h"
993 #undef CSS_PROP_BACKGROUND
996 static const PropertyCheckData PositionCheckProperties
[] = {
997 #define CSS_PROP_POSITION CHECK_DATA_FOR_PROPERTY
998 #include "nsCSSPropList.h"
999 #undef CSS_PROP_POSITION
1002 static const PropertyCheckData TableCheckProperties
[] = {
1003 #define CSS_PROP_TABLE CHECK_DATA_FOR_PROPERTY
1004 #include "nsCSSPropList.h"
1005 #undef CSS_PROP_TABLE
1008 static const PropertyCheckData TableBorderCheckProperties
[] = {
1009 #define CSS_PROP_TABLEBORDER CHECK_DATA_FOR_PROPERTY
1010 #include "nsCSSPropList.h"
1011 #undef CSS_PROP_TABLEBORDER
1014 static const PropertyCheckData ContentCheckProperties
[] = {
1015 #define CSS_PROP_CONTENT CHECK_DATA_FOR_PROPERTY
1016 #include "nsCSSPropList.h"
1017 #undef CSS_PROP_CONTENT
1020 static const PropertyCheckData QuotesCheckProperties
[] = {
1021 #define CSS_PROP_QUOTES CHECK_DATA_FOR_PROPERTY
1022 #include "nsCSSPropList.h"
1023 #undef CSS_PROP_QUOTES
1026 static const PropertyCheckData TextCheckProperties
[] = {
1027 #define CSS_PROP_TEXT CHECK_DATA_FOR_PROPERTY
1028 #include "nsCSSPropList.h"
1029 #undef CSS_PROP_TEXT
1032 static const PropertyCheckData TextResetCheckProperties
[] = {
1033 #define CSS_PROP_TEXTRESET CHECK_DATA_FOR_PROPERTY
1034 #include "nsCSSPropList.h"
1035 #undef CSS_PROP_TEXTRESET
1038 static const PropertyCheckData UserInterfaceCheckProperties
[] = {
1039 #define CSS_PROP_USERINTERFACE CHECK_DATA_FOR_PROPERTY
1040 #include "nsCSSPropList.h"
1041 #undef CSS_PROP_USERINTERFACE
1044 static const PropertyCheckData UIResetCheckProperties
[] = {
1045 #define CSS_PROP_UIRESET CHECK_DATA_FOR_PROPERTY
1046 #include "nsCSSPropList.h"
1047 #undef CSS_PROP_UIRESET
1050 static const PropertyCheckData XULCheckProperties
[] = {
1051 #define CSS_PROP_XUL CHECK_DATA_FOR_PROPERTY
1052 #include "nsCSSPropList.h"
1057 static const PropertyCheckData SVGCheckProperties
[] = {
1058 #define CSS_PROP_SVG CHECK_DATA_FOR_PROPERTY
1059 #include "nsCSSPropList.h"
1063 static const PropertyCheckData SVGResetCheckProperties
[] = {
1064 #define CSS_PROP_SVGRESET CHECK_DATA_FOR_PROPERTY
1065 #include "nsCSSPropList.h"
1066 #undef CSS_PROP_SVGRESET
1070 static const PropertyCheckData ColumnCheckProperties
[] = {
1071 #define CSS_PROP_COLUMN CHECK_DATA_FOR_PROPERTY
1072 #include "nsCSSPropList.h"
1073 #undef CSS_PROP_COLUMN
1076 #undef CSS_PROP_INCLUDE_NOT_CSS
1077 #undef CHECK_DATA_FOR_PROPERTY
1079 static const StructCheckData gCheckProperties
[] = {
1081 #define STYLE_STRUCT(name, checkdata_cb, ctor_args) \
1082 {name##CheckProperties, \
1083 sizeof(name##CheckProperties)/sizeof(PropertyCheckData), \
1085 #include "nsStyleStructList.h"
1093 // XXXldb Taking the address of a reference is evil.
1096 ValueAtOffset(nsRuleDataStruct
& aRuleDataStruct
, size_t aOffset
)
1098 return * reinterpret_cast<nsCSSValue
*>
1099 (reinterpret_cast<char*>(&aRuleDataStruct
) + aOffset
);
1102 inline const nsCSSValue
&
1103 ValueAtOffset(const nsRuleDataStruct
& aRuleDataStruct
, size_t aOffset
)
1105 return * reinterpret_cast<const nsCSSValue
*>
1106 (reinterpret_cast<const char*>(&aRuleDataStruct
) + aOffset
);
1110 RectAtOffset(nsRuleDataStruct
& aRuleDataStruct
, size_t aOffset
)
1112 return reinterpret_cast<nsCSSRect
*>
1113 (reinterpret_cast<char*>(&aRuleDataStruct
) + aOffset
);
1116 inline const nsCSSRect
*
1117 RectAtOffset(const nsRuleDataStruct
& aRuleDataStruct
, size_t aOffset
)
1119 return reinterpret_cast<const nsCSSRect
*>
1120 (reinterpret_cast<const char*>(&aRuleDataStruct
) + aOffset
);
1123 inline nsCSSValuePair
*
1124 ValuePairAtOffset(nsRuleDataStruct
& aRuleDataStruct
, size_t aOffset
)
1126 return reinterpret_cast<nsCSSValuePair
*>
1127 (reinterpret_cast<char*>(&aRuleDataStruct
) + aOffset
);
1130 inline const nsCSSValuePair
*
1131 ValuePairAtOffset(const nsRuleDataStruct
& aRuleDataStruct
, size_t aOffset
)
1133 return reinterpret_cast<const nsCSSValuePair
*>
1134 (reinterpret_cast<const char*>(&aRuleDataStruct
) + aOffset
);
1137 inline nsCSSValueList
*&
1138 ValueListAtOffset(nsRuleDataStruct
& aRuleDataStruct
, size_t aOffset
)
1140 return * reinterpret_cast<nsCSSValueList
**>
1141 (reinterpret_cast<char*>(&aRuleDataStruct
) + aOffset
);
1144 inline const nsCSSValueList
*
1145 ValueListAtOffset(const nsRuleDataStruct
& aRuleDataStruct
, size_t aOffset
)
1147 return * reinterpret_cast<const nsCSSValueList
*const*>
1148 (reinterpret_cast<const char*>(&aRuleDataStruct
) + aOffset
);
1151 inline nsCSSValuePairList
*&
1152 ValuePairListAtOffset(nsRuleDataStruct
& aRuleDataStruct
, size_t aOffset
)
1154 return * reinterpret_cast<nsCSSValuePairList
**>
1155 (reinterpret_cast<char*>(&aRuleDataStruct
) + aOffset
);
1158 inline const nsCSSValuePairList
*
1159 ValuePairListAtOffset(const nsRuleDataStruct
& aRuleDataStruct
, size_t aOffset
)
1161 return * reinterpret_cast<const nsCSSValuePairList
*const*>
1162 (reinterpret_cast<const char*>(&aRuleDataStruct
) + aOffset
);
1165 #if defined(MOZ_MATHML) && defined(DEBUG)
1167 AreAllMathMLPropertiesUndefined(const nsCSSFont
& aRuleData
)
1169 return aRuleData
.mScriptLevel
.GetUnit() == eCSSUnit_Null
&&
1170 aRuleData
.mScriptSizeMultiplier
.GetUnit() == eCSSUnit_Null
&&
1171 aRuleData
.mScriptMinSize
.GetUnit() == eCSSUnit_Null
;
1175 inline nsRuleNode::RuleDetail
1176 nsRuleNode::CheckSpecifiedProperties(const nsStyleStructID aSID
,
1177 const nsRuleDataStruct
& aRuleDataStruct
)
1179 const StructCheckData
*structData
= gCheckProperties
+ aSID
;
1181 // Build a count of the:
1182 PRUint32 total
= 0, // total number of props in the struct
1183 specified
= 0, // number that were specified for this node
1184 inherited
= 0; // number that were 'inherit' (and not
1185 // eCSSUnit_Inherit) for this node
1187 for (const PropertyCheckData
*prop
= structData
->props
,
1188 *prop_end
= prop
+ structData
->nprops
;
1191 switch (prop
->type
) {
1193 case eCSSType_Value
:
1195 ExamineCSSValue(ValueAtOffset(aRuleDataStruct
, prop
->offset
),
1196 specified
, inherited
);
1201 ExamineCSSRect(RectAtOffset(aRuleDataStruct
, prop
->offset
),
1202 specified
, inherited
);
1205 case eCSSType_ValuePair
:
1207 ExamineCSSValuePair(ValuePairAtOffset(aRuleDataStruct
, prop
->offset
),
1208 specified
, inherited
);
1211 case eCSSType_ValueList
:
1214 const nsCSSValueList
* valueList
=
1215 ValueListAtOffset(aRuleDataStruct
, prop
->offset
);
1218 if (eCSSUnit_Inherit
== valueList
->mValue
.GetUnit()) {
1225 case eCSSType_ValuePairList
:
1228 const nsCSSValuePairList
* valuePairList
=
1229 ValuePairListAtOffset(aRuleDataStruct
, prop
->offset
);
1230 if (valuePairList
) {
1232 if (eCSSUnit_Inherit
== valuePairList
->mXValue
.GetUnit()) {
1240 NS_NOTREACHED("unknown type");
1246 printf("CheckSpecifiedProperties: SID=%d total=%d spec=%d inh=%d.\n",
1247 aSID
, total
, specified
, inherited
);
1251 NS_ASSERTION(aSID
!= eStyleStruct_Font
||
1252 mPresContext
->Document()->GetMathMLEnabled() ||
1253 AreAllMathMLPropertiesUndefined(static_cast<const nsCSSFont
&>(aRuleDataStruct
)),
1254 "MathML style property was defined even though MathML is disabled");
1258 * Return the most specific information we can: prefer None or Full
1259 * over Partial, and Reset or Inherited over Mixed, since we can
1260 * optimize based on the edge cases and not the in-between cases.
1262 nsRuleNode::RuleDetail result
;
1263 if (inherited
== total
)
1264 result
= eRuleFullInherited
;
1265 else if (specified
== total
1267 // MathML defines 3 properties in Font that will never be set when
1268 // MathML is not in use. Therefore if all but three
1269 // properties have been set, and MathML is not enabled, we can treat
1270 // this as fully specified. Code in nsMathMLElementFactory will
1271 // rebuild the rule tree and style data when MathML is first enabled
1272 // (see nsMathMLElement::BindToTree).
1273 || (aSID
== eStyleStruct_Font
&& specified
+ 3 == total
&&
1274 !mPresContext
->Document()->GetMathMLEnabled())
1278 result
= eRuleFullReset
;
1280 result
= eRuleFullMixed
;
1281 } else if (specified
== 0)
1283 else if (specified
== inherited
)
1284 result
= eRulePartialInherited
;
1285 else if (inherited
== 0)
1286 result
= eRulePartialReset
;
1288 result
= eRulePartialMixed
;
1290 if (structData
->callback
) {
1291 result
= (*structData
->callback
)(aRuleDataStruct
, result
);
1298 nsRuleNode::GetDisplayData(nsStyleContext
* aContext
)
1300 nsRuleDataDisplay displayData
; // Declare a struct with null CSS values.
1301 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Display
), mPresContext
, aContext
);
1302 ruleData
.mDisplayData
= &displayData
;
1304 return WalkRuleTree(eStyleStruct_Display
, aContext
, &ruleData
, &displayData
);
1308 nsRuleNode::GetVisibilityData(nsStyleContext
* aContext
)
1310 nsRuleDataDisplay displayData
; // Declare a struct with null CSS values.
1311 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Visibility
), mPresContext
, aContext
);
1312 ruleData
.mDisplayData
= &displayData
;
1314 return WalkRuleTree(eStyleStruct_Visibility
, aContext
, &ruleData
, &displayData
);
1318 nsRuleNode::GetTextData(nsStyleContext
* aContext
)
1320 nsRuleDataText textData
; // Declare a struct with null CSS values.
1321 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Text
), mPresContext
, aContext
);
1322 ruleData
.mTextData
= &textData
;
1324 const void* res
= WalkRuleTree(eStyleStruct_Text
, aContext
, &ruleData
, &textData
);
1325 textData
.mTextShadow
= nsnull
; // We are sharing with some style rule. It really owns the data.
1330 nsRuleNode::GetTextResetData(nsStyleContext
* aContext
)
1332 nsRuleDataText textData
; // Declare a struct with null CSS values.
1333 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(TextReset
), mPresContext
, aContext
);
1334 ruleData
.mTextData
= &textData
;
1336 return WalkRuleTree(eStyleStruct_TextReset
, aContext
, &ruleData
, &textData
);
1340 nsRuleNode::GetUserInterfaceData(nsStyleContext
* aContext
)
1342 nsRuleDataUserInterface uiData
; // Declare a struct with null CSS values.
1343 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(UserInterface
), mPresContext
, aContext
);
1344 ruleData
.mUserInterfaceData
= &uiData
;
1346 const void* res
= WalkRuleTree(eStyleStruct_UserInterface
, aContext
, &ruleData
, &uiData
);
1347 uiData
.mCursor
= nsnull
; // We are sharing with some style rule. It really owns the data.
1352 nsRuleNode::GetUIResetData(nsStyleContext
* aContext
)
1354 nsRuleDataUserInterface uiData
; // Declare a struct with null CSS values.
1355 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(UIReset
), mPresContext
, aContext
);
1356 ruleData
.mUserInterfaceData
= &uiData
;
1358 const void* res
= WalkRuleTree(eStyleStruct_UIReset
, aContext
, &ruleData
, &uiData
);
1363 nsRuleNode::GetFontData(nsStyleContext
* aContext
)
1365 nsRuleDataFont fontData
; // Declare a struct with null CSS values.
1366 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Font
), mPresContext
, aContext
);
1367 ruleData
.mFontData
= &fontData
;
1369 return WalkRuleTree(eStyleStruct_Font
, aContext
, &ruleData
, &fontData
);
1373 nsRuleNode::GetColorData(nsStyleContext
* aContext
)
1375 nsRuleDataColor colorData
; // Declare a struct with null CSS values.
1376 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Color
), mPresContext
, aContext
);
1377 ruleData
.mColorData
= &colorData
;
1379 return WalkRuleTree(eStyleStruct_Color
, aContext
, &ruleData
, &colorData
);
1383 nsRuleNode::GetBackgroundData(nsStyleContext
* aContext
)
1385 nsRuleDataColor colorData
; // Declare a struct with null CSS values.
1386 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Background
), mPresContext
, aContext
);
1387 ruleData
.mColorData
= &colorData
;
1389 // If any members need to be set to null here, they must also be set to
1390 // null in HasAuthorSpecifiedRules (look at mBoxShadow in GetBorderData
1391 // and HasAuthorSpecifiedRules).
1393 return WalkRuleTree(eStyleStruct_Background
, aContext
, &ruleData
, &colorData
);
1397 nsRuleNode::GetMarginData(nsStyleContext
* aContext
)
1399 nsRuleDataMargin marginData
; // Declare a struct with null CSS values.
1400 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Margin
), mPresContext
, aContext
);
1401 ruleData
.mMarginData
= &marginData
;
1403 return WalkRuleTree(eStyleStruct_Margin
, aContext
, &ruleData
, &marginData
);
1407 nsRuleNode::GetBorderData(nsStyleContext
* aContext
)
1409 nsRuleDataMargin marginData
; // Declare a struct with null CSS values.
1410 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Border
), mPresContext
, aContext
);
1411 ruleData
.mMarginData
= &marginData
;
1413 const void* res
= WalkRuleTree(eStyleStruct_Border
, aContext
, &ruleData
, &marginData
);
1414 // We are sharing with some style rule. It really owns the data.
1415 // This nulling must also happen in HasAuthorSpecifiedRules.
1416 marginData
.mBoxShadow
= nsnull
;
1421 nsRuleNode::GetPaddingData(nsStyleContext
* aContext
)
1423 nsRuleDataMargin marginData
; // Declare a struct with null CSS values.
1424 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Padding
), mPresContext
, aContext
);
1425 ruleData
.mMarginData
= &marginData
;
1427 // If any members need to be set to null here, they must also be set to
1428 // null in HasAuthorSpecifiedRules (look at mBoxShadow in GetBorderData
1429 // and HasAuthorSpecifiedRules).
1431 return WalkRuleTree(eStyleStruct_Padding
, aContext
, &ruleData
, &marginData
);
1435 nsRuleNode::GetOutlineData(nsStyleContext
* aContext
)
1437 nsRuleDataMargin marginData
; // Declare a struct with null CSS values.
1438 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Outline
), mPresContext
, aContext
);
1439 ruleData
.mMarginData
= &marginData
;
1441 return WalkRuleTree(eStyleStruct_Outline
, aContext
, &ruleData
, &marginData
);
1445 nsRuleNode::GetListData(nsStyleContext
* aContext
)
1447 nsRuleDataList listData
; // Declare a struct with null CSS values.
1448 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(List
), mPresContext
, aContext
);
1449 ruleData
.mListData
= &listData
;
1451 return WalkRuleTree(eStyleStruct_List
, aContext
, &ruleData
, &listData
);
1455 nsRuleNode::GetPositionData(nsStyleContext
* aContext
)
1457 nsRuleDataPosition posData
; // Declare a struct with null CSS values.
1458 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Position
), mPresContext
, aContext
);
1459 ruleData
.mPositionData
= &posData
;
1461 return WalkRuleTree(eStyleStruct_Position
, aContext
, &ruleData
, &posData
);
1465 nsRuleNode::GetTableData(nsStyleContext
* aContext
)
1467 nsRuleDataTable tableData
; // Declare a struct with null CSS values.
1468 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Table
), mPresContext
, aContext
);
1469 ruleData
.mTableData
= &tableData
;
1471 return WalkRuleTree(eStyleStruct_Table
, aContext
, &ruleData
, &tableData
);
1475 nsRuleNode::GetTableBorderData(nsStyleContext
* aContext
)
1477 nsRuleDataTable tableData
; // Declare a struct with null CSS values.
1478 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(TableBorder
), mPresContext
, aContext
);
1479 ruleData
.mTableData
= &tableData
;
1481 return WalkRuleTree(eStyleStruct_TableBorder
, aContext
, &ruleData
, &tableData
);
1485 nsRuleNode::GetContentData(nsStyleContext
* aContext
)
1487 nsRuleDataContent contentData
; // Declare a struct with null CSS values.
1488 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Content
), mPresContext
, aContext
);
1489 ruleData
.mContentData
= &contentData
;
1491 const void* res
= WalkRuleTree(eStyleStruct_Content
, aContext
, &ruleData
, &contentData
);
1492 contentData
.mCounterIncrement
= contentData
.mCounterReset
= nsnull
;
1493 contentData
.mContent
= nsnull
; // We are sharing with some style rule. It really owns the data.
1498 nsRuleNode::GetQuotesData(nsStyleContext
* aContext
)
1500 nsRuleDataContent contentData
; // Declare a struct with null CSS values.
1501 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Quotes
), mPresContext
, aContext
);
1502 ruleData
.mContentData
= &contentData
;
1504 const void* res
= WalkRuleTree(eStyleStruct_Quotes
, aContext
, &ruleData
, &contentData
);
1505 contentData
.mQuotes
= nsnull
; // We are sharing with some style rule. It really owns the data.
1510 nsRuleNode::GetXULData(nsStyleContext
* aContext
)
1512 nsRuleDataXUL xulData
; // Declare a struct with null CSS values.
1513 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(XUL
), mPresContext
, aContext
);
1514 ruleData
.mXULData
= &xulData
;
1516 return WalkRuleTree(eStyleStruct_XUL
, aContext
, &ruleData
, &xulData
);
1520 nsRuleNode::GetColumnData(nsStyleContext
* aContext
)
1522 nsRuleDataColumn columnData
; // Declare a struct with null CSS values.
1523 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Column
), mPresContext
, aContext
);
1524 ruleData
.mColumnData
= &columnData
;
1526 return WalkRuleTree(eStyleStruct_Column
, aContext
, &ruleData
, &columnData
);
1531 nsRuleNode::GetSVGData(nsStyleContext
* aContext
)
1533 nsRuleDataSVG svgData
; // Declare a struct with null CSS values.
1534 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(SVG
), mPresContext
, aContext
);
1535 ruleData
.mSVGData
= &svgData
;
1537 const void *res
= WalkRuleTree(eStyleStruct_SVG
, aContext
, &ruleData
, &svgData
);
1538 svgData
.mStrokeDasharray
= nsnull
; // We are sharing with some style rule. It really owns the data.
1543 nsRuleNode::GetSVGResetData(nsStyleContext
* aContext
)
1545 nsRuleDataSVG svgData
; // Declare a struct with null CSS values.
1546 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(SVGReset
), mPresContext
, aContext
);
1547 ruleData
.mSVGData
= &svgData
;
1549 return WalkRuleTree(eStyleStruct_SVGReset
, aContext
, &ruleData
, &svgData
);
1553 // If we need to restrict which properties apply to the style context,
1554 // return the bit to check in nsCSSProp's flags table. Otherwise,
1557 GetPseudoRestriction(nsStyleContext
*aContext
)
1559 // This needs to match nsStyleSet::WalkRestrictionRule.
1560 PRUint32 pseudoRestriction
= 0;
1561 nsIAtom
*pseudoType
= aContext
->GetPseudoType();
1563 if (pseudoType
== nsCSSPseudoElements::firstLetter
) {
1564 pseudoRestriction
= CSS_PROPERTY_APPLIES_TO_FIRST_LETTER
;
1565 } else if (pseudoType
== nsCSSPseudoElements::firstLine
) {
1566 pseudoRestriction
= CSS_PROPERTY_APPLIES_TO_FIRST_LINE
;
1569 return pseudoRestriction
;
1573 UnsetPropertiesWithoutFlags(const nsStyleStructID aSID
,
1574 nsRuleDataStruct
& aRuleDataStruct
,
1577 NS_ASSERTION(aFlags
!= 0, "aFlags must be nonzero");
1578 const StructCheckData
*structData
= gCheckProperties
+ aSID
;
1580 for (const PropertyCheckData
*prop
= structData
->props
,
1581 *prop_end
= prop
+ structData
->nprops
;
1584 if ((prop
->flags
& aFlags
) == aFlags
)
1585 // Don't unset the property.
1588 switch (prop
->type
) {
1589 case eCSSType_Value
:
1590 ValueAtOffset(aRuleDataStruct
, prop
->offset
).Reset();
1593 RectAtOffset(aRuleDataStruct
, prop
->offset
)->Reset();
1595 case eCSSType_ValuePair
:
1596 ValuePairAtOffset(aRuleDataStruct
, prop
->offset
)->Reset();
1598 case eCSSType_ValueList
:
1599 ValueListAtOffset(aRuleDataStruct
, prop
->offset
) = nsnull
;
1601 case eCSSType_ValuePairList
:
1602 ValuePairListAtOffset(aRuleDataStruct
, prop
->offset
) = nsnull
;
1605 NS_NOTREACHED("unknown type");
1612 nsRuleNode::WalkRuleTree(const nsStyleStructID aSID
,
1613 nsStyleContext
* aContext
,
1614 nsRuleData
* aRuleData
,
1615 nsRuleDataStruct
* aSpecificData
)
1617 // We start at the most specific rule in the tree.
1618 void* startStruct
= nsnull
;
1620 nsRuleNode
* ruleNode
= this;
1621 nsRuleNode
* highestNode
= nsnull
; // The highest node in the rule tree
1622 // that has the same properties
1623 // specified for struct |aSID| as
1625 nsRuleNode
* rootNode
= this; // After the loop below, this will be the
1626 // highest node that we've walked without
1627 // finding cached data on the rule tree.
1628 // If we don't find any cached data, it
1629 // will be the root. (XXX misnamed)
1630 RuleDetail detail
= eRuleNone
;
1631 PRUint32 bit
= nsCachedStyleData::GetBitForSID(aSID
);
1634 // See if this rule node has cached the fact that the remaining
1635 // nodes along this path specify no data whatsoever.
1636 if (ruleNode
->mNoneBits
& bit
)
1639 // If the dependent bit is set on a rule node for this struct, that
1640 // means its rule won't have any information to add, so skip it.
1641 // XXXldb I don't understand why we need to check |detail| here, but
1643 if (detail
== eRuleNone
)
1644 while (ruleNode
->mDependentBits
& bit
) {
1645 NS_ASSERTION(ruleNode
->mStyleData
.GetStyleData(aSID
) == nsnull
,
1646 "dependent bit with cached data makes no sense");
1647 // Climb up to the next rule in the tree (a less specific rule).
1648 rootNode
= ruleNode
;
1649 ruleNode
= ruleNode
->mParent
;
1650 NS_ASSERTION(!(ruleNode
->mNoneBits
& bit
), "can't have both bits set");
1653 // Check for cached data after the inner loop above -- otherwise
1655 startStruct
= ruleNode
->mStyleData
.GetStyleData(aSID
);
1657 break; // We found a rule with fully specified data. We don't
1658 // need to go up the tree any further, since the remainder
1659 // of this branch has already been computed.
1661 // Ask the rule to fill in the properties that it specifies.
1662 nsIStyleRule
*rule
= ruleNode
->mRule
;
1664 aRuleData
->mLevel
= ruleNode
->GetLevel();
1665 aRuleData
->mIsImportantRule
= ruleNode
->IsImportantRule();
1666 rule
->MapRuleInfoInto(aRuleData
);
1669 // Now we check to see how many properties have been specified by
1670 // the rules we've examined so far.
1671 RuleDetail oldDetail
= detail
;
1672 detail
= CheckSpecifiedProperties(aSID
, *aSpecificData
);
1674 if (oldDetail
== eRuleNone
&& detail
!= eRuleNone
)
1675 highestNode
= ruleNode
;
1677 if (detail
== eRuleFullReset
||
1678 detail
== eRuleFullMixed
||
1679 detail
== eRuleFullInherited
)
1680 break; // We don't need to examine any more rules. All properties
1681 // have been fully specified.
1683 // Climb up to the next rule in the tree (a less specific rule).
1684 rootNode
= ruleNode
;
1685 ruleNode
= ruleNode
->mParent
;
1688 // If needed, unset the properties that don't have a flag that allows
1689 // them to be set for this style context. (For example, only some
1690 // properties apply to :first-line and :first-letter.)
1691 PRUint32 pseudoRestriction
= GetPseudoRestriction(aContext
);
1692 if (pseudoRestriction
) {
1693 UnsetPropertiesWithoutFlags(aSID
, *aSpecificData
, pseudoRestriction
);
1695 // Recompute |detail| based on the restrictions we just applied.
1696 // We can adjust |detail| arbitrarily because of the restriction
1697 // rule added in nsStyleSet::WalkRestrictionRule.
1698 detail
= CheckSpecifiedProperties(aSID
, *aSpecificData
);
1701 NS_ASSERTION(!startStruct
|| (detail
!= eRuleFullReset
&&
1702 detail
!= eRuleFullMixed
&&
1703 detail
!= eRuleFullInherited
),
1704 "can't have start struct and be fully specified");
1706 PRBool isReset
= nsCachedStyleData::IsReset(aSID
);
1708 highestNode
= rootNode
;
1710 if (!aRuleData
->mCanStoreInRuleTree
)
1711 detail
= eRulePartialMixed
; // Treat as though some data is specified to avoid
1712 // the optimizations and force data computation.
1714 if (detail
== eRuleNone
&& startStruct
&& !aRuleData
->mPostResolveCallback
) {
1715 // We specified absolutely no rule information, but a parent rule in the tree
1716 // specified all the rule information. We set a bit along the branch from our
1717 // node in the tree to the node that specified the data that tells nodes on that
1718 // branch that they never need to examine their rules for this particular struct type
1720 PropagateDependentBit(bit
, ruleNode
);
1723 // FIXME Do we need to check for mPostResolveCallback?
1724 if ((!startStruct
&& !isReset
&&
1725 (detail
== eRuleNone
|| detail
== eRulePartialInherited
)) ||
1726 detail
== eRuleFullInherited
) {
1727 // We specified no non-inherited information and neither did any of
1728 // our parent rules.
1730 // We set a bit along the branch from the highest node (ruleNode)
1731 // down to our node (this) indicating that no non-inherited data was
1732 // specified. This bit is guaranteed to be set already on the path
1733 // from the highest node to the root node in the case where
1734 // (detail == eRuleNone), which is the most common case here.
1735 // We must check |!isReset| because the Compute*Data functions for
1736 // reset structs wouldn't handle none bits correctly.
1737 if (highestNode
!= this && !isReset
)
1738 PropagateNoneBit(bit
, highestNode
);
1740 // All information must necessarily be inherited from our parent style context.
1741 // In the absence of any computed data in the rule tree and with
1742 // no rules specified that didn't have values of 'inherit', we should check our parent.
1743 nsStyleContext
* parentContext
= aContext
->GetParent();
1745 /* Reset structs don't inherit from first-line. */
1746 /* See similar code in COMPUTE_START_RESET */
1747 while (parentContext
&&
1748 parentContext
->GetPseudoType() == nsCSSPseudoElements::firstLine
) {
1749 parentContext
= parentContext
->GetParent();
1752 if (parentContext
) {
1753 // We have a parent, and so we should just inherit from the parent.
1754 // Set the inherit bits on our context. These bits tell the style context that
1755 // it never has to go back to the rule tree for data. Instead the style context tree
1756 // should be walked to find the data.
1757 const void* parentStruct
= parentContext
->GetStyleData(aSID
);
1758 aContext
->AddStyleBit(bit
); // makes const_cast OK.
1759 aContext
->SetStyle(aSID
, const_cast<void*>(parentStruct
));
1760 return parentStruct
;
1763 // We are the root. In the case of fonts, the default values just
1764 // come from the pres context.
1765 return SetDefaultOnRoot(aSID
, aContext
);
1768 // We need to compute the data from the information that the rules specified.
1770 #define STYLE_STRUCT_TEST aSID
1771 #define STYLE_STRUCT(name, checkdata_cb, ctor_args) \
1772 res = Compute##name##Data(startStruct, *aSpecificData, aContext, \
1773 highestNode, detail, !aRuleData->mCanStoreInRuleTree);
1774 #include "nsStyleStructList.h"
1776 #undef STYLE_STRUCT_TEST
1778 // If we have a post-resolve callback, handle that now.
1779 if (aRuleData
->mPostResolveCallback
&& (NS_LIKELY(res
!= nsnull
)))
1780 (*aRuleData
->mPostResolveCallback
)(const_cast<void*>(res
), aRuleData
);
1782 // Now return the result.
1787 nsRuleNode::SetDefaultOnRoot(const nsStyleStructID aSID
, nsStyleContext
* aContext
)
1790 case eStyleStruct_Font
:
1792 nsStyleFont
* fontData
= new (mPresContext
) nsStyleFont(mPresContext
);
1793 if (NS_LIKELY(fontData
!= nsnull
)) {
1794 nscoord minimumFontSize
=
1795 mPresContext
->GetCachedIntPref(kPresContext_MinimumFontSize
);
1797 if (minimumFontSize
> 0 && !mPresContext
->IsChrome()) {
1798 fontData
->mFont
.size
= PR_MAX(fontData
->mSize
, minimumFontSize
);
1801 fontData
->mFont
.size
= fontData
->mSize
;
1803 aContext
->SetStyle(eStyleStruct_Font
, fontData
);
1807 case eStyleStruct_Display
:
1809 nsStyleDisplay
* disp
= new (mPresContext
) nsStyleDisplay();
1810 if (NS_LIKELY(disp
!= nsnull
)) {
1811 aContext
->SetStyle(eStyleStruct_Display
, disp
);
1815 case eStyleStruct_Visibility
:
1817 nsStyleVisibility
* vis
= new (mPresContext
) nsStyleVisibility(mPresContext
);
1818 if (NS_LIKELY(vis
!= nsnull
)) {
1819 aContext
->SetStyle(eStyleStruct_Visibility
, vis
);
1823 case eStyleStruct_Text
:
1825 nsStyleText
* text
= new (mPresContext
) nsStyleText();
1826 if (NS_LIKELY(text
!= nsnull
)) {
1827 aContext
->SetStyle(eStyleStruct_Text
, text
);
1831 case eStyleStruct_TextReset
:
1833 nsStyleTextReset
* text
= new (mPresContext
) nsStyleTextReset();
1834 if (NS_LIKELY(text
!= nsnull
)) {
1835 aContext
->SetStyle(eStyleStruct_TextReset
, text
);
1839 case eStyleStruct_Color
:
1841 nsStyleColor
* color
= new (mPresContext
) nsStyleColor(mPresContext
);
1842 if (NS_LIKELY(color
!= nsnull
)) {
1843 aContext
->SetStyle(eStyleStruct_Color
, color
);
1847 case eStyleStruct_Background
:
1849 nsStyleBackground
* bg
= new (mPresContext
) nsStyleBackground();
1850 if (NS_LIKELY(bg
!= nsnull
)) {
1851 aContext
->SetStyle(eStyleStruct_Background
, bg
);
1855 case eStyleStruct_Margin
:
1857 nsStyleMargin
* margin
= new (mPresContext
) nsStyleMargin();
1858 if (NS_LIKELY(margin
!= nsnull
)) {
1859 aContext
->SetStyle(eStyleStruct_Margin
, margin
);
1863 case eStyleStruct_Border
:
1865 nsStyleBorder
* border
= new (mPresContext
) nsStyleBorder(mPresContext
);
1866 if (NS_LIKELY(border
!= nsnull
)) {
1867 aContext
->SetStyle(eStyleStruct_Border
, border
);
1871 case eStyleStruct_Padding
:
1873 nsStylePadding
* padding
= new (mPresContext
) nsStylePadding();
1874 if (NS_LIKELY(padding
!= nsnull
)) {
1875 aContext
->SetStyle(eStyleStruct_Padding
, padding
);
1879 case eStyleStruct_Outline
:
1881 nsStyleOutline
* outline
= new (mPresContext
) nsStyleOutline(mPresContext
);
1882 if (NS_LIKELY(outline
!= nsnull
)) {
1883 aContext
->SetStyle(eStyleStruct_Outline
, outline
);
1887 case eStyleStruct_List
:
1889 nsStyleList
* list
= new (mPresContext
) nsStyleList();
1890 if (NS_LIKELY(list
!= nsnull
)) {
1891 aContext
->SetStyle(eStyleStruct_List
, list
);
1895 case eStyleStruct_Position
:
1897 nsStylePosition
* pos
= new (mPresContext
) nsStylePosition();
1898 if (NS_LIKELY(pos
!= nsnull
)) {
1899 aContext
->SetStyle(eStyleStruct_Position
, pos
);
1903 case eStyleStruct_Table
:
1905 nsStyleTable
* table
= new (mPresContext
) nsStyleTable();
1906 if (NS_LIKELY(table
!= nsnull
)) {
1907 aContext
->SetStyle(eStyleStruct_Table
, table
);
1911 case eStyleStruct_TableBorder
:
1913 nsStyleTableBorder
* table
= new (mPresContext
) nsStyleTableBorder(mPresContext
);
1914 if (NS_LIKELY(table
!= nsnull
)) {
1915 aContext
->SetStyle(eStyleStruct_TableBorder
, table
);
1919 case eStyleStruct_Content
:
1921 nsStyleContent
* content
= new (mPresContext
) nsStyleContent();
1922 if (NS_LIKELY(content
!= nsnull
)) {
1923 aContext
->SetStyle(eStyleStruct_Content
, content
);
1927 case eStyleStruct_Quotes
:
1929 nsStyleQuotes
* quotes
= new (mPresContext
) nsStyleQuotes();
1930 if (NS_LIKELY(quotes
!= nsnull
)) {
1931 aContext
->SetStyle(eStyleStruct_Quotes
, quotes
);
1935 case eStyleStruct_UserInterface
:
1937 nsStyleUserInterface
* ui
= new (mPresContext
) nsStyleUserInterface();
1938 if (NS_LIKELY(ui
!= nsnull
)) {
1939 aContext
->SetStyle(eStyleStruct_UserInterface
, ui
);
1943 case eStyleStruct_UIReset
:
1945 nsStyleUIReset
* ui
= new (mPresContext
) nsStyleUIReset();
1946 if (NS_LIKELY(ui
!= nsnull
)) {
1947 aContext
->SetStyle(eStyleStruct_UIReset
, ui
);
1952 case eStyleStruct_XUL
:
1954 nsStyleXUL
* xul
= new (mPresContext
) nsStyleXUL();
1955 if (NS_LIKELY(xul
!= nsnull
)) {
1956 aContext
->SetStyle(eStyleStruct_XUL
, xul
);
1961 case eStyleStruct_Column
:
1963 nsStyleColumn
* column
= new (mPresContext
) nsStyleColumn(mPresContext
);
1964 if (NS_LIKELY(column
!= nsnull
)) {
1965 aContext
->SetStyle(eStyleStruct_Column
, column
);
1971 case eStyleStruct_SVG
:
1973 nsStyleSVG
* svg
= new (mPresContext
) nsStyleSVG();
1974 if (NS_LIKELY(svg
!= nsnull
)) {
1975 aContext
->SetStyle(eStyleStruct_SVG
, svg
);
1980 case eStyleStruct_SVGReset
:
1982 nsStyleSVGReset
* svgReset
= new (mPresContext
) nsStyleSVGReset();
1983 if (NS_LIKELY(svgReset
!= nsnull
)) {
1984 aContext
->SetStyle(eStyleStruct_SVGReset
, svgReset
);
1991 * unhandled case: nsStyleStructID_Length.
1992 * last item of nsStyleStructID, to know its length.
2000 * This function handles cascading of *-left or *-right box properties
2001 * against *-start (which is L for LTR and R for RTL) or *-end (which is
2002 * R for LTR and L for RTL).
2004 * Cascading these properties correctly is hard because we need to
2005 * cascade two properties as one, but which two properties depends on a
2006 * third property ('direction'). We solve this by treating each of
2007 * these properties (say, 'margin-start') as a shorthand that sets a
2008 * property containing the value of the property specified
2009 * ('margin-start-value') and sets a pair of properties
2010 * ('margin-left-ltr-source' and 'margin-right-rtl-source') saying which
2011 * of the properties we use. Thus, when we want to compute the value of
2012 * 'margin-left' when 'direction' is 'ltr', we look at the value of
2013 * 'margin-left-ltr-source', which tells us whether to use the highest
2014 * 'margin-left' in the cascade or the highest 'margin-start'.
2016 * Finally, since we can compute the normal (*-left and *-right)
2017 * properties in a loop, this function works by modifying the data we
2018 * will use in that loop (which the caller must copy from the const
2022 nsRuleNode::AdjustLogicalBoxProp(nsStyleContext
* aContext
,
2023 const nsCSSValue
& aLTRSource
,
2024 const nsCSSValue
& aRTLSource
,
2025 const nsCSSValue
& aLTRLogicalValue
,
2026 const nsCSSValue
& aRTLLogicalValue
,
2028 nsCSSRect
& aValueRect
,
2031 PRBool LTRlogical
= aLTRSource
.GetUnit() == eCSSUnit_Enumerated
&&
2032 aLTRSource
.GetIntValue() == NS_BOXPROP_SOURCE_LOGICAL
;
2033 PRBool RTLlogical
= aRTLSource
.GetUnit() == eCSSUnit_Enumerated
&&
2034 aRTLSource
.GetIntValue() == NS_BOXPROP_SOURCE_LOGICAL
;
2035 if (LTRlogical
|| RTLlogical
) {
2036 // We can't cache anything on the rule tree if we use any data from
2037 // the style context, since data cached in the rule tree could be
2038 // used with a style context with a different value.
2039 aInherited
= PR_TRUE
;
2040 PRUint8 dir
= aContext
->GetStyleVisibility()->mDirection
;
2042 if (dir
== NS_STYLE_DIRECTION_LTR
) {
2044 aValueRect
.*(nsCSSRect::sides
[aSide
]) = aLTRLogicalValue
;
2047 aValueRect
.*(nsCSSRect::sides
[aSide
]) = aRTLLogicalValue
;
2053 * Begin an nsRuleNode::Compute*Data function for an inherited struct.
2055 * @param type_ The nsStyle* type this function computes.
2056 * @param ctorargs_ The arguments used for the default nsStyle* constructor.
2057 * @param data_ Variable (declared here) holding the result of this
2059 * @param parentdata_ Variable (declared here) holding the parent style
2060 * context's data for this struct.
2061 * @param rdtype_ The nsCSS* struct type used to compute this struct's data.
2062 * @param rdata_ Variable (declared here) holding the nsCSS* used here.
2064 #define COMPUTE_START_INHERITED(type_, ctorargs_, data_, parentdata_, rdtype_, rdata_) \
2065 NS_ASSERTION(aRuleDetail != eRuleFullInherited, \
2066 "should not have bothered calling Compute*Data"); \
2068 nsStyleContext* parentContext = aContext->GetParent(); \
2070 const nsRuleData##rdtype_& rdata_ = \
2071 static_cast<const nsRuleData##rdtype_&>(aData); \
2072 nsStyle##type_* data_ = nsnull; \
2073 const nsStyle##type_* parentdata_ = nsnull; \
2074 PRBool inherited = aInherited; \
2076 /* If |inherited| might be false by the time we're done, we can't call */ \
2077 /* parentContext->GetStyle##type_() since it could recur into setting */ \
2078 /* the same struct on the same rule node, causing a leak. */ \
2079 if (parentContext && aRuleDetail != eRuleFullReset && \
2080 (!aStartStruct || (aRuleDetail != eRulePartialReset && \
2081 aRuleDetail != eRuleNone))) \
2082 parentdata_ = parentContext->GetStyle##type_(); \
2084 /* We only need to compute the delta between this computed data and */ \
2085 /* our computed data. */ \
2086 data_ = new (mPresContext) \
2087 nsStyle##type_(*static_cast<nsStyle##type_*>(aStartStruct)); \
2089 if (aRuleDetail != eRuleFullMixed && aRuleDetail != eRuleFullReset) { \
2090 /* No question. We will have to inherit. Go ahead and init */ \
2091 /* with inherited vals from parent. */ \
2092 inherited = PR_TRUE; \
2094 data_ = new (mPresContext) nsStyle##type_(*parentdata_); \
2096 data_ = new (mPresContext) nsStyle##type_ ctorargs_; \
2099 data_ = new (mPresContext) nsStyle##type_ ctorargs_; \
2102 if (NS_UNLIKELY(!data_)) \
2103 return nsnull; /* Out Of Memory */ \
2105 parentdata_ = data_;
2108 * Begin an nsRuleNode::Compute*Data function for a reset struct.
2110 * @param type_ The nsStyle* type this function computes.
2111 * @param ctorargs_ The arguments used for the default nsStyle* constructor.
2112 * @param data_ Variable (declared here) holding the result of this
2114 * @param parentdata_ Variable (declared here) holding the parent style
2115 * context's data for this struct.
2116 * @param rdtype_ The nsCSS* struct type used to compute this struct's data.
2117 * @param rdata_ Variable (declared here) holding the nsCSS* used here.
2119 #define COMPUTE_START_RESET(type_, ctorargs_, data_, parentdata_, rdtype_, rdata_) \
2120 NS_ASSERTION(aRuleDetail != eRuleFullInherited, \
2121 "should not have bothered calling Compute*Data"); \
2123 nsStyleContext* parentContext = aContext->GetParent(); \
2124 /* Reset structs don't inherit from first-line */ \
2125 /* See similar code in WalkRuleTree */ \
2126 while (parentContext && \
2127 parentContext->GetPseudoType() == nsCSSPseudoElements::firstLine) { \
2128 parentContext = parentContext->GetParent(); \
2131 const nsRuleData##rdtype_& rdata_ = \
2132 static_cast<const nsRuleData##rdtype_&>(aData); \
2133 nsStyle##type_* data_; \
2135 /* We only need to compute the delta between this computed data and */ \
2136 /* our computed data. */ \
2137 data_ = new (mPresContext) \
2138 nsStyle##type_(*static_cast<nsStyle##type_*>(aStartStruct)); \
2140 data_ = new (mPresContext) nsStyle##type_ ctorargs_; \
2142 if (NS_UNLIKELY(!data_)) \
2143 return nsnull; /* Out Of Memory */ \
2145 /* If |inherited| might be false by the time we're done, we can't call */ \
2146 /* parentContext->GetStyle##type_() since it could recur into setting */ \
2147 /* the same struct on the same rule node, causing a leak. */ \
2148 const nsStyle##type_* parentdata_ = data_; \
2149 if (parentContext && \
2150 aRuleDetail != eRuleFullReset && \
2151 aRuleDetail != eRulePartialReset && \
2152 aRuleDetail != eRuleNone) \
2153 parentdata_ = parentContext->GetStyle##type_(); \
2154 PRBool inherited = aInherited;
2157 * Begin an nsRuleNode::Compute*Data function for an inherited struct.
2159 * @param type_ The nsStyle* type this function computes.
2160 * @param data_ Variable holding the result of this function.
2162 #define COMPUTE_END_INHERITED(type_, data_) \
2164 /* We inherited, and therefore can't be cached in the rule node. We */ \
2165 /* have to be put right on the style context. */ \
2166 aContext->SetStyle(eStyleStruct_##type_, data_); \
2168 /* We were fully specified and can therefore be cached right on the */ \
2170 if (!aHighestNode->mStyleData.mInheritedData) { \
2171 aHighestNode->mStyleData.mInheritedData = \
2172 new (mPresContext) nsInheritedStyleData; \
2173 if (NS_UNLIKELY(!aHighestNode->mStyleData.mInheritedData)) { \
2174 data_->Destroy(mPresContext); \
2178 aHighestNode->mStyleData.mInheritedData->m##type_##Data = data_; \
2179 /* Propagate the bit down. */ \
2180 PropagateDependentBit(NS_STYLE_INHERIT_BIT(type_), aHighestNode); \
2186 * Begin an nsRuleNode::Compute*Data function for a reset struct.
2188 * @param type_ The nsStyle* type this function computes.
2189 * @param data_ Variable holding the result of this function.
2191 #define COMPUTE_END_RESET(type_, data_) \
2193 /* We inherited, and therefore can't be cached in the rule node. We */ \
2194 /* have to be put right on the style context. */ \
2195 aContext->SetStyle(eStyleStruct_##type_, data_); \
2197 /* We were fully specified and can therefore be cached right on the */ \
2199 if (!aHighestNode->mStyleData.mResetData) { \
2200 aHighestNode->mStyleData.mResetData = \
2201 new (mPresContext) nsResetStyleData; \
2202 if (NS_UNLIKELY(!aHighestNode->mStyleData.mResetData)) { \
2203 data_->Destroy(mPresContext); \
2207 aHighestNode->mStyleData.mResetData->m##type_##Data = data_; \
2208 /* Propagate the bit down. */ \
2209 PropagateDependentBit(NS_STYLE_INHERIT_BIT(type_), aHighestNode); \
2215 // This function figures out how much scaling should be suppressed to
2216 // satisfy scriptminsize. This is our attempt to implement
2217 // http://www.w3.org/TR/MathML2/chapter3.html#id.3.3.4.2.2
2218 // This is called after mScriptLevel, mScriptMinSize and mScriptSizeMultiplier
2219 // have been set in aFont.
2221 // Here are the invariants we enforce:
2222 // 1) A decrease in size must not reduce the size below minscriptsize.
2223 // 2) An increase in size must not increase the size above the size we would
2224 // have if minscriptsize had not been applied anywhere.
2225 // 3) The scriptlevel-induced size change must between 1.0 and the parent's
2226 // scriptsizemultiplier^(new script level - old script level), as close to the
2227 // latter as possible subject to constraints 1 and 2.
2229 ComputeScriptLevelSize(const nsStyleFont
* aFont
, const nsStyleFont
* aParentFont
,
2230 nsPresContext
* aPresContext
, nscoord
* aUnconstrainedSize
)
2232 PRInt32 scriptLevelChange
=
2233 aFont
->mScriptLevel
- aParentFont
->mScriptLevel
;
2234 if (scriptLevelChange
== 0) {
2235 *aUnconstrainedSize
= aParentFont
->mScriptUnconstrainedSize
;
2236 // Constraint #3 says that we cannot change size, and #1 and #2 are always
2237 // satisfied with no change. It's important this be fast because it covers
2238 // all non-MathML content.
2239 return aParentFont
->mSize
;
2242 // Compute actual value of minScriptSize
2243 nscoord minScriptSize
=
2244 nsStyleFont::ZoomText(aPresContext
, aParentFont
->mScriptMinSize
);
2246 double scriptLevelScale
=
2247 pow(aParentFont
->mScriptSizeMultiplier
, scriptLevelChange
);
2248 // Compute the size we would have had if minscriptsize had never been
2249 // applied, also prevent overflow (bug 413274)
2250 *aUnconstrainedSize
=
2251 NSToCoordRound(PR_MIN(aParentFont
->mScriptUnconstrainedSize
*scriptLevelScale
,
2253 // Compute the size we could get via scriptlevel change
2254 nscoord scriptLevelSize
=
2255 NSToCoordRound(PR_MIN(aParentFont
->mSize
*scriptLevelScale
,
2257 if (scriptLevelScale
<= 1.0) {
2258 if (aParentFont
->mSize
<= minScriptSize
) {
2259 // We can't decrease the font size at all, so just stick to no change
2260 // (authors are allowed to explicitly set the font size smaller than
2262 return aParentFont
->mSize
;
2264 // We can decrease, so apply constraint #1
2265 return PR_MAX(minScriptSize
, scriptLevelSize
);
2267 // scriptminsize can only make sizes larger than the unconstrained size
2268 NS_ASSERTION(*aUnconstrainedSize
<= scriptLevelSize
, "How can this ever happen?");
2269 // Apply constraint #2
2270 return PR_MIN(scriptLevelSize
, PR_MAX(*aUnconstrainedSize
, minScriptSize
));
2276 nsRuleNode::SetFontSize(nsPresContext
* aPresContext
,
2277 const nsRuleDataFont
& aFontData
,
2278 const nsStyleFont
* aFont
,
2279 const nsStyleFont
* aParentFont
,
2281 const nsFont
& aSystemFont
,
2282 nscoord aParentSize
,
2283 nscoord aScriptLevelAdjustedParentSize
,
2284 PRBool aUsedStartStruct
,
2287 PRBool zoom
= PR_FALSE
;
2288 PRInt32 baseSize
= (PRInt32
) aPresContext
->
2289 GetDefaultFont(aFont
->mGenericID
)->size
;
2290 if (eCSSUnit_Enumerated
== aFontData
.mSize
.GetUnit()) {
2291 PRInt32 value
= aFontData
.mSize
.GetIntValue();
2292 PRInt32 scaler
= aPresContext
->FontScaler();
2293 float scaleFactor
= nsStyleUtil::GetScalingFactor(scaler
);
2296 if ((NS_STYLE_FONT_SIZE_XXSMALL
<= value
) &&
2297 (value
<= NS_STYLE_FONT_SIZE_XXLARGE
)) {
2298 *aSize
= nsStyleUtil::CalcFontPointSize(value
, baseSize
,
2299 scaleFactor
, aPresContext
, eFontSize_CSS
);
2301 else if (NS_STYLE_FONT_SIZE_XXXLARGE
== value
) {
2302 // <font size="7"> is not specified in CSS, so we don't use eFontSize_CSS.
2303 *aSize
= nsStyleUtil::CalcFontPointSize(value
, baseSize
,
2304 scaleFactor
, aPresContext
);
2306 else if (NS_STYLE_FONT_SIZE_LARGER
== value
||
2307 NS_STYLE_FONT_SIZE_SMALLER
== value
) {
2308 aInherited
= PR_TRUE
;
2310 // Un-zoom so we use the tables correctly. We'll then rezoom due
2311 // to the |zoom = PR_TRUE| above.
2312 // Note that relative units here use the parent's size unadjusted
2313 // for scriptlevel changes. A scriptlevel change between us and the parent
2314 // is simply ignored.
2315 nscoord parentSize
=
2316 nsStyleFont::UnZoomText(aPresContext
, aParentSize
);
2318 if (NS_STYLE_FONT_SIZE_LARGER
== value
) {
2319 *aSize
= nsStyleUtil::FindNextLargerFontSize(parentSize
,
2320 baseSize
, scaleFactor
, aPresContext
, eFontSize_CSS
);
2321 NS_ASSERTION(*aSize
> parentSize
,
2322 "FindNextLargerFontSize failed");
2325 *aSize
= nsStyleUtil::FindNextSmallerFontSize(parentSize
,
2326 baseSize
, scaleFactor
, aPresContext
, eFontSize_CSS
);
2327 NS_ASSERTION(*aSize
< parentSize
||
2328 parentSize
<= nsPresContext::CSSPixelsToAppUnits(1),
2329 "FindNextSmallerFontSize failed");
2332 NS_NOTREACHED("unexpected value");
2335 else if (aFontData
.mSize
.IsLengthUnit()) {
2336 // Note that font-based length units use the parent's size unadjusted
2337 // for scriptlevel changes. A scriptlevel change between us and the parent
2338 // is simply ignored.
2339 *aSize
= CalcLengthWith(aFontData
.mSize
, aParentSize
, aParentFont
, nsnull
,
2340 aPresContext
, aInherited
);
2341 zoom
= aFontData
.mSize
.IsFixedLengthUnit() ||
2342 aFontData
.mSize
.GetUnit() == eCSSUnit_Pixel
;
2344 else if (eCSSUnit_Percent
== aFontData
.mSize
.GetUnit()) {
2345 aInherited
= PR_TRUE
;
2346 // Note that % units use the parent's size unadjusted for scriptlevel
2347 // changes. A scriptlevel change between us and the parent is simply
2349 *aSize
= NSToCoordRound(aParentSize
*
2350 aFontData
.mSize
.GetPercentValue());
2353 else if (eCSSUnit_System_Font
== aFontData
.mSize
.GetUnit()) {
2354 // this becomes our cascading size
2355 *aSize
= aSystemFont
.size
;
2358 else if (eCSSUnit_Inherit
== aFontData
.mSize
.GetUnit()) {
2359 aInherited
= PR_TRUE
;
2360 // We apply scriptlevel change for this case, because the default is
2361 // to inherit and we don't want explicit "inherit" to differ from the
2363 *aSize
= aScriptLevelAdjustedParentSize
;
2366 else if (eCSSUnit_Initial
== aFontData
.mSize
.GetUnit()) {
2367 // The initial value is 'medium', which has magical sizing based on
2368 // the generic font family, so do that here too.
2372 NS_ASSERTION(eCSSUnit_Null
== aFontData
.mSize
.GetUnit(),
2373 "What kind of font-size value is this?");
2375 // if aUsedStartStruct is true, then every single property in the
2376 // font struct is being set all at once. This means scriptlevel is not
2377 // going to have any influence on the font size; there is no need to
2378 // do anything here.
2379 if (!aUsedStartStruct
&& aParentSize
!= aScriptLevelAdjustedParentSize
) {
2380 // There was no rule affecting the size but the size has been
2381 // affected by the parent's size via scriptlevel change. So treat
2382 // this as inherited.
2383 aInherited
= PR_TRUE
;
2384 *aSize
= aScriptLevelAdjustedParentSize
;
2389 // We want to zoom the cascaded size so that em-based measurements,
2390 // line-heights, etc., work.
2392 *aSize
= nsStyleFont::ZoomText(aPresContext
, *aSize
);
2396 static PRInt8
ClampTo8Bit(PRInt32 aValue
) {
2401 return PRInt8(aValue
);
2405 nsRuleNode::SetFont(nsPresContext
* aPresContext
, nsStyleContext
* aContext
,
2406 nscoord aMinFontSize
,
2407 PRUint8 aGenericFontID
, const nsRuleDataFont
& aFontData
,
2408 const nsStyleFont
* aParentFont
,
2409 nsStyleFont
* aFont
, PRBool aUsedStartStruct
,
2412 const nsFont
* defaultVariableFont
=
2413 aPresContext
->GetDefaultFont(kPresContext_DefaultVariableFont_ID
);
2415 // -moz-system-font: enum (never inherit!)
2417 if (eCSSUnit_Enumerated
== aFontData
.mSystemFont
.GetUnit()) {
2418 nsSystemFontID sysID
;
2419 switch (aFontData
.mSystemFont
.GetIntValue()) {
2420 case NS_STYLE_FONT_CAPTION
: sysID
= eSystemFont_Caption
; break; // css2
2421 case NS_STYLE_FONT_ICON
: sysID
= eSystemFont_Icon
; break;
2422 case NS_STYLE_FONT_MENU
: sysID
= eSystemFont_Menu
; break;
2423 case NS_STYLE_FONT_MESSAGE_BOX
: sysID
= eSystemFont_MessageBox
; break;
2424 case NS_STYLE_FONT_SMALL_CAPTION
: sysID
= eSystemFont_SmallCaption
; break;
2425 case NS_STYLE_FONT_STATUS_BAR
: sysID
= eSystemFont_StatusBar
; break;
2426 case NS_STYLE_FONT_WINDOW
: sysID
= eSystemFont_Window
; break; // css3
2427 case NS_STYLE_FONT_DOCUMENT
: sysID
= eSystemFont_Document
; break;
2428 case NS_STYLE_FONT_WORKSPACE
: sysID
= eSystemFont_Workspace
; break;
2429 case NS_STYLE_FONT_DESKTOP
: sysID
= eSystemFont_Desktop
; break;
2430 case NS_STYLE_FONT_INFO
: sysID
= eSystemFont_Info
; break;
2431 case NS_STYLE_FONT_DIALOG
: sysID
= eSystemFont_Dialog
; break;
2432 case NS_STYLE_FONT_BUTTON
: sysID
= eSystemFont_Button
; break;
2433 case NS_STYLE_FONT_PULL_DOWN_MENU
:sysID
= eSystemFont_PullDownMenu
; break;
2434 case NS_STYLE_FONT_LIST
: sysID
= eSystemFont_List
; break;
2435 case NS_STYLE_FONT_FIELD
: sysID
= eSystemFont_Field
; break;
2438 // GetSystemFont sets the font face but not necessarily the size
2439 // XXX Or at least it used to -- no longer true for thebes. Maybe
2440 // it should be again, though.
2441 systemFont
.size
= defaultVariableFont
->size
;
2443 if (NS_FAILED(aPresContext
->DeviceContext()->GetSystemFont(sysID
,
2445 systemFont
.name
= defaultVariableFont
->name
;
2448 // XXXldb All of this platform-specific stuff should be in the
2449 // nsIDeviceContext implementations, not here.
2453 // As far as I can tell the system default fonts and sizes for
2454 // on MS-Windows for Buttons, Listboxes/Comboxes and Text Fields are
2455 // all pre-determined and cannot be changed by either the control panel
2456 // or programmtically.
2459 // Fields (text fields)
2460 // Button and Selects (listboxes/comboboxes)
2461 // We use whatever font is defined by the system. Which it appears
2462 // (and the assumption is) it is always a proportional font. Then we
2463 // always use 2 points smaller than what the browser has defined as
2464 // the default proportional font.
2465 case eSystemFont_Field
:
2466 case eSystemFont_Button
:
2467 case eSystemFont_List
:
2468 // Assumption: system defined font is proportional
2470 PR_MAX(defaultVariableFont
->size
- aPresContext
->PointsToAppUnits(2), 0);
2475 // In case somebody explicitly used -moz-use-system-font.
2476 systemFont
= *defaultVariableFont
;
2480 // font-family: string list, enum, inherit
2481 NS_ASSERTION(eCSSUnit_Enumerated
!= aFontData
.mFamily
.GetUnit(),
2482 "system fonts should not be in mFamily anymore");
2483 if (eCSSUnit_String
== aFontData
.mFamily
.GetUnit()) {
2484 // set the correct font if we are using DocumentFonts OR we are overriding for XUL
2486 if (aGenericFontID
== kGenericFont_NONE
) {
2487 // only bother appending fallback fonts if this isn't a fallback generic font itself
2488 if (!aFont
->mFont
.name
.IsEmpty())
2489 aFont
->mFont
.name
.Append((PRUnichar
)',');
2490 // defaultVariableFont.name should always be "serif" or "sans-serif".
2491 aFont
->mFont
.name
.Append(defaultVariableFont
->name
);
2493 aFont
->mFont
.familyNameQuirks
=
2494 (aPresContext
->CompatibilityMode() == eCompatibility_NavQuirks
&&
2495 aFontData
.mFamilyFromHTML
);
2496 aFont
->mFont
.systemFont
= PR_FALSE
;
2497 // Technically this is redundant with the code below, but it's good
2498 // to have since we'll still want it once we get rid of
2499 // SetGenericFont (bug 380915).
2500 aFont
->mGenericID
= aGenericFontID
;
2502 else if (eCSSUnit_System_Font
== aFontData
.mFamily
.GetUnit()) {
2503 aFont
->mFont
.name
= systemFont
.name
;
2504 aFont
->mFont
.familyNameQuirks
= PR_FALSE
;
2505 aFont
->mFont
.systemFont
= PR_TRUE
;
2506 aFont
->mGenericID
= kGenericFont_NONE
;
2508 else if (eCSSUnit_Inherit
== aFontData
.mFamily
.GetUnit()) {
2509 aInherited
= PR_TRUE
;
2510 aFont
->mFont
.name
= aParentFont
->mFont
.name
;
2511 aFont
->mFont
.familyNameQuirks
= aParentFont
->mFont
.familyNameQuirks
;
2512 aFont
->mFont
.systemFont
= aParentFont
->mFont
.systemFont
;
2513 aFont
->mGenericID
= aParentFont
->mGenericID
;
2515 else if (eCSSUnit_Initial
== aFontData
.mFamily
.GetUnit()) {
2516 aFont
->mFont
.name
= defaultVariableFont
->name
;
2517 aFont
->mFont
.familyNameQuirks
= PR_FALSE
;
2518 aFont
->mFont
.systemFont
= defaultVariableFont
->systemFont
;
2519 aFont
->mGenericID
= kGenericFont_NONE
;
2522 // When we're in the loop in SetGenericFont, we must ensure that we
2523 // always keep aFont->mFlags set to the correct generic. But we have
2524 // to be careful not to touch it when we're called directly from
2525 // ComputeFontData, because we could have a start struct.
2526 if (aGenericFontID
!= kGenericFont_NONE
) {
2527 aFont
->mGenericID
= aGenericFontID
;
2530 // font-style: enum, normal, inherit, initial, -moz-system-font
2531 SetDiscrete(aFontData
.mStyle
, aFont
->mFont
.style
, aInherited
,
2532 SETDSC_ENUMERATED
| SETDSC_NORMAL
| SETDSC_SYSTEM_FONT
,
2533 aParentFont
->mFont
.style
,
2534 defaultVariableFont
->style
,
2536 NS_STYLE_FONT_STYLE_NORMAL
,
2539 // font-variant: enum, normal, inherit, initial, -moz-system-font
2540 SetDiscrete(aFontData
.mVariant
, aFont
->mFont
.variant
, aInherited
,
2541 SETDSC_ENUMERATED
| SETDSC_NORMAL
| SETDSC_SYSTEM_FONT
,
2542 aParentFont
->mFont
.variant
,
2543 defaultVariableFont
->variant
,
2545 NS_STYLE_FONT_VARIANT_NORMAL
,
2546 systemFont
.variant
);
2548 // font-weight: int, enum, normal, inherit, initial, -moz-system-font
2549 // special handling for enum
2550 if (eCSSUnit_Enumerated
== aFontData
.mWeight
.GetUnit()) {
2551 PRInt32 value
= aFontData
.mWeight
.GetIntValue();
2553 case NS_STYLE_FONT_WEIGHT_NORMAL
:
2554 case NS_STYLE_FONT_WEIGHT_BOLD
:
2555 aFont
->mFont
.weight
= value
;
2557 case NS_STYLE_FONT_WEIGHT_BOLDER
:
2558 case NS_STYLE_FONT_WEIGHT_LIGHTER
:
2559 aInherited
= PR_TRUE
;
2560 aFont
->mFont
.weight
= nsStyleUtil::ConstrainFontWeight(aParentFont
->mFont
.weight
+ value
);
2564 SetDiscrete(aFontData
.mWeight
, aFont
->mFont
.weight
, aInherited
,
2565 SETDSC_INTEGER
| SETDSC_NORMAL
| SETDSC_SYSTEM_FONT
,
2566 aParentFont
->mFont
.weight
,
2567 defaultVariableFont
->weight
,
2569 NS_STYLE_FONT_WEIGHT_NORMAL
,
2573 // Compute scriptlevel, scriptminsize and scriptsizemultiplier now so
2574 // they're available for font-size computation.
2576 // -moz-script-min-size: length
2577 if (aFontData
.mScriptMinSize
.IsLengthUnit()) {
2578 // scriptminsize in font units (em, ex) has to be interpreted relative
2579 // to the parent font, or the size definitions are circular and we
2581 aFont
->mScriptMinSize
=
2582 CalcLengthWith(aFontData
.mScriptMinSize
, aParentFont
->mSize
, aParentFont
, nsnull
,
2583 aPresContext
, aInherited
);
2586 // -moz-script-size-multiplier: factor, inherit, initial
2587 SetFactor(aFontData
.mScriptSizeMultiplier
, aFont
->mScriptSizeMultiplier
,
2588 aInherited
, aParentFont
->mScriptSizeMultiplier
,
2589 NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER
,
2592 // -moz-script-level: integer, number, inherit
2593 if (eCSSUnit_Integer
== aFontData
.mScriptLevel
.GetUnit()) {
2595 aFont
->mScriptLevel
= ClampTo8Bit(aParentFont
->mScriptLevel
+ aFontData
.mScriptLevel
.GetIntValue());
2597 else if (eCSSUnit_Number
== aFontData
.mScriptLevel
.GetUnit()) {
2599 aFont
->mScriptLevel
= ClampTo8Bit(PRInt32(aFontData
.mScriptLevel
.GetFloatValue()));
2601 else if (eCSSUnit_Inherit
== aFontData
.mScriptSizeMultiplier
.GetUnit()) {
2602 aInherited
= PR_TRUE
;
2603 aFont
->mScriptLevel
= aParentFont
->mScriptLevel
;
2605 else if (eCSSUnit_Initial
== aFontData
.mScriptSizeMultiplier
.GetUnit()) {
2606 aFont
->mScriptLevel
= 0;
2610 // font-size: enum, length, percent, inherit
2611 nscoord scriptLevelAdjustedParentSize
= aParentFont
->mSize
;
2613 nscoord scriptLevelAdjustedUnconstrainedParentSize
;
2614 scriptLevelAdjustedParentSize
=
2615 ComputeScriptLevelSize(aFont
, aParentFont
, aPresContext
,
2616 &scriptLevelAdjustedUnconstrainedParentSize
);
2617 NS_ASSERTION(!aUsedStartStruct
|| aFont
->mScriptUnconstrainedSize
== aFont
->mSize
,
2618 "If we have a start struct, we should have reset everything coming in here");
2620 SetFontSize(aPresContext
, aFontData
, aFont
, aParentFont
, &aFont
->mSize
,
2621 systemFont
, aParentFont
->mSize
, scriptLevelAdjustedParentSize
,
2622 aUsedStartStruct
, aInherited
);
2624 if (aParentFont
->mSize
== aParentFont
->mScriptUnconstrainedSize
&&
2625 scriptLevelAdjustedParentSize
== scriptLevelAdjustedUnconstrainedParentSize
) {
2626 // Fast path: we have not been affected by scriptminsize so we don't
2627 // need to call SetFontSize again to compute the
2628 // scriptminsize-unconstrained size. This is OK even if we have a
2629 // start struct, because if we have a start struct then 'font-size'
2630 // was specified and so scriptminsize has no effect.
2631 aFont
->mScriptUnconstrainedSize
= aFont
->mSize
;
2633 SetFontSize(aPresContext
, aFontData
, aFont
, aParentFont
,
2634 &aFont
->mScriptUnconstrainedSize
, systemFont
,
2635 aParentFont
->mScriptUnconstrainedSize
,
2636 scriptLevelAdjustedUnconstrainedParentSize
,
2637 aUsedStartStruct
, aInherited
);
2639 NS_ASSERTION(aFont
->mScriptUnconstrainedSize
<= aFont
->mSize
,
2640 "scriptminsize should never be making things bigger");
2643 // enforce the user' specified minimum font-size on the value that we expose
2644 // (but don't change font-size:0)
2645 if (0 < aFont
->mSize
&& aFont
->mSize
< aMinFontSize
)
2646 aFont
->mFont
.size
= aMinFontSize
;
2648 aFont
->mFont
.size
= aFont
->mSize
;
2650 // font-size-adjust: number, none, inherit, initial, -moz-system-font
2651 if (eCSSUnit_System_Font
== aFontData
.mSizeAdjust
.GetUnit()) {
2652 aFont
->mFont
.sizeAdjust
= systemFont
.sizeAdjust
;
2654 SetFactor(aFontData
.mSizeAdjust
, aFont
->mFont
.sizeAdjust
, aInherited
,
2655 aParentFont
->mFont
.sizeAdjust
, 0.0f
, SETFCT_NONE
);
2659 // - backtrack to an ancestor with the same generic font name (possibly
2660 // up to the root where default values come from the presentation context)
2661 // - re-apply cascading rules from there without caching intermediate values
2663 nsRuleNode::SetGenericFont(nsPresContext
* aPresContext
,
2664 nsStyleContext
* aContext
,
2665 PRUint8 aGenericFontID
, nscoord aMinFontSize
,
2668 // walk up the contexts until a context with the desired generic font
2669 nsAutoVoidArray contextPath
;
2670 contextPath
.AppendElement(aContext
);
2671 nsStyleContext
* higherContext
= aContext
->GetParent();
2672 while (higherContext
) {
2673 if (higherContext
->GetStyleFont()->mGenericID
== aGenericFontID
) {
2674 // done walking up the higher contexts
2677 contextPath
.AppendElement(higherContext
);
2678 higherContext
= higherContext
->GetParent();
2681 // re-apply the cascading rules, starting from the higher context
2683 // If we stopped earlier because we reached the root of the style tree,
2684 // we will start with the default generic font from the presentation
2685 // context. Otherwise we start with the higher context.
2686 const nsFont
* defaultFont
= aPresContext
->GetDefaultFont(aGenericFontID
);
2687 nsStyleFont
parentFont(*defaultFont
, aPresContext
);
2688 if (higherContext
) {
2689 const nsStyleFont
* tmpFont
= higherContext
->GetStyleFont();
2690 parentFont
= *tmpFont
;
2692 *aFont
= parentFont
;
2695 PRUint32 fontBit
= nsCachedStyleData::GetBitForSID(eStyleStruct_Font
);
2697 for (PRInt32 i
= contextPath
.Count() - 1; i
>= 0; --i
) {
2698 nsStyleContext
* context
= (nsStyleContext
*)contextPath
[i
];
2699 nsRuleDataFont fontData
; // Declare a struct with null CSS values.
2700 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Font
), aPresContext
, context
);
2701 ruleData
.mFontData
= &fontData
;
2703 // Trimmed down version of ::WalkRuleTree() to re-apply the style rules
2704 // Note that we *do* need to do this for our own data, since what is
2705 // in |fontData| in ComputeFontData is only for the rules below
2707 for (nsRuleNode
* ruleNode
= context
->GetRuleNode(); ruleNode
;
2708 ruleNode
= ruleNode
->GetParent()) {
2709 if (ruleNode
->mNoneBits
& fontBit
)
2710 // no more font rules on this branch, get out
2713 nsIStyleRule
*rule
= ruleNode
->GetRule();
2715 ruleData
.mLevel
= ruleNode
->GetLevel();
2716 ruleData
.mIsImportantRule
= ruleNode
->IsImportantRule();
2717 rule
->MapRuleInfoInto(&ruleData
);
2721 // Compute the delta from the information that the rules specified
2723 // Avoid unnecessary operations in SetFont(). But we care if it's
2724 // the final value that we're computing.
2726 fontData
.mFamily
.Reset();
2728 nsRuleNode::SetFont(aPresContext
, context
, aMinFontSize
,
2729 aGenericFontID
, fontData
, &parentFont
, aFont
,
2732 // XXX Not sure if we need to do this here
2733 // If we have a post-resolve callback, handle that now.
2734 if (ruleData
.mPostResolveCallback
)
2735 (ruleData
.mPostResolveCallback
)(aFont
, &ruleData
);
2737 parentFont
= *aFont
;
2741 static PRBool
ExtractGeneric(const nsString
& aFamily
, PRBool aGeneric
,
2744 nsAutoString
*data
= static_cast<nsAutoString
*>(aData
);
2748 return PR_FALSE
; // stop enumeration
2754 nsRuleNode::ComputeFontData(void* aStartStruct
,
2755 const nsRuleDataStruct
& aData
,
2756 nsStyleContext
* aContext
,
2757 nsRuleNode
* aHighestNode
,
2758 const RuleDetail aRuleDetail
, PRBool aInherited
)
2760 COMPUTE_START_INHERITED(Font
, (mPresContext
), font
, parentFont
,
2763 // NOTE: The |aRuleDetail| passed in is a little bit conservative due
2764 // to the -moz-system-font property. We really don't need to consider
2765 // it here in determining whether to cache in the rule tree. However,
2766 // we do need to consider it in WalkRuleTree when deciding whether to
2767 // walk further up the tree. So this means that when the font struct
2768 // is fully specified using *longhand* properties (excluding
2769 // -moz-system-font), we won't cache in the rule tree even though we
2770 // could. However, it's pretty unlikely authors will do that
2771 // (although there is a pretty good chance they'll fully specify it
2772 // using the 'font' shorthand).
2774 // See if there is a minimum font-size constraint to honor
2775 nscoord minimumFontSize
=
2776 mPresContext
->GetCachedIntPref(kPresContext_MinimumFontSize
);
2778 if (minimumFontSize
< 0)
2779 minimumFontSize
= 0;
2781 PRBool useDocumentFonts
=
2782 mPresContext
->GetCachedBoolPref(kPresContext_UseDocumentFonts
);
2784 // See if we are in the chrome
2785 // We only need to know this to determine if we have to use the
2786 // document fonts (overriding the useDocumentFonts flag), or to
2787 // determine if we have to override the minimum font-size constraint.
2788 if ((!useDocumentFonts
|| minimumFontSize
> 0) && mPresContext
->IsChrome()) {
2789 // if we are not using document fonts, but this is a XUL document,
2790 // then we use the document fonts anyway
2791 useDocumentFonts
= PR_TRUE
;
2792 minimumFontSize
= 0;
2795 // Figure out if we are a generic font
2796 PRUint8 generic
= kGenericFont_NONE
;
2797 // XXXldb What if we would have had a string if we hadn't been doing
2798 // the optimization with a non-null aStartStruct?
2799 if (eCSSUnit_String
== fontData
.mFamily
.GetUnit()) {
2800 fontData
.mFamily
.GetStringValue(font
->mFont
.name
);
2801 // XXXldb Do we want to extract the generic for this if it's not only a
2803 nsFont::GetGenericID(font
->mFont
.name
, &generic
);
2805 // If we aren't allowed to use document fonts, then we are only entitled
2806 // to use the user's default variable-width font and fixed-width font
2807 if (!useDocumentFonts
) {
2808 // Extract the generic from the specified font family...
2809 nsAutoString genericName
;
2810 if (!font
->mFont
.EnumerateFamilies(ExtractGeneric
, &genericName
)) {
2811 // The specified font had a generic family.
2812 font
->mFont
.name
= genericName
;
2813 nsFont::GetGenericID(genericName
, &generic
);
2815 // ... and only use it if it's -moz-fixed or monospace
2816 if (generic
!= kGenericFont_moz_fixed
&&
2817 generic
!= kGenericFont_monospace
) {
2818 font
->mFont
.name
.Truncate();
2819 generic
= kGenericFont_NONE
;
2822 // The specified font did not have a generic family.
2823 font
->mFont
.name
.Truncate();
2824 generic
= kGenericFont_NONE
;
2829 // Now compute our font struct
2830 if (generic
== kGenericFont_NONE
) {
2831 // continue the normal processing
2832 nsRuleNode::SetFont(mPresContext
, aContext
, minimumFontSize
, generic
,
2833 fontData
, parentFont
, font
,
2834 aStartStruct
!= nsnull
, inherited
);
2837 // re-calculate the font as a generic font
2838 inherited
= PR_TRUE
;
2839 nsRuleNode::SetGenericFont(mPresContext
, aContext
, generic
,
2840 minimumFontSize
, font
);
2843 COMPUTE_END_INHERITED(Font
, font
)
2846 already_AddRefed
<nsCSSShadowArray
>
2847 nsRuleNode::GetShadowData(nsCSSValueList
* aList
,
2848 nsStyleContext
* aContext
,
2852 PRUint32 arrayLength
= 0;
2853 for (nsCSSValueList
*list2
= aList
; list2
; list2
= list2
->mNext
)
2856 NS_ASSERTION(arrayLength
> 0, "Non-null text-shadow list, yet we counted 0 items.");
2857 nsCSSShadowArray
* shadowList
= new(arrayLength
) nsCSSShadowArray(arrayLength
);
2862 nsStyleCoord tempCoord
;
2864 for (nsCSSShadowItem
* item
= shadowList
->ShadowAt(0);
2866 aList
= aList
->mNext
, ++item
) {
2867 nsCSSValue::Array
*arr
= aList
->mValue
.GetArrayValue();
2868 // OK to pass bad aParentCoord since we're not passing SETCOORD_INHERIT
2869 unitOK
= SetCoord(arr
->Item(0), tempCoord
, nsStyleCoord(),
2870 SETCOORD_LENGTH
, aContext
, mPresContext
, inherited
);
2871 NS_ASSERTION(unitOK
, "unexpected unit");
2872 item
->mXOffset
= tempCoord
.GetCoordValue();
2874 unitOK
= SetCoord(arr
->Item(1), tempCoord
, nsStyleCoord(),
2875 SETCOORD_LENGTH
, aContext
, mPresContext
, inherited
);
2876 NS_ASSERTION(unitOK
, "unexpected unit");
2877 item
->mYOffset
= tempCoord
.GetCoordValue();
2879 // Blur radius is optional in the current box-shadow spec
2880 if (arr
->Item(2).GetUnit() != eCSSUnit_Null
) {
2881 unitOK
= SetCoord(arr
->Item(2), tempCoord
, nsStyleCoord(),
2882 SETCOORD_LENGTH
, aContext
, mPresContext
, inherited
);
2883 NS_ASSERTION(unitOK
, "unexpected unit");
2884 item
->mRadius
= tempCoord
.GetCoordValue();
2889 // Find the spread radius
2890 if (aUsesSpread
&& arr
->Item(3).GetUnit() != eCSSUnit_Null
) {
2891 unitOK
= SetCoord(arr
->Item(3), tempCoord
, nsStyleCoord(),
2892 SETCOORD_LENGTH
, aContext
, mPresContext
, inherited
);
2893 NS_ASSERTION(unitOK
, "unexpected unit");
2894 item
->mSpread
= tempCoord
.GetCoordValue();
2899 if (arr
->Item(4).GetUnit() != eCSSUnit_Null
) {
2900 item
->mHasColor
= PR_TRUE
;
2901 // 2nd argument can be bogus since inherit is not a valid color
2902 unitOK
= SetColor(arr
->Item(4), 0, mPresContext
, aContext
, item
->mColor
,
2904 NS_ASSERTION(unitOK
, "unexpected unit");
2908 NS_ADDREF(shadowList
);
2913 nsRuleNode::ComputeTextData(void* aStartStruct
,
2914 const nsRuleDataStruct
& aData
,
2915 nsStyleContext
* aContext
,
2916 nsRuleNode
* aHighestNode
,
2917 const RuleDetail aRuleDetail
, PRBool aInherited
)
2919 COMPUTE_START_INHERITED(Text
, (), text
, parentText
, Text
, textData
)
2921 // letter-spacing: normal, length, inherit
2922 SetCoord(textData
.mLetterSpacing
, text
->mLetterSpacing
, parentText
->mLetterSpacing
,
2923 SETCOORD_LH
| SETCOORD_NORMAL
| SETCOORD_INITIAL_NORMAL
,
2924 aContext
, mPresContext
, inherited
);
2926 // text-shadow: none, list, inherit, initial
2927 nsCSSValueList
* list
= textData
.mTextShadow
;
2929 text
->mTextShadow
= nsnull
;
2931 // Don't need to handle none/initial explicitly: The above assignment
2932 // takes care of that
2933 if (eCSSUnit_Inherit
== list
->mValue
.GetUnit()) {
2934 inherited
= PR_TRUE
;
2935 text
->mTextShadow
= parentText
->mTextShadow
;
2936 } else if (eCSSUnit_Array
== list
->mValue
.GetUnit()) {
2938 text
->mTextShadow
= GetShadowData(list
, aContext
, PR_FALSE
, inherited
);
2942 // line-height: normal, number, length, percent, inherit
2943 if (eCSSUnit_Percent
== textData
.mLineHeight
.GetUnit()) {
2944 inherited
= PR_TRUE
;
2945 // Use |mFont.size| to pick up minimum font size.
2946 text
->mLineHeight
.SetCoordValue(
2947 nscoord(float(aContext
->GetStyleFont()->mFont
.size
) *
2948 textData
.mLineHeight
.GetPercentValue()));
2950 else if (eCSSUnit_Initial
== textData
.mLineHeight
.GetUnit() ||
2951 eCSSUnit_System_Font
== textData
.mLineHeight
.GetUnit()) {
2952 text
->mLineHeight
.SetNormalValue();
2955 SetCoord(textData
.mLineHeight
, text
->mLineHeight
, parentText
->mLineHeight
,
2956 SETCOORD_LH
| SETCOORD_FACTOR
| SETCOORD_NORMAL
,
2957 aContext
, mPresContext
, inherited
);
2958 if (textData
.mLineHeight
.IsFixedLengthUnit() ||
2959 textData
.mLineHeight
.GetUnit() == eCSSUnit_Pixel
) {
2960 nscoord lh
= nsStyleFont::ZoomText(mPresContext
,
2961 text
->mLineHeight
.GetCoordValue());
2962 nscoord minimumFontSize
=
2963 mPresContext
->GetCachedIntPref(kPresContext_MinimumFontSize
);
2965 if (minimumFontSize
> 0 && !mPresContext
->IsChrome()) {
2966 // If we applied a minimum font size, scale the line height by
2967 // the same ratio. (If we *might* have applied a minimum font
2968 // size, we can't cache in the rule tree.)
2969 inherited
= PR_TRUE
;
2970 const nsStyleFont
*font
= aContext
->GetStyleFont();
2971 if (font
->mSize
!= 0) {
2972 lh
= nscoord(float(lh
) * float(font
->mFont
.size
) / float(font
->mSize
));
2974 lh
= minimumFontSize
;
2977 text
->mLineHeight
.SetCoordValue(lh
);
2982 // text-align: enum, string, inherit, initial
2983 if (eCSSUnit_String
== textData
.mTextAlign
.GetUnit()) {
2984 NS_NOTYETIMPLEMENTED("align string");
2986 SetDiscrete(textData
.mTextAlign
, text
->mTextAlign
, inherited
,
2987 SETDSC_ENUMERATED
, parentText
->mTextAlign
,
2988 NS_STYLE_TEXT_ALIGN_DEFAULT
,
2991 // text-indent: length, percent, inherit, initial
2992 SetCoord(textData
.mTextIndent
, text
->mTextIndent
, parentText
->mTextIndent
,
2993 SETCOORD_LPH
| SETCOORD_INITIAL_ZERO
, aContext
,
2994 mPresContext
, inherited
);
2996 // text-transform: enum, none, inherit, initial
2997 SetDiscrete(textData
.mTextTransform
, text
->mTextTransform
, inherited
,
2998 SETDSC_ENUMERATED
| SETDSC_NONE
, parentText
->mTextTransform
,
2999 NS_STYLE_TEXT_TRANSFORM_NONE
, 0,
3000 NS_STYLE_TEXT_TRANSFORM_NONE
, 0, 0);
3002 // white-space: enum, normal, inherit, initial
3003 SetDiscrete(textData
.mWhiteSpace
, text
->mWhiteSpace
, inherited
,
3004 SETDSC_ENUMERATED
| SETDSC_NORMAL
, parentText
->mWhiteSpace
,
3005 NS_STYLE_WHITESPACE_NORMAL
, 0, 0,
3006 NS_STYLE_WHITESPACE_NORMAL
, 0);
3008 // word-spacing: normal, length, inherit
3009 SetCoord(textData
.mWordSpacing
, text
->mWordSpacing
, parentText
->mWordSpacing
,
3010 SETCOORD_LH
| SETCOORD_NORMAL
| SETCOORD_INITIAL_NORMAL
,
3011 aContext
, mPresContext
, inherited
);
3013 // word-wrap: enum, normal, inherit, initial
3014 SetDiscrete(textData
.mWordWrap
, text
->mWordWrap
, inherited
,
3015 SETDSC_ENUMERATED
| SETDSC_NORMAL
, parentText
->mWordWrap
,
3016 NS_STYLE_WORDWRAP_NORMAL
, 0, 0,
3017 NS_STYLE_WORDWRAP_NORMAL
, 0);
3019 COMPUTE_END_INHERITED(Text
, text
)
3023 nsRuleNode::ComputeTextResetData(void* aStartStruct
,
3024 const nsRuleDataStruct
& aData
,
3025 nsStyleContext
* aContext
,
3026 nsRuleNode
* aHighestNode
,
3027 const RuleDetail aRuleDetail
, PRBool aInherited
)
3029 COMPUTE_START_RESET(TextReset
, (), text
, parentText
, Text
, textData
)
3031 // vertical-align: enum, length, percent, inherit
3032 if (!SetCoord(textData
.mVerticalAlign
, text
->mVerticalAlign
,
3033 parentText
->mVerticalAlign
, SETCOORD_LPH
| SETCOORD_ENUMERATED
,
3034 aContext
, mPresContext
, inherited
)) {
3035 if (eCSSUnit_Initial
== textData
.mVerticalAlign
.GetUnit()) {
3036 text
->mVerticalAlign
.SetIntValue(NS_STYLE_VERTICAL_ALIGN_BASELINE
,
3037 eStyleUnit_Enumerated
);
3041 // text-decoration: none, enum (bit field), inherit, initial
3042 if (eCSSUnit_Enumerated
== textData
.mDecoration
.GetUnit()) {
3043 PRInt32 td
= textData
.mDecoration
.GetIntValue();
3044 text
->mTextDecoration
= td
;
3045 if (td
& NS_STYLE_TEXT_DECORATION_PREF_ANCHORS
) {
3046 PRBool underlineLinks
=
3047 mPresContext
->GetCachedBoolPref(kPresContext_UnderlineLinks
);
3048 if (underlineLinks
) {
3049 text
->mTextDecoration
|= NS_STYLE_TEXT_DECORATION_UNDERLINE
;
3052 text
->mTextDecoration
&= ~NS_STYLE_TEXT_DECORATION_UNDERLINE
;
3057 SetDiscrete(textData
.mDecoration
, text
->mTextDecoration
, inherited
,
3059 parentText
->mTextDecoration
,
3060 NS_STYLE_TEXT_DECORATION_NONE
, 0,
3061 NS_STYLE_TEXT_DECORATION_NONE
, 0, 0);
3063 // unicode-bidi: enum, normal, inherit, initial
3064 SetDiscrete(textData
.mUnicodeBidi
, text
->mUnicodeBidi
, inherited
,
3065 SETDSC_ENUMERATED
| SETDSC_NORMAL
,
3066 parentText
->mUnicodeBidi
,
3067 NS_STYLE_UNICODE_BIDI_NORMAL
, 0, 0,
3068 NS_STYLE_UNICODE_BIDI_NORMAL
, 0);
3070 COMPUTE_END_RESET(TextReset
, text
)
3074 nsRuleNode::ComputeUserInterfaceData(void* aStartStruct
,
3075 const nsRuleDataStruct
& aData
,
3076 nsStyleContext
* aContext
,
3077 nsRuleNode
* aHighestNode
,
3078 const RuleDetail aRuleDetail
,
3081 COMPUTE_START_INHERITED(UserInterface
, (), ui
, parentUI
,
3082 UserInterface
, uiData
)
3084 // cursor: enum, auto, url, inherit
3085 nsCSSValueList
* list
= uiData
.mCursor
;
3086 if (nsnull
!= list
) {
3087 delete [] ui
->mCursorArray
;
3088 ui
->mCursorArray
= nsnull
;
3089 ui
->mCursorArrayLength
= 0;
3091 if (eCSSUnit_Inherit
== list
->mValue
.GetUnit()) {
3092 inherited
= PR_TRUE
;
3093 ui
->mCursor
= parentUI
->mCursor
;
3094 ui
->CopyCursorArrayFrom(*parentUI
);
3096 else if (eCSSUnit_Initial
== list
->mValue
.GetUnit()) {
3097 ui
->mCursor
= NS_STYLE_CURSOR_AUTO
;
3100 // The parser will never create a list that is *all* URL values --
3102 PRUint32 arrayLength
= 0;
3103 nsCSSValueList
* list2
= list
;
3104 for ( ; list
->mValue
.GetUnit() == eCSSUnit_Array
; list
= list
->mNext
)
3105 if (list
->mValue
.GetArrayValue()->Item(0).GetImageValue())
3108 if (arrayLength
!= 0) {
3109 ui
->mCursorArray
= new nsCursorImage
[arrayLength
];
3110 if (ui
->mCursorArray
) {
3111 ui
->mCursorArrayLength
= arrayLength
;
3113 for (nsCursorImage
*item
= ui
->mCursorArray
;
3114 list2
->mValue
.GetUnit() == eCSSUnit_Array
;
3115 list2
= list2
->mNext
) {
3116 nsCSSValue::Array
*arr
= list2
->mValue
.GetArrayValue();
3117 imgIRequest
*req
= arr
->Item(0).GetImageValue();
3120 if (arr
->Item(1).GetUnit() != eCSSUnit_Null
) {
3121 item
->mHaveHotspot
= PR_TRUE
;
3122 item
->mHotspotX
= arr
->Item(1).GetFloatValue(),
3123 item
->mHotspotY
= arr
->Item(2).GetFloatValue();
3131 NS_ASSERTION(list
, "Must have non-array value at the end");
3132 NS_ASSERTION(list
->mValue
.GetUnit() == eCSSUnit_Enumerated
||
3133 list
->mValue
.GetUnit() == eCSSUnit_Auto
,
3134 "Unexpected fallback value at end of cursor list");
3136 if (eCSSUnit_Enumerated
== list
->mValue
.GetUnit()) {
3137 ui
->mCursor
= list
->mValue
.GetIntValue();
3139 else if (eCSSUnit_Auto
== list
->mValue
.GetUnit()) {
3140 ui
->mCursor
= NS_STYLE_CURSOR_AUTO
;
3145 // user-input: auto, none, enum, inherit, initial
3146 SetDiscrete(uiData
.mUserInput
, ui
->mUserInput
, inherited
,
3147 SETDSC_ENUMERATED
| SETDSC_NONE
| SETDSC_AUTO
,
3148 parentUI
->mUserInput
,
3149 NS_STYLE_USER_INPUT_AUTO
,
3150 NS_STYLE_USER_INPUT_AUTO
,
3151 NS_STYLE_USER_INPUT_NONE
,
3154 // user-modify: enum, inherit, initial
3155 SetDiscrete(uiData
.mUserModify
, ui
->mUserModify
, inherited
,
3157 parentUI
->mUserModify
,
3158 NS_STYLE_USER_MODIFY_READ_ONLY
,
3161 // user-focus: none, normal, enum, inherit, initial
3162 SetDiscrete(uiData
.mUserFocus
, ui
->mUserFocus
, inherited
,
3163 SETDSC_ENUMERATED
| SETDSC_NONE
| SETDSC_NORMAL
,
3164 parentUI
->mUserFocus
,
3165 NS_STYLE_USER_FOCUS_NONE
,
3167 NS_STYLE_USER_FOCUS_NONE
,
3168 NS_STYLE_USER_FOCUS_NORMAL
,
3171 COMPUTE_END_INHERITED(UserInterface
, ui
)
3175 nsRuleNode::ComputeUIResetData(void* aStartStruct
,
3176 const nsRuleDataStruct
& aData
,
3177 nsStyleContext
* aContext
,
3178 nsRuleNode
* aHighestNode
,
3179 const RuleDetail aRuleDetail
, PRBool aInherited
)
3181 COMPUTE_START_RESET(UIReset
, (), ui
, parentUI
, UserInterface
, uiData
)
3183 // user-select: auto, none, enum, inherit, initial
3184 SetDiscrete(uiData
.mUserSelect
, ui
->mUserSelect
, inherited
,
3185 SETDSC_ENUMERATED
| SETDSC_NONE
| SETDSC_AUTO
,
3186 parentUI
->mUserSelect
,
3187 NS_STYLE_USER_SELECT_AUTO
,
3188 NS_STYLE_USER_SELECT_AUTO
,
3189 NS_STYLE_USER_SELECT_NONE
,
3192 // ime-mode: auto, normal, enum, inherit, initial
3193 SetDiscrete(uiData
.mIMEMode
, ui
->mIMEMode
, inherited
,
3194 SETDSC_ENUMERATED
| SETDSC_NORMAL
| SETDSC_AUTO
,
3196 NS_STYLE_IME_MODE_AUTO
,
3197 NS_STYLE_IME_MODE_AUTO
,
3199 NS_STYLE_IME_MODE_NORMAL
,
3202 // force-broken-image-icons: integer, inherit, initial
3203 SetDiscrete(uiData
.mForceBrokenImageIcon
, ui
->mForceBrokenImageIcon
,
3206 parentUI
->mForceBrokenImageIcon
,
3209 // -moz-window-shadow: enum, none, inherit, initial
3210 SetDiscrete(uiData
.mWindowShadow
, ui
->mWindowShadow
, inherited
,
3211 SETDSC_ENUMERATED
| SETDSC_NONE
, parentUI
->mWindowShadow
,
3212 NS_STYLE_WINDOW_SHADOW_DEFAULT
, 0,
3213 NS_STYLE_WINDOW_SHADOW_NONE
, 0, 0);
3215 COMPUTE_END_RESET(UIReset
, ui
)
3218 /* Given a -moz-transform token stream, accumulates them into an
3219 * nsStyleTransformMatrix
3221 * @param aList The nsCSSValueList of arrays to read into transform functions.
3222 * @param aContext The style context to use for unit conversion.
3223 * @param aPresContext The presentation context to use for unit conversion
3224 * @param aInherited If the value is inherited, this is set to PR_TRUE.
3225 * @return An nsStyleTransformMatrix corresponding to the net transform.
3227 static nsStyleTransformMatrix
ReadTransforms(const nsCSSValueList
* aList
,
3228 nsStyleContext
* aContext
,
3229 nsPresContext
* aPresContext
,
3232 nsStyleTransformMatrix result
;
3234 for (const nsCSSValueList
* curr
= aList
; curr
!= nsnull
; curr
= curr
->mNext
) {
3235 const nsCSSValue
&currElem
= curr
->mValue
;
3236 NS_ASSERTION(currElem
.GetUnit() == eCSSUnit_Function
,
3237 "Stream should consist solely of functions!");
3238 NS_ASSERTION(currElem
.GetArrayValue()->Count() >= 1,
3239 "Incoming function is too short!");
3241 /* Read in a single transform matrix, then accumulate it with the total. */
3242 nsStyleTransformMatrix currMatrix
;
3243 currMatrix
.SetToTransformFunction(currElem
.GetArrayValue(), aContext
,
3244 aPresContext
, aInherited
);
3245 result
*= currMatrix
;
3251 nsRuleNode::ComputeDisplayData(void* aStartStruct
,
3252 const nsRuleDataStruct
& aData
,
3253 nsStyleContext
* aContext
,
3254 nsRuleNode
* aHighestNode
,
3255 const RuleDetail aRuleDetail
, PRBool aInherited
)
3257 COMPUTE_START_RESET(Display
, (), display
, parentDisplay
,
3258 Display
, displayData
)
3260 // opacity: factor, inherit, initial
3261 SetFactor(displayData
.mOpacity
, display
->mOpacity
, inherited
,
3262 parentDisplay
->mOpacity
, 1.0f
, SETFCT_OPACITY
);
3264 // display: enum, none, inherit, initial
3265 SetDiscrete(displayData
.mDisplay
, display
->mDisplay
, inherited
,
3266 SETDSC_ENUMERATED
| SETDSC_NONE
, parentDisplay
->mDisplay
,
3267 NS_STYLE_DISPLAY_INLINE
, 0,
3268 NS_STYLE_DISPLAY_NONE
, 0, 0);
3270 // appearance: enum, none, inherit, initial
3271 SetDiscrete(displayData
.mAppearance
, display
->mAppearance
, inherited
,
3272 SETDSC_ENUMERATED
| SETDSC_NONE
, parentDisplay
->mAppearance
,
3274 NS_THEME_NONE
, 0, 0);
3276 // binding: url, none, inherit
3277 if (eCSSUnit_URL
== displayData
.mBinding
.GetUnit()) {
3278 nsCSSValue::URL
* url
= displayData
.mBinding
.GetURLStructValue();
3279 NS_ASSERTION(url
, "What's going on here?");
3281 if (NS_LIKELY(url
->mURI
)) {
3282 display
->mBinding
= url
;
3284 display
->mBinding
= nsnull
;
3287 else if (eCSSUnit_None
== displayData
.mBinding
.GetUnit() ||
3288 eCSSUnit_Initial
== displayData
.mBinding
.GetUnit()) {
3289 display
->mBinding
= nsnull
;
3291 else if (eCSSUnit_Inherit
== displayData
.mBinding
.GetUnit()) {
3292 inherited
= PR_TRUE
;
3293 display
->mBinding
= parentDisplay
->mBinding
;
3296 // position: enum, inherit, initial
3297 SetDiscrete(displayData
.mPosition
, display
->mPosition
, inherited
,
3298 SETDSC_ENUMERATED
, parentDisplay
->mPosition
,
3299 NS_STYLE_POSITION_STATIC
, 0, 0, 0, 0);
3301 // clear: enum, none, inherit, initial
3302 SetDiscrete(displayData
.mClear
, display
->mBreakType
, inherited
,
3303 SETDSC_ENUMERATED
| SETDSC_NONE
, parentDisplay
->mBreakType
,
3304 NS_STYLE_CLEAR_NONE
, 0,
3305 NS_STYLE_CLEAR_NONE
, 0, 0);
3307 // temp fix for bug 24000
3308 // Map 'auto' and 'avoid' to PR_FALSE, and 'always', 'left', and
3309 // 'right' to PR_TRUE.
3310 // "A conforming user agent may interpret the values 'left' and
3311 // 'right' as 'always'." - CSS2.1, section 13.3.1
3312 if (eCSSUnit_Enumerated
== displayData
.mBreakBefore
.GetUnit()) {
3313 display
->mBreakBefore
= (NS_STYLE_PAGE_BREAK_AVOID
!= displayData
.mBreakBefore
.GetIntValue());
3315 else if (eCSSUnit_Auto
== displayData
.mBreakBefore
.GetUnit() ||
3316 eCSSUnit_Initial
== displayData
.mBreakBefore
.GetUnit()) {
3317 display
->mBreakBefore
= PR_FALSE
;
3319 else if (eCSSUnit_Inherit
== displayData
.mBreakBefore
.GetUnit()) {
3320 inherited
= PR_TRUE
;
3321 display
->mBreakBefore
= parentDisplay
->mBreakBefore
;
3324 if (eCSSUnit_Enumerated
== displayData
.mBreakAfter
.GetUnit()) {
3325 display
->mBreakAfter
= (NS_STYLE_PAGE_BREAK_AVOID
!= displayData
.mBreakAfter
.GetIntValue());
3327 else if (eCSSUnit_Auto
== displayData
.mBreakAfter
.GetUnit() ||
3328 eCSSUnit_Initial
== displayData
.mBreakAfter
.GetUnit()) {
3329 display
->mBreakAfter
= PR_FALSE
;
3331 else if (eCSSUnit_Inherit
== displayData
.mBreakAfter
.GetUnit()) {
3332 inherited
= PR_TRUE
;
3333 display
->mBreakAfter
= parentDisplay
->mBreakAfter
;
3337 // float: enum, none, inherit, initial
3338 SetDiscrete(displayData
.mFloat
, display
->mFloats
, inherited
,
3339 SETDSC_ENUMERATED
| SETDSC_NONE
, parentDisplay
->mFloats
,
3340 NS_STYLE_FLOAT_NONE
, 0,
3341 NS_STYLE_FLOAT_NONE
, 0, 0);
3343 // overflow-x: enum, auto, inherit, initial
3344 SetDiscrete(displayData
.mOverflowX
, display
->mOverflowX
, inherited
,
3345 SETDSC_ENUMERATED
| SETDSC_AUTO
,
3346 parentDisplay
->mOverflowX
,
3347 NS_STYLE_OVERFLOW_VISIBLE
,
3348 NS_STYLE_OVERFLOW_AUTO
,
3351 // overflow-y: enum, auto, inherit, initial
3352 SetDiscrete(displayData
.mOverflowY
, display
->mOverflowY
, inherited
,
3353 SETDSC_ENUMERATED
| SETDSC_AUTO
,
3354 parentDisplay
->mOverflowY
,
3355 NS_STYLE_OVERFLOW_VISIBLE
,
3356 NS_STYLE_OVERFLOW_AUTO
,
3359 // CSS3 overflow-x and overflow-y require some fixup as well in some
3360 // cases. NS_STYLE_OVERFLOW_VISIBLE and NS_STYLE_OVERFLOW_CLIP are
3361 // meaningful only when used in both dimensions.
3362 if (display
->mOverflowX
!= display
->mOverflowY
&&
3363 (display
->mOverflowX
== NS_STYLE_OVERFLOW_VISIBLE
||
3364 display
->mOverflowX
== NS_STYLE_OVERFLOW_CLIP
||
3365 display
->mOverflowY
== NS_STYLE_OVERFLOW_VISIBLE
||
3366 display
->mOverflowY
== NS_STYLE_OVERFLOW_CLIP
)) {
3367 // We can't store in the rule tree since a more specific rule might
3368 // change these conditions.
3369 inherited
= PR_TRUE
;
3371 // NS_STYLE_OVERFLOW_CLIP is a deprecated value, so if it's specified
3372 // in only one dimension, convert it to NS_STYLE_OVERFLOW_HIDDEN.
3373 if (display
->mOverflowX
== NS_STYLE_OVERFLOW_CLIP
)
3374 display
->mOverflowX
= NS_STYLE_OVERFLOW_HIDDEN
;
3375 if (display
->mOverflowY
== NS_STYLE_OVERFLOW_CLIP
)
3376 display
->mOverflowY
= NS_STYLE_OVERFLOW_HIDDEN
;
3378 // If 'visible' is specified but doesn't match the other dimension, it
3379 // turns into 'auto'.
3380 if (display
->mOverflowX
== NS_STYLE_OVERFLOW_VISIBLE
)
3381 display
->mOverflowX
= NS_STYLE_OVERFLOW_AUTO
;
3382 if (display
->mOverflowY
== NS_STYLE_OVERFLOW_VISIBLE
)
3383 display
->mOverflowY
= NS_STYLE_OVERFLOW_AUTO
;
3386 // clip property: length, auto, inherit
3387 if (eCSSUnit_Inherit
== displayData
.mClip
.mTop
.GetUnit()) { // if one is inherit, they all are
3388 inherited
= PR_TRUE
;
3389 display
->mClipFlags
= parentDisplay
->mClipFlags
;
3390 display
->mClip
= parentDisplay
->mClip
;
3392 // if one is initial, they all are
3393 else if (eCSSUnit_Initial
== displayData
.mClip
.mTop
.GetUnit()) {
3394 display
->mClipFlags
= NS_STYLE_CLIP_AUTO
;
3395 display
->mClip
.SetRect(0,0,0,0);
3398 PRBool fullAuto
= PR_TRUE
;
3400 display
->mClipFlags
= 0; // clear it
3402 if (eCSSUnit_Auto
== displayData
.mClip
.mTop
.GetUnit()) {
3403 display
->mClip
.y
= 0;
3404 display
->mClipFlags
|= NS_STYLE_CLIP_TOP_AUTO
;
3406 else if (displayData
.mClip
.mTop
.IsLengthUnit()) {
3407 display
->mClip
.y
= CalcLength(displayData
.mClip
.mTop
, aContext
, mPresContext
, inherited
);
3408 fullAuto
= PR_FALSE
;
3410 if (eCSSUnit_Auto
== displayData
.mClip
.mBottom
.GetUnit()) {
3411 // Setting to NS_MAXSIZE for the 'auto' case ensures that
3412 // the clip rect is nonempty. It is important that mClip be
3413 // nonempty if the actual clip rect could be nonempty.
3414 display
->mClip
.height
= NS_MAXSIZE
;
3415 display
->mClipFlags
|= NS_STYLE_CLIP_BOTTOM_AUTO
;
3417 else if (displayData
.mClip
.mBottom
.IsLengthUnit()) {
3418 display
->mClip
.height
= CalcLength(displayData
.mClip
.mBottom
, aContext
, mPresContext
, inherited
) -
3420 fullAuto
= PR_FALSE
;
3422 if (eCSSUnit_Auto
== displayData
.mClip
.mLeft
.GetUnit()) {
3423 display
->mClip
.x
= 0;
3424 display
->mClipFlags
|= NS_STYLE_CLIP_LEFT_AUTO
;
3426 else if (displayData
.mClip
.mLeft
.IsLengthUnit()) {
3427 display
->mClip
.x
= CalcLength(displayData
.mClip
.mLeft
, aContext
, mPresContext
, inherited
);
3428 fullAuto
= PR_FALSE
;
3430 if (eCSSUnit_Auto
== displayData
.mClip
.mRight
.GetUnit()) {
3431 // Setting to NS_MAXSIZE for the 'auto' case ensures that
3432 // the clip rect is nonempty. It is important that mClip be
3433 // nonempty if the actual clip rect could be nonempty.
3434 display
->mClip
.width
= NS_MAXSIZE
;
3435 display
->mClipFlags
|= NS_STYLE_CLIP_RIGHT_AUTO
;
3437 else if (displayData
.mClip
.mRight
.IsLengthUnit()) {
3438 display
->mClip
.width
= CalcLength(displayData
.mClip
.mRight
, aContext
, mPresContext
, inherited
) -
3440 fullAuto
= PR_FALSE
;
3442 display
->mClipFlags
&= ~NS_STYLE_CLIP_TYPE_MASK
;
3444 display
->mClipFlags
|= NS_STYLE_CLIP_AUTO
;
3447 display
->mClipFlags
|= NS_STYLE_CLIP_RECT
;
3451 if (display
->mDisplay
!= NS_STYLE_DISPLAY_NONE
) {
3452 // CSS2 9.7 specifies display type corrections dealing with 'float'
3453 // and 'position'. Since generated content can't be floated or
3454 // positioned, we can deal with it here.
3456 if (nsCSSPseudoElements::firstLetter
== aContext
->GetPseudoType()) {
3457 // a non-floating first-letter must be inline
3458 // XXX this fix can go away once bug 103189 is fixed correctly
3459 display
->mDisplay
= NS_STYLE_DISPLAY_INLINE
;
3461 // We can't cache the data in the rule tree since if a more specific
3462 // rule has 'float: left' we'll end up with the wrong 'display'
3464 inherited
= PR_TRUE
;
3467 if (display
->IsAbsolutelyPositioned()) {
3468 // 1) if position is 'absolute' or 'fixed' then display must be
3469 // block-level and float must be 'none'
3471 // Backup original display value for calculation of a hypothetical
3472 // box (CSS2 10.6.4/10.6.5).
3473 // See nsHTMLReflowState::CalculateHypotheticalBox
3474 display
->mOriginalDisplay
= display
->mDisplay
;
3475 EnsureBlockDisplay(display
->mDisplay
);
3476 display
->mFloats
= NS_STYLE_FLOAT_NONE
;
3478 // We can't cache the data in the rule tree since if a more specific
3479 // rule has 'position: static' we'll end up with problems with the
3480 // 'display' and 'float' properties.
3481 inherited
= PR_TRUE
;
3482 } else if (display
->mFloats
!= NS_STYLE_FLOAT_NONE
) {
3483 // 2) if float is not none, and display is not none, then we must
3484 // set a block-level 'display' type per CSS2.1 section 9.7.
3486 EnsureBlockDisplay(display
->mDisplay
);
3488 // We can't cache the data in the rule tree since if a more specific
3489 // rule has 'float: none' we'll end up with the wrong 'display'
3491 inherited
= PR_TRUE
;
3496 /* Convert the nsCSSValueList into an nsTArray<nsTransformFunction *>. */
3497 const nsCSSValueList
*head
= displayData
.mTransform
;
3499 if (head
!= nsnull
) {
3500 /* There is a chance that we will discover that
3501 * the transform property has been set to 'none,' 'initial,' or 'inherit.'
3502 * If so, process appropriately.
3505 /* If it's 'none,' indicate that there are no transforms. */
3506 if (head
->mValue
.GetUnit() == eCSSUnit_None
)
3507 display
->mTransformPresent
= PR_FALSE
;
3509 /* If we need to inherit, do so by making a full deep-copy. */
3510 else if (head
->mValue
.GetUnit() == eCSSUnit_Inherit
) {
3511 display
->mTransformPresent
= parentDisplay
->mTransformPresent
;
3512 if (parentDisplay
->mTransformPresent
)
3513 display
->mTransform
= parentDisplay
->mTransform
;
3514 inherited
= PR_TRUE
;
3516 /* If it's 'initial', then we reset to empty. */
3517 else if (head
->mValue
.GetUnit() == eCSSUnit_Initial
)
3518 display
->mTransformPresent
= PR_FALSE
;
3520 /* Otherwise, we are looking at a list of CSS tokens. We'll read each of
3521 * them in as an array of nsTransformFunction objects, then will accumulate
3522 * them all together to form the final transform matrix.
3526 display
->mTransform
=
3527 ReadTransforms(head
, aContext
, mPresContext
, inherited
);
3529 /* Make sure to say that this data is valid! */
3530 display
->mTransformPresent
= PR_TRUE
;
3534 /* Convert -moz-transform-origin. */
3535 if (displayData
.mTransformOrigin
.mXValue
.GetUnit() != eCSSUnit_Null
||
3536 displayData
.mTransformOrigin
.mXValue
.GetUnit() != eCSSUnit_Null
) {
3538 /* If X coordinate is an enumerated type, handle it explicitly. */
3539 if (eCSSUnit_Enumerated
== displayData
.mTransformOrigin
.mXValue
.GetUnit())
3540 display
->mTransformOrigin
[0].SetPercentValue
3541 (GetFloatFromBoxPosition
3542 (displayData
.mTransformOrigin
.mXValue
.GetIntValue()));
3544 /* Convert lengths, percents, and inherit. Default value is 50%. */
3548 SetCoord(displayData
.mTransformOrigin
.mXValue
,
3549 display
->mTransformOrigin
[0],
3550 parentDisplay
->mTransformOrigin
[0],
3551 SETCOORD_LPH
| SETCOORD_INITIAL_HALF
,
3552 aContext
, mPresContext
, aInherited
);
3553 NS_ASSERTION(result
, "Malformed -moz-transform-origin parse!");
3556 /* If Y coordinate is an enumerated type, handle it explicitly. */
3557 if (eCSSUnit_Enumerated
== displayData
.mTransformOrigin
.mYValue
.GetUnit())
3558 display
->mTransformOrigin
[1].SetPercentValue
3559 (GetFloatFromBoxPosition
3560 (displayData
.mTransformOrigin
.mYValue
.GetIntValue()));
3562 /* Convert lengths, percents, initial, inherit. */
3566 SetCoord(displayData
.mTransformOrigin
.mYValue
,
3567 display
->mTransformOrigin
[1],
3568 parentDisplay
->mTransformOrigin
[1],
3569 SETCOORD_LPH
| SETCOORD_INITIAL_HALF
,
3570 aContext
, mPresContext
, aInherited
);
3571 NS_ASSERTION(result
, "Malformed -moz-transform-origin parse!");
3575 COMPUTE_END_RESET(Display
, display
)
3579 nsRuleNode::ComputeVisibilityData(void* aStartStruct
,
3580 const nsRuleDataStruct
& aData
,
3581 nsStyleContext
* aContext
,
3582 nsRuleNode
* aHighestNode
,
3583 const RuleDetail aRuleDetail
, PRBool aInherited
)
3585 COMPUTE_START_INHERITED(Visibility
, (mPresContext
),
3586 visibility
, parentVisibility
,
3587 Display
, displayData
)
3589 // direction: enum, inherit, initial
3590 SetDiscrete(displayData
.mDirection
, visibility
->mDirection
, inherited
,
3591 SETDSC_ENUMERATED
, parentVisibility
->mDirection
,
3592 (GET_BIDI_OPTION_DIRECTION(mPresContext
->GetBidi())
3593 == IBMBIDI_TEXTDIRECTION_RTL
)
3594 ? NS_STYLE_DIRECTION_RTL
: NS_STYLE_DIRECTION_LTR
,
3597 // visibility: enum, inherit, initial
3598 SetDiscrete(displayData
.mVisibility
, visibility
->mVisible
, inherited
,
3599 SETDSC_ENUMERATED
, parentVisibility
->mVisible
,
3600 NS_STYLE_VISIBILITY_VISIBLE
, 0, 0, 0, 0);
3602 // lang: string, inherit
3603 // this is not a real CSS property, it is a html attribute mapped to CSS struture
3604 if (eCSSUnit_String
== displayData
.mLang
.GetUnit()) {
3605 if (!gLangService
) {
3606 CallGetService(NS_LANGUAGEATOMSERVICE_CONTRACTID
, &gLangService
);
3611 displayData
.mLang
.GetStringValue(lang
);
3612 visibility
->mLangGroup
= gLangService
->LookupLanguage(lang
);
3616 COMPUTE_END_INHERITED(Visibility
, visibility
)
3620 nsRuleNode::ComputeColorData(void* aStartStruct
,
3621 const nsRuleDataStruct
& aData
,
3622 nsStyleContext
* aContext
,
3623 nsRuleNode
* aHighestNode
,
3624 const RuleDetail aRuleDetail
, PRBool aInherited
)
3626 COMPUTE_START_INHERITED(Color
, (mPresContext
), color
, parentColor
,
3629 // color: color, string, inherit
3630 // Special case for currentColor. According to CSS3, setting color to 'currentColor'
3631 // should behave as if it is inherited
3632 if (colorData
.mColor
.GetUnit() == eCSSUnit_EnumColor
&&
3633 colorData
.mColor
.GetIntValue() == NS_COLOR_CURRENTCOLOR
) {
3634 color
->mColor
= parentColor
->mColor
;
3635 inherited
= PR_TRUE
;
3637 else if (colorData
.mColor
.GetUnit() == eCSSUnit_Initial
) {
3638 color
->mColor
= mPresContext
->DefaultColor();
3641 SetColor(colorData
.mColor
, parentColor
->mColor
, mPresContext
, aContext
, color
->mColor
,
3645 COMPUTE_END_INHERITED(Color
, color
)
3649 nsRuleNode::ComputeBackgroundData(void* aStartStruct
,
3650 const nsRuleDataStruct
& aData
,
3651 nsStyleContext
* aContext
,
3652 nsRuleNode
* aHighestNode
,
3653 const RuleDetail aRuleDetail
,
3656 COMPUTE_START_RESET(Background
, (), bg
, parentBG
, Color
, colorData
)
3658 // save parentFlags in case bg == parentBG and we clobber them later
3659 PRUint8 parentFlags
= parentBG
->mBackgroundFlags
;
3661 // background-color: color, string, inherit
3662 if (eCSSUnit_Initial
== colorData
.mBackColor
.GetUnit()) {
3663 bg
->mBackgroundColor
= NS_RGBA(0, 0, 0, 0);
3664 } else if (!SetColor(colorData
.mBackColor
, parentBG
->mBackgroundColor
,
3665 mPresContext
, aContext
, bg
->mBackgroundColor
,
3667 NS_ASSERTION(eCSSUnit_Null
== colorData
.mBackColor
.GetUnit(),
3668 "unexpected color unit");
3671 // background-image: url (stored as image), none, inherit
3672 if (eCSSUnit_Image
== colorData
.mBackImage
.GetUnit()) {
3673 bg
->mBackgroundImage
= colorData
.mBackImage
.GetImageValue();
3675 else if (eCSSUnit_None
== colorData
.mBackImage
.GetUnit() ||
3676 eCSSUnit_Initial
== colorData
.mBackImage
.GetUnit()) {
3677 bg
->mBackgroundImage
= nsnull
;
3679 else if (eCSSUnit_Inherit
== colorData
.mBackImage
.GetUnit()) {
3680 inherited
= PR_TRUE
;
3681 bg
->mBackgroundImage
= parentBG
->mBackgroundImage
;
3684 if (bg
->mBackgroundImage
) {
3685 bg
->mBackgroundFlags
&= ~NS_STYLE_BG_IMAGE_NONE
;
3687 bg
->mBackgroundFlags
|= NS_STYLE_BG_IMAGE_NONE
;
3690 // background-repeat: enum, inherit, initial
3691 SetDiscrete(colorData
.mBackRepeat
, bg
->mBackgroundRepeat
, inherited
,
3692 SETDSC_ENUMERATED
, parentBG
->mBackgroundRepeat
,
3693 NS_STYLE_BG_REPEAT_XY
, 0, 0, 0, 0);
3695 // background-attachment: enum, inherit, initial
3696 SetDiscrete(colorData
.mBackAttachment
, bg
->mBackgroundAttachment
, inherited
,
3697 SETDSC_ENUMERATED
, parentBG
->mBackgroundAttachment
,
3698 NS_STYLE_BG_ATTACHMENT_SCROLL
, 0, 0, 0, 0);
3700 // background-clip: enum, inherit, initial
3701 SetDiscrete(colorData
.mBackClip
, bg
->mBackgroundClip
, inherited
,
3702 SETDSC_ENUMERATED
, parentBG
->mBackgroundClip
,
3703 NS_STYLE_BG_CLIP_BORDER
, 0, 0, 0, 0);
3705 // background-inline-policy: enum, inherit, initial
3706 SetDiscrete(colorData
.mBackInlinePolicy
, bg
->mBackgroundInlinePolicy
,
3707 inherited
, SETDSC_ENUMERATED
,
3708 parentBG
->mBackgroundInlinePolicy
,
3709 NS_STYLE_BG_INLINE_POLICY_CONTINUOUS
, 0, 0, 0, 0);
3711 // background-origin: enum, inherit, initial
3712 SetDiscrete(colorData
.mBackOrigin
, bg
->mBackgroundOrigin
, inherited
,
3713 SETDSC_ENUMERATED
, parentBG
->mBackgroundOrigin
,
3714 NS_STYLE_BG_ORIGIN_PADDING
, 0, 0, 0, 0);
3716 // background-position: enum, length, percent (flags), inherit
3717 if (eCSSUnit_Percent
== colorData
.mBackPosition
.mXValue
.GetUnit()) {
3718 bg
->mBackgroundXPosition
.mFloat
= colorData
.mBackPosition
.mXValue
.GetPercentValue();
3719 bg
->mBackgroundFlags
|= NS_STYLE_BG_X_POSITION_PERCENT
;
3720 bg
->mBackgroundFlags
&= ~NS_STYLE_BG_X_POSITION_LENGTH
;
3722 else if (colorData
.mBackPosition
.mXValue
.IsLengthUnit()) {
3723 bg
->mBackgroundXPosition
.mCoord
= CalcLength(colorData
.mBackPosition
.mXValue
,
3724 aContext
, mPresContext
, inherited
);
3725 bg
->mBackgroundFlags
|= NS_STYLE_BG_X_POSITION_LENGTH
;
3726 bg
->mBackgroundFlags
&= ~NS_STYLE_BG_X_POSITION_PERCENT
;
3728 else if (eCSSUnit_Enumerated
== colorData
.mBackPosition
.mXValue
.GetUnit()) {
3729 bg
->mBackgroundXPosition
.mFloat
=
3730 GetFloatFromBoxPosition(colorData
.mBackPosition
.mXValue
.GetIntValue());
3732 bg
->mBackgroundFlags
|= NS_STYLE_BG_X_POSITION_PERCENT
;
3733 bg
->mBackgroundFlags
&= ~NS_STYLE_BG_X_POSITION_LENGTH
;
3735 else if (eCSSUnit_Inherit
== colorData
.mBackPosition
.mXValue
.GetUnit()) {
3736 inherited
= PR_TRUE
;
3737 bg
->mBackgroundXPosition
= parentBG
->mBackgroundXPosition
;
3738 bg
->mBackgroundFlags
&= ~(NS_STYLE_BG_X_POSITION_LENGTH
| NS_STYLE_BG_X_POSITION_PERCENT
);
3739 bg
->mBackgroundFlags
|= (parentFlags
& (NS_STYLE_BG_X_POSITION_LENGTH
| NS_STYLE_BG_X_POSITION_PERCENT
));
3741 else if (eCSSUnit_Initial
== colorData
.mBackPosition
.mXValue
.GetUnit()) {
3742 bg
->mBackgroundFlags
&= ~(NS_STYLE_BG_X_POSITION_LENGTH
| NS_STYLE_BG_X_POSITION_PERCENT
);
3745 if (eCSSUnit_Percent
== colorData
.mBackPosition
.mYValue
.GetUnit()) {
3746 bg
->mBackgroundYPosition
.mFloat
= colorData
.mBackPosition
.mYValue
.GetPercentValue();
3747 bg
->mBackgroundFlags
|= NS_STYLE_BG_Y_POSITION_PERCENT
;
3748 bg
->mBackgroundFlags
&= ~NS_STYLE_BG_Y_POSITION_LENGTH
;
3750 else if (colorData
.mBackPosition
.mYValue
.IsLengthUnit()) {
3751 bg
->mBackgroundYPosition
.mCoord
= CalcLength(colorData
.mBackPosition
.mYValue
,
3752 aContext
, mPresContext
, inherited
);
3753 bg
->mBackgroundFlags
|= NS_STYLE_BG_Y_POSITION_LENGTH
;
3754 bg
->mBackgroundFlags
&= ~NS_STYLE_BG_Y_POSITION_PERCENT
;
3756 else if (eCSSUnit_Enumerated
== colorData
.mBackPosition
.mYValue
.GetUnit()) {
3757 bg
->mBackgroundYPosition
.mFloat
=
3758 GetFloatFromBoxPosition(colorData
.mBackPosition
.mYValue
.GetIntValue());
3760 bg
->mBackgroundFlags
|= NS_STYLE_BG_Y_POSITION_PERCENT
;
3761 bg
->mBackgroundFlags
&= ~NS_STYLE_BG_Y_POSITION_LENGTH
;
3763 else if (eCSSUnit_Inherit
== colorData
.mBackPosition
.mYValue
.GetUnit()) {
3764 inherited
= PR_TRUE
;
3765 bg
->mBackgroundYPosition
= parentBG
->mBackgroundYPosition
;
3766 bg
->mBackgroundFlags
&= ~(NS_STYLE_BG_Y_POSITION_LENGTH
| NS_STYLE_BG_Y_POSITION_PERCENT
);
3767 bg
->mBackgroundFlags
|= (parentFlags
& (NS_STYLE_BG_Y_POSITION_LENGTH
| NS_STYLE_BG_Y_POSITION_PERCENT
));
3769 else if (eCSSUnit_Initial
== colorData
.mBackPosition
.mYValue
.GetUnit()) {
3770 bg
->mBackgroundFlags
&= ~(NS_STYLE_BG_Y_POSITION_LENGTH
| NS_STYLE_BG_Y_POSITION_PERCENT
);
3773 COMPUTE_END_RESET(Background
, bg
)
3777 nsRuleNode::ComputeMarginData(void* aStartStruct
,
3778 const nsRuleDataStruct
& aData
,
3779 nsStyleContext
* aContext
,
3780 nsRuleNode
* aHighestNode
,
3781 const RuleDetail aRuleDetail
, PRBool aInherited
)
3783 COMPUTE_START_RESET(Margin
, (), margin
, parentMargin
, Margin
, marginData
)
3785 // margin: length, percent, auto, inherit
3787 nsCSSRect
ourMargin(marginData
.mMargin
);
3788 AdjustLogicalBoxProp(aContext
,
3789 marginData
.mMarginLeftLTRSource
,
3790 marginData
.mMarginLeftRTLSource
,
3791 marginData
.mMarginStart
, marginData
.mMarginEnd
,
3792 NS_SIDE_LEFT
, ourMargin
, inherited
);
3793 AdjustLogicalBoxProp(aContext
,
3794 marginData
.mMarginRightLTRSource
,
3795 marginData
.mMarginRightRTLSource
,
3796 marginData
.mMarginEnd
, marginData
.mMarginStart
,
3797 NS_SIDE_RIGHT
, ourMargin
, inherited
);
3798 NS_FOR_CSS_SIDES(side
) {
3799 nsStyleCoord parentCoord
= parentMargin
->mMargin
.Get(side
);
3800 if (SetCoord(ourMargin
.*(nsCSSRect::sides
[side
]),
3801 coord
, parentCoord
, SETCOORD_LPAH
| SETCOORD_INITIAL_ZERO
,
3802 aContext
, mPresContext
, inherited
)) {
3803 margin
->mMargin
.Set(side
, coord
);
3807 margin
->RecalcData();
3808 COMPUTE_END_RESET(Margin
, margin
)
3812 nsRuleNode::ComputeBorderData(void* aStartStruct
,
3813 const nsRuleDataStruct
& aData
,
3814 nsStyleContext
* aContext
,
3815 nsRuleNode
* aHighestNode
,
3816 const RuleDetail aRuleDetail
, PRBool aInherited
)
3818 COMPUTE_START_RESET(Border
, (mPresContext
), border
, parentBorder
,
3821 // -moz-box-shadow: none, list, inherit, initial
3822 nsCSSValueList
* list
= marginData
.mBoxShadow
;
3824 // This handles 'none' and 'initial'
3825 border
->mBoxShadow
= nsnull
;
3827 if (eCSSUnit_Inherit
== list
->mValue
.GetUnit()) {
3828 inherited
= PR_TRUE
;
3829 border
->mBoxShadow
= parentBorder
->mBoxShadow
;
3830 } else if (eCSSUnit_Array
== list
->mValue
.GetUnit()) {
3832 border
->mBoxShadow
= GetShadowData(list
, aContext
, PR_TRUE
, inherited
);
3836 // border-width, border-*-width: length, enum, inherit
3838 nsCSSRect
ourBorderWidth(marginData
.mBorderWidth
);
3839 AdjustLogicalBoxProp(aContext
,
3840 marginData
.mBorderLeftWidthLTRSource
,
3841 marginData
.mBorderLeftWidthRTLSource
,
3842 marginData
.mBorderStartWidth
,
3843 marginData
.mBorderEndWidth
,
3844 NS_SIDE_LEFT
, ourBorderWidth
, inherited
);
3845 AdjustLogicalBoxProp(aContext
,
3846 marginData
.mBorderRightWidthLTRSource
,
3847 marginData
.mBorderRightWidthRTLSource
,
3848 marginData
.mBorderEndWidth
,
3849 marginData
.mBorderStartWidth
,
3850 NS_SIDE_RIGHT
, ourBorderWidth
, inherited
);
3851 { // scope for compilers with broken |for| loop scoping
3852 NS_FOR_CSS_SIDES(side
) {
3853 const nsCSSValue
&value
= ourBorderWidth
.*(nsCSSRect::sides
[side
]);
3854 NS_ASSERTION(eCSSUnit_Percent
!= value
.GetUnit(),
3855 "Percentage borders not implemented yet "
3856 "If implementing, make sure to fix all consumers of "
3857 "nsStyleBorder, the IsPercentageAwareChild method, "
3858 "the nsAbsoluteContainingBlock::FrameDependsOnContainer "
3860 "nsLineLayout::IsPercentageAwareReplacedElement method "
3861 "and probably some other places");
3862 if (eCSSUnit_Enumerated
== value
.GetUnit()) {
3863 NS_ASSERTION(value
.GetIntValue() == NS_STYLE_BORDER_WIDTH_THIN
||
3864 value
.GetIntValue() == NS_STYLE_BORDER_WIDTH_MEDIUM
||
3865 value
.GetIntValue() == NS_STYLE_BORDER_WIDTH_THICK
,
3866 "Unexpected enum value");
3867 border
->SetBorderWidth(side
,
3868 (mPresContext
->GetBorderWidthTable())[value
.GetIntValue()]);
3870 // OK to pass bad aParentCoord since we're not passing SETCOORD_INHERIT
3871 else if (SetCoord(value
, coord
, nsStyleCoord(), SETCOORD_LENGTH
,
3872 aContext
, mPresContext
, inherited
)) {
3873 NS_ASSERTION(coord
.GetUnit() == eStyleUnit_Coord
, "unexpected unit");
3874 border
->SetBorderWidth(side
, coord
.GetCoordValue());
3876 else if (eCSSUnit_Inherit
== value
.GetUnit()) {
3877 inherited
= PR_TRUE
;
3878 border
->SetBorderWidth(side
,
3879 parentBorder
->GetComputedBorder().side(side
));
3881 else if (eCSSUnit_Initial
== value
.GetUnit()) {
3882 border
->SetBorderWidth(side
,
3883 (mPresContext
->GetBorderWidthTable())[NS_STYLE_BORDER_WIDTH_MEDIUM
]);
3886 NS_ASSERTION(eCSSUnit_Null
== value
.GetUnit(),
3887 "missing case handling border width");
3892 // border-style, border-*-style: enum, none, inherit
3893 nsCSSRect
ourStyle(marginData
.mBorderStyle
);
3894 AdjustLogicalBoxProp(aContext
,
3895 marginData
.mBorderLeftStyleLTRSource
,
3896 marginData
.mBorderLeftStyleRTLSource
,
3897 marginData
.mBorderStartStyle
, marginData
.mBorderEndStyle
,
3898 NS_SIDE_LEFT
, ourStyle
, inherited
);
3899 AdjustLogicalBoxProp(aContext
,
3900 marginData
.mBorderRightStyleLTRSource
,
3901 marginData
.mBorderRightStyleRTLSource
,
3902 marginData
.mBorderEndStyle
, marginData
.mBorderStartStyle
,
3903 NS_SIDE_RIGHT
, ourStyle
, inherited
);
3904 { // scope for compilers with broken |for| loop scoping
3905 NS_FOR_CSS_SIDES(side
) {
3906 const nsCSSValue
&value
= ourStyle
.*(nsCSSRect::sides
[side
]);
3907 nsCSSUnit unit
= value
.GetUnit();
3908 if (eCSSUnit_Enumerated
== unit
) {
3909 border
->SetBorderStyle(side
, value
.GetIntValue());
3911 else if (eCSSUnit_None
== unit
|| eCSSUnit_Initial
== unit
) {
3912 border
->SetBorderStyle(side
, NS_STYLE_BORDER_STYLE_NONE
);
3914 else if (eCSSUnit_Inherit
== unit
) {
3915 inherited
= PR_TRUE
;
3916 border
->SetBorderStyle(side
, parentBorder
->GetBorderStyle(side
));
3921 // -moz-border-*-colors: color, string, enum
3922 nscolor borderColor
;
3923 nscolor unused
= NS_RGB(0,0,0);
3925 { // scope for compilers with broken |for| loop scoping
3926 NS_FOR_CSS_SIDES(side
) {
3927 nsCSSValueList
* list
=
3928 marginData
.mBorderColors
.*(nsCSSValueListRect::sides
[side
]);
3929 // FIXME Bug 389404: Implement inherit and -moz-initial.
3931 // Some composite border color information has been specified for this
3933 border
->EnsureBorderColors();
3934 border
->ClearBorderColors(side
);
3936 if (SetColor(list
->mValue
, unused
, mPresContext
,
3937 aContext
, borderColor
, inherited
))
3938 border
->AppendBorderColor(side
, borderColor
);
3945 // border-color, border-*-color: color, string, enum, inherit
3946 nsCSSRect
ourBorderColor(marginData
.mBorderColor
);
3948 AdjustLogicalBoxProp(aContext
,
3949 marginData
.mBorderLeftColorLTRSource
,
3950 marginData
.mBorderLeftColorRTLSource
,
3951 marginData
.mBorderStartColor
, marginData
.mBorderEndColor
,
3952 NS_SIDE_LEFT
, ourBorderColor
, inherited
);
3953 AdjustLogicalBoxProp(aContext
,
3954 marginData
.mBorderRightColorLTRSource
,
3955 marginData
.mBorderRightColorRTLSource
,
3956 marginData
.mBorderEndColor
, marginData
.mBorderStartColor
,
3957 NS_SIDE_RIGHT
, ourBorderColor
, inherited
);
3958 { // scope for compilers with broken |for| loop scoping
3959 NS_FOR_CSS_SIDES(side
) {
3960 const nsCSSValue
&value
= ourBorderColor
.*(nsCSSRect::sides
[side
]);
3961 if (eCSSUnit_Inherit
== value
.GetUnit()) {
3962 if (parentContext
) {
3963 inherited
= PR_TRUE
;
3964 parentBorder
->GetBorderColor(side
, borderColor
, foreground
);
3966 // We want to inherit the color from the parent, not use the
3967 // color on the element where this chunk of style data will be
3968 // used. We can ensure that the data for the parent are fully
3969 // computed (unlike for the element where this will be used, for
3970 // which the color could be specified on a more specific rule).
3971 border
->SetBorderColor(side
, parentContext
->GetStyleColor()->mColor
);
3973 border
->SetBorderColor(side
, borderColor
);
3976 border
->SetBorderToForeground(side
);
3979 else if (SetColor(value
, unused
, mPresContext
, aContext
, borderColor
, inherited
)) {
3980 border
->SetBorderColor(side
, borderColor
);
3982 else if (eCSSUnit_Enumerated
== value
.GetUnit()) {
3983 switch (value
.GetIntValue()) {
3984 case NS_STYLE_COLOR_MOZ_USE_TEXT_COLOR
:
3985 border
->SetBorderToForeground(side
);
3989 else if (eCSSUnit_Initial
== value
.GetUnit()) {
3990 border
->SetBorderToForeground(side
);
3995 // -moz-border-radius: length, percent, inherit
3997 const nsCSSCornerSizes
& borderRadius
= marginData
.mBorderRadius
;
3998 NS_FOR_CSS_HALF_CORNERS(corner
) {
3999 nsStyleCoord parentCoord
= parentBorder
->mBorderRadius
.Get(corner
);
4000 if (SetCoord(borderRadius
.GetHalfCorner(corner
),
4001 coord
, parentCoord
, SETCOORD_LPH
| SETCOORD_INITIAL_ZERO
,
4002 aContext
, mPresContext
, inherited
))
4003 border
->mBorderRadius
.Set(corner
, coord
);
4007 // float-edge: enum, inherit, initial
4008 SetDiscrete(marginData
.mFloatEdge
, border
->mFloatEdge
, inherited
,
4009 SETDSC_ENUMERATED
, parentBorder
->mFloatEdge
,
4010 NS_STYLE_FLOAT_EDGE_CONTENT
, 0, 0, 0, 0);
4013 if (eCSSUnit_Array
== marginData
.mBorderImage
.GetUnit()) {
4014 nsCSSValue::Array
*arr
= marginData
.mBorderImage
.GetArrayValue();
4017 if (eCSSUnit_Image
== arr
->Item(0).GetUnit()) {
4018 border
->SetBorderImage(arr
->Item(0).GetImageValue());
4021 // the numbers saying where to split the image
4022 NS_FOR_CSS_SIDES(side
) {
4023 // an uninitialized parentCoord is ok because I'm not passing SETCOORD_INHERIT
4024 if (SetCoord(arr
->Item(1 + side
), coord
, nsStyleCoord(),
4025 SETCOORD_FACTOR
| SETCOORD_PERCENT
, aContext
,
4026 mPresContext
, inherited
)) {
4027 border
->mBorderImageSplit
.Set(side
, coord
);
4031 // possible replacement for border-width
4032 // if have one - have all four (see CSSParserImpl::ParseBorderImage())
4033 if (eCSSUnit_Null
!= arr
->Item(5).GetUnit()) {
4034 NS_FOR_CSS_SIDES(side
) {
4035 // an uninitialized parentCoord is ok because I'm not passing SETCOORD_INHERIT
4036 if (!SetCoord(arr
->Item(5 + side
), coord
, nsStyleCoord(),
4037 SETCOORD_LENGTH
, aContext
, mPresContext
, inherited
)) {
4038 NS_NOTREACHED("SetCoord for border-width replacement from border-image failed");
4040 if (coord
.GetUnit() == eStyleUnit_Coord
) {
4041 border
->SetBorderImageWidthOverride(side
, coord
.GetCoordValue());
4043 NS_WARNING("a border-width replacement from border-image "
4044 "has a unit that's not eStyleUnit_Coord");
4045 border
->SetBorderImageWidthOverride(side
, 0);
4048 border
->mHaveBorderImageWidth
= PR_TRUE
;
4050 border
->mHaveBorderImageWidth
= PR_FALSE
;
4053 // stretch/round/repeat keywords
4054 if (eCSSUnit_Null
== arr
->Item(9).GetUnit()) {
4055 // default, both horizontal and vertical are stretch
4056 border
->mBorderImageHFill
= NS_STYLE_BORDER_IMAGE_STRETCH
;
4057 border
->mBorderImageVFill
= NS_STYLE_BORDER_IMAGE_STRETCH
;
4059 // have horizontal value
4060 border
->mBorderImageHFill
= arr
->Item(9).GetIntValue();
4061 if (eCSSUnit_Null
== arr
->Item(10).GetUnit()) {
4062 // vertical same as horizontal
4063 border
->mBorderImageVFill
= border
->mBorderImageHFill
;
4065 // have vertical value
4066 border
->mBorderImageVFill
= arr
->Item(10).GetIntValue();
4069 } else if (eCSSUnit_None
== marginData
.mBorderImage
.GetUnit() ||
4070 eCSSUnit_Initial
== marginData
.mBorderImage
.GetUnit()) {
4071 border
->mHaveBorderImageWidth
= PR_FALSE
;
4072 border
->SetBorderImage(nsnull
);
4073 } else if (eCSSUnit_Inherit
== marginData
.mBorderImage
.GetUnit()) {
4074 NS_FOR_CSS_SIDES(side
) {
4075 border
->SetBorderImageWidthOverride(side
, parentBorder
->mBorderImageWidth
.side(side
));
4077 border
->mBorderImageSplit
= parentBorder
->mBorderImageSplit
;
4078 border
->mBorderImageHFill
= parentBorder
->mBorderImageHFill
;
4079 border
->mBorderImageVFill
= parentBorder
->mBorderImageVFill
;
4080 border
->mHaveBorderImageWidth
= parentBorder
->mHaveBorderImageWidth
;
4081 border
->SetBorderImage(parentBorder
->GetBorderImage());
4084 COMPUTE_END_RESET(Border
, border
)
4088 nsRuleNode::ComputePaddingData(void* aStartStruct
,
4089 const nsRuleDataStruct
& aData
,
4090 nsStyleContext
* aContext
,
4091 nsRuleNode
* aHighestNode
,
4092 const RuleDetail aRuleDetail
, PRBool aInherited
)
4094 COMPUTE_START_RESET(Padding
, (), padding
, parentPadding
, Margin
, marginData
)
4096 // padding: length, percent, inherit
4098 nsCSSRect
ourPadding(marginData
.mPadding
);
4099 AdjustLogicalBoxProp(aContext
,
4100 marginData
.mPaddingLeftLTRSource
,
4101 marginData
.mPaddingLeftRTLSource
,
4102 marginData
.mPaddingStart
, marginData
.mPaddingEnd
,
4103 NS_SIDE_LEFT
, ourPadding
, inherited
);
4104 AdjustLogicalBoxProp(aContext
,
4105 marginData
.mPaddingRightLTRSource
,
4106 marginData
.mPaddingRightRTLSource
,
4107 marginData
.mPaddingEnd
, marginData
.mPaddingStart
,
4108 NS_SIDE_RIGHT
, ourPadding
, inherited
);
4109 NS_FOR_CSS_SIDES(side
) {
4110 nsStyleCoord parentCoord
= parentPadding
->mPadding
.Get(side
);
4111 if (SetCoord(ourPadding
.*(nsCSSRect::sides
[side
]),
4112 coord
, parentCoord
, SETCOORD_LPH
| SETCOORD_INITIAL_ZERO
,
4113 aContext
, mPresContext
, inherited
)) {
4114 padding
->mPadding
.Set(side
, coord
);
4118 padding
->RecalcData();
4119 COMPUTE_END_RESET(Padding
, padding
)
4123 nsRuleNode::ComputeOutlineData(void* aStartStruct
,
4124 const nsRuleDataStruct
& aData
,
4125 nsStyleContext
* aContext
,
4126 nsRuleNode
* aHighestNode
,
4127 const RuleDetail aRuleDetail
, PRBool aInherited
)
4129 COMPUTE_START_RESET(Outline
, (mPresContext
), outline
, parentOutline
,
4132 // outline-width: length, enum, inherit
4133 if (eCSSUnit_Initial
== marginData
.mOutlineWidth
.GetUnit()) {
4134 outline
->mOutlineWidth
=
4135 nsStyleCoord(NS_STYLE_BORDER_WIDTH_MEDIUM
, eStyleUnit_Enumerated
);
4138 SetCoord(marginData
.mOutlineWidth
, outline
->mOutlineWidth
,
4139 parentOutline
->mOutlineWidth
, SETCOORD_LEH
, aContext
,
4140 mPresContext
, inherited
);
4143 // outline-offset: length, inherit
4144 nsStyleCoord tempCoord
;
4145 if (SetCoord(marginData
.mOutlineOffset
, tempCoord
,
4146 parentOutline
->mOutlineOffset
,
4147 SETCOORD_LH
| SETCOORD_INITIAL_ZERO
, aContext
, mPresContext
,
4149 outline
->mOutlineOffset
= tempCoord
.GetCoordValue();
4151 NS_ASSERTION(marginData
.mOutlineOffset
.GetUnit() == eCSSUnit_Null
,
4155 // outline-color: color, string, enum, inherit
4156 nscolor outlineColor
;
4157 nscolor unused
= NS_RGB(0,0,0);
4158 if (eCSSUnit_Inherit
== marginData
.mOutlineColor
.GetUnit()) {
4159 if (parentContext
) {
4160 inherited
= PR_TRUE
;
4161 if (parentOutline
->GetOutlineColor(outlineColor
))
4162 outline
->SetOutlineColor(outlineColor
);
4164 #ifdef GFX_HAS_INVERT
4165 outline
->SetOutlineInitialColor();
4167 // We want to inherit the color from the parent, not use the
4168 // color on the element where this chunk of style data will be
4169 // used. We can ensure that the data for the parent are fully
4170 // computed (unlike for the element where this will be used, for
4171 // which the color could be specified on a more specific rule).
4172 outline
->SetOutlineColor(parentContext
->GetStyleColor()->mColor
);
4176 outline
->SetOutlineInitialColor();
4179 else if (SetColor(marginData
.mOutlineColor
, unused
, mPresContext
, aContext
, outlineColor
, inherited
))
4180 outline
->SetOutlineColor(outlineColor
);
4181 else if (eCSSUnit_Enumerated
== marginData
.mOutlineColor
.GetUnit() ||
4182 eCSSUnit_Initial
== marginData
.mOutlineColor
.GetUnit()) {
4183 outline
->SetOutlineInitialColor();
4186 // -moz-outline-radius: length, percent, inherit
4189 const nsCSSCornerSizes
& outlineRadius
= marginData
.mOutlineRadius
;
4190 NS_FOR_CSS_HALF_CORNERS(corner
) {
4191 nsStyleCoord parentCoord
= parentOutline
->mOutlineRadius
.Get(corner
);
4192 if (SetCoord(outlineRadius
.GetHalfCorner(corner
),
4193 coord
, parentCoord
, SETCOORD_LPH
| SETCOORD_INITIAL_ZERO
,
4194 aContext
, mPresContext
, inherited
))
4195 outline
->mOutlineRadius
.Set(corner
, coord
);
4199 // outline-style: auto, enum, none, inherit, initial
4200 // cannot use SetDiscrete because of SetOutlineStyle
4201 if (eCSSUnit_Enumerated
== marginData
.mOutlineStyle
.GetUnit())
4202 outline
->SetOutlineStyle(marginData
.mOutlineStyle
.GetIntValue());
4203 else if (eCSSUnit_None
== marginData
.mOutlineStyle
.GetUnit() ||
4204 eCSSUnit_Initial
== marginData
.mOutlineStyle
.GetUnit())
4205 outline
->SetOutlineStyle(NS_STYLE_BORDER_STYLE_NONE
);
4206 else if (eCSSUnit_Auto
== marginData
.mOutlineStyle
.GetUnit()) {
4207 outline
->SetOutlineStyle(NS_STYLE_BORDER_STYLE_AUTO
);
4208 } else if (eCSSUnit_Inherit
== marginData
.mOutlineStyle
.GetUnit()) {
4209 inherited
= PR_TRUE
;
4210 outline
->SetOutlineStyle(parentOutline
->GetOutlineStyle());
4213 outline
->RecalcData(mPresContext
);
4214 COMPUTE_END_RESET(Outline
, outline
)
4218 nsRuleNode::ComputeListData(void* aStartStruct
,
4219 const nsRuleDataStruct
& aData
,
4220 nsStyleContext
* aContext
,
4221 nsRuleNode
* aHighestNode
,
4222 const RuleDetail aRuleDetail
, PRBool aInherited
)
4224 COMPUTE_START_INHERITED(List
, (), list
, parentList
, List
, listData
)
4226 // list-style-type: enum, none, inherit, initial
4227 SetDiscrete(listData
.mType
, list
->mListStyleType
, inherited
,
4228 SETDSC_ENUMERATED
| SETDSC_NONE
, parentList
->mListStyleType
,
4229 NS_STYLE_LIST_STYLE_DISC
, 0,
4230 NS_STYLE_LIST_STYLE_NONE
, 0, 0);
4232 // list-style-image: url, none, inherit
4233 if (eCSSUnit_Image
== listData
.mImage
.GetUnit()) {
4234 list
->mListStyleImage
= listData
.mImage
.GetImageValue();
4236 else if (eCSSUnit_None
== listData
.mImage
.GetUnit() ||
4237 eCSSUnit_Initial
== listData
.mImage
.GetUnit()) {
4238 list
->mListStyleImage
= nsnull
;
4240 else if (eCSSUnit_Inherit
== listData
.mImage
.GetUnit()) {
4241 inherited
= PR_TRUE
;
4242 list
->mListStyleImage
= parentList
->mListStyleImage
;
4245 // list-style-position: enum, inherit, initial
4246 SetDiscrete(listData
.mPosition
, list
->mListStylePosition
, inherited
,
4247 SETDSC_ENUMERATED
, parentList
->mListStylePosition
,
4248 NS_STYLE_LIST_STYLE_POSITION_OUTSIDE
, 0, 0, 0, 0);
4250 // image region property: length, auto, inherit
4251 if (eCSSUnit_Inherit
== listData
.mImageRegion
.mTop
.GetUnit()) { // if one is inherit, they all are
4252 inherited
= PR_TRUE
;
4253 list
->mImageRegion
= parentList
->mImageRegion
;
4255 // if one is -moz-initial, they all are
4256 else if (eCSSUnit_Initial
== listData
.mImageRegion
.mTop
.GetUnit()) {
4257 list
->mImageRegion
.Empty();
4260 if (eCSSUnit_Auto
== listData
.mImageRegion
.mTop
.GetUnit())
4261 list
->mImageRegion
.y
= 0;
4262 else if (listData
.mImageRegion
.mTop
.IsLengthUnit())
4263 list
->mImageRegion
.y
= CalcLength(listData
.mImageRegion
.mTop
, aContext
, mPresContext
, inherited
);
4265 if (eCSSUnit_Auto
== listData
.mImageRegion
.mBottom
.GetUnit())
4266 list
->mImageRegion
.height
= 0;
4267 else if (listData
.mImageRegion
.mBottom
.IsLengthUnit())
4268 list
->mImageRegion
.height
= CalcLength(listData
.mImageRegion
.mBottom
, aContext
,
4269 mPresContext
, inherited
) - list
->mImageRegion
.y
;
4271 if (eCSSUnit_Auto
== listData
.mImageRegion
.mLeft
.GetUnit())
4272 list
->mImageRegion
.x
= 0;
4273 else if (listData
.mImageRegion
.mLeft
.IsLengthUnit())
4274 list
->mImageRegion
.x
= CalcLength(listData
.mImageRegion
.mLeft
, aContext
, mPresContext
, inherited
);
4276 if (eCSSUnit_Auto
== listData
.mImageRegion
.mRight
.GetUnit())
4277 list
->mImageRegion
.width
= 0;
4278 else if (listData
.mImageRegion
.mRight
.IsLengthUnit())
4279 list
->mImageRegion
.width
= CalcLength(listData
.mImageRegion
.mRight
, aContext
, mPresContext
, inherited
) -
4280 list
->mImageRegion
.x
;
4283 COMPUTE_END_INHERITED(List
, list
)
4287 nsRuleNode::ComputePositionData(void* aStartStruct
,
4288 const nsRuleDataStruct
& aData
,
4289 nsStyleContext
* aContext
,
4290 nsRuleNode
* aHighestNode
,
4291 const RuleDetail aRuleDetail
, PRBool aInherited
)
4293 COMPUTE_START_RESET(Position
, (), pos
, parentPos
, Position
, posData
)
4295 // box offsets: length, percent, auto, inherit
4297 NS_FOR_CSS_SIDES(side
) {
4298 nsStyleCoord parentCoord
= parentPos
->mOffset
.Get(side
);
4299 if (SetCoord(posData
.mOffset
.*(nsCSSRect::sides
[side
]),
4300 coord
, parentCoord
, SETCOORD_LPAH
| SETCOORD_INITIAL_AUTO
,
4301 aContext
, mPresContext
, inherited
)) {
4302 pos
->mOffset
.Set(side
, coord
);
4306 SetCoord(posData
.mWidth
, pos
->mWidth
, parentPos
->mWidth
,
4307 SETCOORD_LPAEH
| SETCOORD_INITIAL_AUTO
, aContext
,
4308 mPresContext
, inherited
);
4309 SetCoord(posData
.mMinWidth
, pos
->mMinWidth
, parentPos
->mMinWidth
,
4310 SETCOORD_LPEH
| SETCOORD_INITIAL_ZERO
, aContext
,
4311 mPresContext
, inherited
);
4312 SetCoord(posData
.mMaxWidth
, pos
->mMaxWidth
, parentPos
->mMaxWidth
,
4313 SETCOORD_LPOEH
| SETCOORD_INITIAL_NONE
, aContext
,
4314 mPresContext
, inherited
);
4316 SetCoord(posData
.mHeight
, pos
->mHeight
, parentPos
->mHeight
,
4317 SETCOORD_LPAH
| SETCOORD_INITIAL_AUTO
, aContext
,
4318 mPresContext
, inherited
);
4319 SetCoord(posData
.mMinHeight
, pos
->mMinHeight
, parentPos
->mMinHeight
,
4320 SETCOORD_LPH
| SETCOORD_INITIAL_ZERO
, aContext
,
4321 mPresContext
, inherited
);
4322 SetCoord(posData
.mMaxHeight
, pos
->mMaxHeight
, parentPos
->mMaxHeight
,
4323 SETCOORD_LPOH
| SETCOORD_INITIAL_NONE
, aContext
,
4324 mPresContext
, inherited
);
4326 // box-sizing: enum, inherit, initial
4327 SetDiscrete(posData
.mBoxSizing
, pos
->mBoxSizing
, inherited
,
4328 SETDSC_ENUMERATED
, parentPos
->mBoxSizing
,
4329 NS_STYLE_BOX_SIZING_CONTENT
, 0, 0, 0, 0);
4332 if (! SetCoord(posData
.mZIndex
, pos
->mZIndex
, parentPos
->mZIndex
,
4333 SETCOORD_IA
| SETCOORD_INITIAL_AUTO
, aContext
,
4334 nsnull
, inherited
)) {
4335 if (eCSSUnit_Inherit
== posData
.mZIndex
.GetUnit()) {
4336 // handle inherit, because it's ok to inherit 'auto' here
4337 inherited
= PR_TRUE
;
4338 pos
->mZIndex
= parentPos
->mZIndex
;
4342 COMPUTE_END_RESET(Position
, pos
)
4346 nsRuleNode::ComputeTableData(void* aStartStruct
,
4347 const nsRuleDataStruct
& aData
,
4348 nsStyleContext
* aContext
,
4349 nsRuleNode
* aHighestNode
,
4350 const RuleDetail aRuleDetail
, PRBool aInherited
)
4352 COMPUTE_START_RESET(Table
, (), table
, parentTable
, Table
, tableData
)
4354 // table-layout: auto, enum, inherit, initial
4355 SetDiscrete(tableData
.mLayout
, table
->mLayoutStrategy
, inherited
,
4356 SETDSC_ENUMERATED
| SETDSC_AUTO
,
4357 parentTable
->mLayoutStrategy
,
4358 NS_STYLE_TABLE_LAYOUT_AUTO
,
4359 NS_STYLE_TABLE_LAYOUT_AUTO
, 0, 0, 0);
4361 // rules: enum (not a real CSS prop)
4362 if (eCSSUnit_Enumerated
== tableData
.mRules
.GetUnit())
4363 table
->mRules
= tableData
.mRules
.GetIntValue();
4365 // frame: enum (not a real CSS prop)
4366 if (eCSSUnit_Enumerated
== tableData
.mFrame
.GetUnit())
4367 table
->mFrame
= tableData
.mFrame
.GetIntValue();
4369 // cols: enum, int (not a real CSS prop)
4370 if (eCSSUnit_Enumerated
== tableData
.mCols
.GetUnit() ||
4371 eCSSUnit_Integer
== tableData
.mCols
.GetUnit())
4372 table
->mCols
= tableData
.mCols
.GetIntValue();
4374 // span: pixels (not a real CSS prop)
4375 if (eCSSUnit_Enumerated
== tableData
.mSpan
.GetUnit() ||
4376 eCSSUnit_Integer
== tableData
.mSpan
.GetUnit())
4377 table
->mSpan
= tableData
.mSpan
.GetIntValue();
4379 COMPUTE_END_RESET(Table
, table
)
4383 nsRuleNode::ComputeTableBorderData(void* aStartStruct
,
4384 const nsRuleDataStruct
& aData
,
4385 nsStyleContext
* aContext
,
4386 nsRuleNode
* aHighestNode
,
4387 const RuleDetail aRuleDetail
, PRBool aInherited
)
4389 COMPUTE_START_INHERITED(TableBorder
, (mPresContext
), table
, parentTable
,
4392 // border-collapse: enum, inherit, initial
4393 SetDiscrete(tableData
.mBorderCollapse
, table
->mBorderCollapse
, inherited
,
4394 SETDSC_ENUMERATED
, parentTable
->mBorderCollapse
,
4395 NS_STYLE_BORDER_SEPARATE
, 0, 0, 0, 0);
4397 // border-spacing-x: length, inherit
4398 nsStyleCoord tempCoord
;
4399 if (SetCoord(tableData
.mBorderSpacing
.mXValue
, tempCoord
,
4400 parentTable
->mBorderSpacingX
,
4401 SETCOORD_LH
| SETCOORD_INITIAL_ZERO
,
4402 aContext
, mPresContext
, inherited
)) {
4403 table
->mBorderSpacingX
= tempCoord
.GetCoordValue();
4405 NS_ASSERTION(tableData
.mBorderSpacing
.mXValue
.GetUnit() == eCSSUnit_Null
,
4409 // border-spacing-y: length, inherit
4410 if (SetCoord(tableData
.mBorderSpacing
.mYValue
, tempCoord
,
4411 parentTable
->mBorderSpacingY
,
4412 SETCOORD_LH
| SETCOORD_INITIAL_ZERO
,
4413 aContext
, mPresContext
, inherited
)) {
4414 table
->mBorderSpacingY
= tempCoord
.GetCoordValue();
4416 NS_ASSERTION(tableData
.mBorderSpacing
.mYValue
.GetUnit() == eCSSUnit_Null
,
4420 // caption-side: enum, inherit, initial
4421 SetDiscrete(tableData
.mCaptionSide
, table
->mCaptionSide
, inherited
,
4422 SETDSC_ENUMERATED
, parentTable
->mCaptionSide
,
4423 NS_STYLE_CAPTION_SIDE_TOP
, 0, 0, 0, 0);
4425 // empty-cells: enum, inherit, initial
4426 SetDiscrete(tableData
.mEmptyCells
, table
->mEmptyCells
, inherited
,
4427 SETDSC_ENUMERATED
, parentTable
->mEmptyCells
,
4428 (mPresContext
->CompatibilityMode() == eCompatibility_NavQuirks
)
4429 ? NS_STYLE_TABLE_EMPTY_CELLS_SHOW_BACKGROUND
4430 : NS_STYLE_TABLE_EMPTY_CELLS_SHOW
,
4433 COMPUTE_END_INHERITED(TableBorder
, table
)
4437 nsRuleNode::ComputeContentData(void* aStartStruct
,
4438 const nsRuleDataStruct
& aData
,
4439 nsStyleContext
* aContext
,
4440 nsRuleNode
* aHighestNode
,
4441 const RuleDetail aRuleDetail
, PRBool aInherited
)
4443 COMPUTE_START_RESET(Content
, (), content
, parentContent
,
4444 Content
, contentData
)
4446 // content: [string, url, counter, attr, enum]+, normal, none, inherit
4448 nsAutoString buffer
;
4449 nsCSSValueList
* contentValue
= contentData
.mContent
;
4451 if (eCSSUnit_Normal
== contentValue
->mValue
.GetUnit() ||
4452 eCSSUnit_None
== contentValue
->mValue
.GetUnit() ||
4453 eCSSUnit_Initial
== contentValue
->mValue
.GetUnit()) {
4454 // "normal", "none", and "initial" all mean no content
4455 content
->AllocateContents(0);
4457 else if (eCSSUnit_Inherit
== contentValue
->mValue
.GetUnit()) {
4458 inherited
= PR_TRUE
;
4459 count
= parentContent
->ContentCount();
4460 if (NS_SUCCEEDED(content
->AllocateContents(count
))) {
4461 while (0 < count
--) {
4462 content
->ContentAt(count
) = parentContent
->ContentAt(count
);
4468 while (contentValue
) {
4470 contentValue
= contentValue
->mNext
;
4472 if (NS_SUCCEEDED(content
->AllocateContents(count
))) {
4473 const nsAutoString nullStr
;
4475 contentValue
= contentData
.mContent
;
4476 while (contentValue
) {
4477 const nsCSSValue
& value
= contentValue
->mValue
;
4478 nsCSSUnit unit
= value
.GetUnit();
4479 nsStyleContentType type
;
4480 nsStyleContentData
&data
= content
->ContentAt(count
++);
4482 case eCSSUnit_String
: type
= eStyleContentType_String
; break;
4483 case eCSSUnit_Image
: type
= eStyleContentType_Image
; break;
4484 case eCSSUnit_Attr
: type
= eStyleContentType_Attr
; break;
4485 case eCSSUnit_Counter
: type
= eStyleContentType_Counter
; break;
4486 case eCSSUnit_Counters
: type
= eStyleContentType_Counters
; break;
4487 case eCSSUnit_Enumerated
:
4488 switch (value
.GetIntValue()) {
4489 case NS_STYLE_CONTENT_OPEN_QUOTE
:
4490 type
= eStyleContentType_OpenQuote
; break;
4491 case NS_STYLE_CONTENT_CLOSE_QUOTE
:
4492 type
= eStyleContentType_CloseQuote
; break;
4493 case NS_STYLE_CONTENT_NO_OPEN_QUOTE
:
4494 type
= eStyleContentType_NoOpenQuote
; break;
4495 case NS_STYLE_CONTENT_NO_CLOSE_QUOTE
:
4496 type
= eStyleContentType_NoCloseQuote
; break;
4497 case NS_STYLE_CONTENT_ALT_CONTENT
:
4498 type
= eStyleContentType_AltContent
; break;
4500 NS_ERROR("bad content value");
4504 NS_ERROR("bad content type");
4507 if (type
== eStyleContentType_Image
) {
4508 data
.mContent
.mImage
= value
.GetImageValue();
4509 NS_IF_ADDREF(data
.mContent
.mImage
);
4511 else if (type
<= eStyleContentType_Attr
) {
4512 value
.GetStringValue(buffer
);
4514 data
.mContent
.mString
= NS_strdup(buffer
.get());
4516 else if (type
<= eStyleContentType_Counters
) {
4517 data
.mContent
.mCounters
= value
.GetArrayValue();
4518 data
.mContent
.mCounters
->AddRef();
4521 data
.mContent
.mString
= nsnull
;
4523 contentValue
= contentValue
->mNext
;
4529 // counter-increment: [string [int]]+, none, inherit
4530 nsCSSValuePairList
* ourIncrement
= contentData
.mCounterIncrement
;
4532 if (eCSSUnit_None
== ourIncrement
->mXValue
.GetUnit() ||
4533 eCSSUnit_Initial
== ourIncrement
->mXValue
.GetUnit()) {
4534 content
->AllocateCounterIncrements(0);
4536 else if (eCSSUnit_Inherit
== ourIncrement
->mXValue
.GetUnit()) {
4537 inherited
= PR_TRUE
;
4538 count
= parentContent
->CounterIncrementCount();
4539 if (NS_SUCCEEDED(content
->AllocateCounterIncrements(count
))) {
4540 while (0 < count
--) {
4541 const nsStyleCounterData
*data
=
4542 parentContent
->GetCounterIncrementAt(count
);
4543 content
->SetCounterIncrementAt(count
, data
->mCounter
, data
->mValue
);
4547 else if (eCSSUnit_String
== ourIncrement
->mXValue
.GetUnit()) {
4549 while (ourIncrement
) {
4551 ourIncrement
= ourIncrement
->mNext
;
4553 if (NS_SUCCEEDED(content
->AllocateCounterIncrements(count
))) {
4555 ourIncrement
= contentData
.mCounterIncrement
;
4556 while (ourIncrement
) {
4558 if (eCSSUnit_Integer
== ourIncrement
->mYValue
.GetUnit()) {
4559 increment
= ourIncrement
->mYValue
.GetIntValue();
4564 ourIncrement
->mXValue
.GetStringValue(buffer
);
4565 content
->SetCounterIncrementAt(count
++, buffer
, increment
);
4566 ourIncrement
= ourIncrement
->mNext
;
4572 // counter-reset: [string [int]]+, none, inherit
4573 nsCSSValuePairList
* ourReset
= contentData
.mCounterReset
;
4575 if (eCSSUnit_None
== ourReset
->mXValue
.GetUnit() ||
4576 eCSSUnit_Initial
== ourReset
->mXValue
.GetUnit()) {
4577 content
->AllocateCounterResets(0);
4579 else if (eCSSUnit_Inherit
== ourReset
->mXValue
.GetUnit()) {
4580 inherited
= PR_TRUE
;
4581 count
= parentContent
->CounterResetCount();
4582 if (NS_SUCCEEDED(content
->AllocateCounterResets(count
))) {
4583 while (0 < count
--) {
4584 const nsStyleCounterData
*data
=
4585 parentContent
->GetCounterResetAt(count
);
4586 content
->SetCounterResetAt(count
, data
->mCounter
, data
->mValue
);
4590 else if (eCSSUnit_String
== ourReset
->mXValue
.GetUnit()) {
4594 ourReset
= ourReset
->mNext
;
4596 if (NS_SUCCEEDED(content
->AllocateCounterResets(count
))) {
4598 ourReset
= contentData
.mCounterReset
;
4601 if (eCSSUnit_Integer
== ourReset
->mYValue
.GetUnit()) {
4602 reset
= ourReset
->mYValue
.GetIntValue();
4607 ourReset
->mXValue
.GetStringValue(buffer
);
4608 content
->SetCounterResetAt(count
++, buffer
, reset
);
4609 ourReset
= ourReset
->mNext
;
4615 // marker-offset: length, auto, inherit
4616 SetCoord(contentData
.mMarkerOffset
, content
->mMarkerOffset
, parentContent
->mMarkerOffset
,
4617 SETCOORD_LH
| SETCOORD_AUTO
| SETCOORD_INITIAL_AUTO
, aContext
,
4618 mPresContext
, inherited
);
4620 COMPUTE_END_RESET(Content
, content
)
4624 nsRuleNode::ComputeQuotesData(void* aStartStruct
,
4625 const nsRuleDataStruct
& aData
,
4626 nsStyleContext
* aContext
,
4627 nsRuleNode
* aHighestNode
,
4628 const RuleDetail aRuleDetail
, PRBool aInherited
)
4630 COMPUTE_START_INHERITED(Quotes
, (), quotes
, parentQuotes
,
4631 Content
, contentData
)
4633 // quotes: inherit, initial, none, [string string]+
4634 nsCSSValuePairList
* ourQuotes
= contentData
.mQuotes
;
4636 if (eCSSUnit_Inherit
== ourQuotes
->mXValue
.GetUnit()) {
4637 inherited
= PR_TRUE
;
4638 quotes
->CopyFrom(*parentQuotes
);
4640 else if (eCSSUnit_Initial
== ourQuotes
->mXValue
.GetUnit()) {
4641 quotes
->SetInitial();
4643 else if (eCSSUnit_None
== ourQuotes
->mXValue
.GetUnit()) {
4644 quotes
->AllocateQuotes(0);
4646 else if (eCSSUnit_String
== ourQuotes
->mXValue
.GetUnit()) {
4647 nsAutoString buffer
;
4648 nsAutoString closeBuffer
;
4653 ourQuotes
= ourQuotes
->mNext
;
4655 if (NS_SUCCEEDED(quotes
->AllocateQuotes(count
))) {
4657 ourQuotes
= contentData
.mQuotes
;
4659 ourQuotes
->mXValue
.GetStringValue(buffer
);
4660 ourQuotes
->mYValue
.GetStringValue(closeBuffer
);
4662 Unquote(closeBuffer
);
4663 quotes
->SetQuotesAt(count
++, buffer
, closeBuffer
);
4664 ourQuotes
= ourQuotes
->mNext
;
4670 COMPUTE_END_INHERITED(Quotes
, quotes
)
4674 nsRuleNode::ComputeXULData(void* aStartStruct
,
4675 const nsRuleDataStruct
& aData
,
4676 nsStyleContext
* aContext
,
4677 nsRuleNode
* aHighestNode
,
4678 const RuleDetail aRuleDetail
, PRBool aInherited
)
4680 COMPUTE_START_RESET(XUL
, (), xul
, parentXUL
, XUL
, xulData
)
4682 // box-align: enum, inherit, initial
4683 SetDiscrete(xulData
.mBoxAlign
, xul
->mBoxAlign
, inherited
,
4684 SETDSC_ENUMERATED
, parentXUL
->mBoxAlign
,
4685 NS_STYLE_BOX_ALIGN_STRETCH
, 0, 0, 0, 0);
4687 // box-direction: enum, inherit, initial
4688 SetDiscrete(xulData
.mBoxDirection
, xul
->mBoxDirection
, inherited
,
4689 SETDSC_ENUMERATED
, parentXUL
->mBoxDirection
,
4690 NS_STYLE_BOX_DIRECTION_NORMAL
, 0, 0, 0, 0);
4692 // box-flex: factor, inherit
4693 SetFactor(xulData
.mBoxFlex
, xul
->mBoxFlex
, inherited
,
4694 parentXUL
->mBoxFlex
, 0.0f
);
4696 // box-orient: enum, inherit, initial
4697 SetDiscrete(xulData
.mBoxOrient
, xul
->mBoxOrient
, inherited
,
4698 SETDSC_ENUMERATED
, parentXUL
->mBoxOrient
,
4699 NS_STYLE_BOX_ORIENT_HORIZONTAL
, 0, 0, 0, 0);
4701 // box-pack: enum, inherit, initial
4702 SetDiscrete(xulData
.mBoxPack
, xul
->mBoxPack
, inherited
,
4703 SETDSC_ENUMERATED
, parentXUL
->mBoxPack
,
4704 NS_STYLE_BOX_PACK_START
, 0, 0, 0, 0);
4706 // box-ordinal-group: integer, inherit, initial
4707 SetDiscrete(xulData
.mBoxOrdinal
, xul
->mBoxOrdinal
, inherited
,
4708 SETDSC_INTEGER
, parentXUL
->mBoxOrdinal
, 1,
4711 if (eCSSUnit_Inherit
== xulData
.mStackSizing
.GetUnit()) {
4712 inherited
= PR_TRUE
;
4713 xul
->mStretchStack
= parentXUL
->mStretchStack
;
4714 } else if (eCSSUnit_Initial
== xulData
.mStackSizing
.GetUnit()) {
4715 xul
->mStretchStack
= PR_TRUE
;
4716 } else if (eCSSUnit_Enumerated
== xulData
.mStackSizing
.GetUnit()) {
4717 xul
->mStretchStack
= xulData
.mStackSizing
.GetIntValue() ==
4718 NS_STYLE_STACK_SIZING_STRETCH_TO_FIT
;
4721 COMPUTE_END_RESET(XUL
, xul
)
4725 nsRuleNode::ComputeColumnData(void* aStartStruct
,
4726 const nsRuleDataStruct
& aData
,
4727 nsStyleContext
* aContext
,
4728 nsRuleNode
* aHighestNode
,
4729 const RuleDetail aRuleDetail
, PRBool aInherited
)
4731 COMPUTE_START_RESET(Column
, (mPresContext
), column
, parent
, Column
, columnData
)
4733 // column-width: length, auto, inherit
4734 SetCoord(columnData
.mColumnWidth
,
4735 column
->mColumnWidth
, parent
->mColumnWidth
,
4736 SETCOORD_LAH
| SETCOORD_INITIAL_AUTO
,
4737 aContext
, mPresContext
, inherited
);
4739 // column-gap: length, percentage, inherit, normal
4740 SetCoord(columnData
.mColumnGap
,
4741 column
->mColumnGap
, parent
->mColumnGap
,
4742 SETCOORD_LPH
| SETCOORD_NORMAL
| SETCOORD_INITIAL_NORMAL
,
4743 aContext
, mPresContext
, inherited
);
4745 // column-count: auto, integer, inherit
4746 if (eCSSUnit_Auto
== columnData
.mColumnCount
.GetUnit() ||
4747 eCSSUnit_Initial
== columnData
.mColumnCount
.GetUnit()) {
4748 column
->mColumnCount
= NS_STYLE_COLUMN_COUNT_AUTO
;
4749 } else if (eCSSUnit_Integer
== columnData
.mColumnCount
.GetUnit()) {
4750 column
->mColumnCount
= columnData
.mColumnCount
.GetIntValue();
4751 // Max 1000 columns - wallpaper for bug 345583.
4752 column
->mColumnCount
= PR_MIN(column
->mColumnCount
, 1000);
4753 } else if (eCSSUnit_Inherit
== columnData
.mColumnCount
.GetUnit()) {
4754 inherited
= PR_TRUE
;
4755 column
->mColumnCount
= parent
->mColumnCount
;
4758 // column-rule-width: length, enum, inherit
4759 const nsCSSValue
& widthValue
= columnData
.mColumnRuleWidth
;
4760 if (eCSSUnit_Initial
== widthValue
.GetUnit()) {
4761 column
->SetColumnRuleWidth(
4762 (mPresContext
->GetBorderWidthTable())[NS_STYLE_BORDER_WIDTH_MEDIUM
]);
4764 else if (eCSSUnit_Enumerated
== widthValue
.GetUnit()) {
4765 NS_ASSERTION(widthValue
.GetIntValue() == NS_STYLE_BORDER_WIDTH_THIN
||
4766 widthValue
.GetIntValue() == NS_STYLE_BORDER_WIDTH_MEDIUM
||
4767 widthValue
.GetIntValue() == NS_STYLE_BORDER_WIDTH_THICK
,
4768 "Unexpected enum value");
4769 column
->SetColumnRuleWidth(
4770 (mPresContext
->GetBorderWidthTable())[widthValue
.GetIntValue()]);
4772 else if (eCSSUnit_Inherit
== widthValue
.GetUnit()) {
4773 column
->SetColumnRuleWidth(parent
->GetComputedColumnRuleWidth());
4774 inherited
= PR_TRUE
;
4776 else if (widthValue
.IsLengthUnit()) {
4777 column
->SetColumnRuleWidth(CalcLength(widthValue
, aContext
,
4778 mPresContext
, inherited
));
4781 // column-rule-style: enum, none, inherit
4782 const nsCSSValue
& styleValue
= columnData
.mColumnRuleStyle
;
4783 if (eCSSUnit_Enumerated
== styleValue
.GetUnit()) {
4784 column
->mColumnRuleStyle
= styleValue
.GetIntValue();
4786 else if (eCSSUnit_None
== styleValue
.GetUnit() ||
4787 eCSSUnit_Initial
== styleValue
.GetUnit()) {
4788 column
->mColumnRuleStyle
= NS_STYLE_BORDER_STYLE_NONE
;
4790 else if (eCSSUnit_Inherit
== styleValue
.GetUnit()) {
4791 inherited
= PR_TRUE
;
4792 column
->mColumnRuleStyle
= parent
->mColumnRuleStyle
;
4795 // column-rule-color: color, inherit
4796 const nsCSSValue
& colorValue
= columnData
.mColumnRuleColor
;
4797 if (eCSSUnit_Inherit
== colorValue
.GetUnit()) {
4798 inherited
= PR_TRUE
;
4799 column
->mColumnRuleColorIsForeground
= PR_FALSE
;
4800 if (parent
->mColumnRuleColorIsForeground
) {
4801 column
->mColumnRuleColor
= parentContext
->GetStyleColor()->mColor
;
4803 column
->mColumnRuleColor
= parent
->mColumnRuleColor
;
4806 else if (eCSSUnit_Initial
== colorValue
.GetUnit()) {
4807 column
->mColumnRuleColorIsForeground
= PR_TRUE
;
4809 else if (SetColor(colorValue
, 0, mPresContext
, aContext
, column
->mColumnRuleColor
, inherited
)) {
4810 column
->mColumnRuleColorIsForeground
= PR_FALSE
;
4813 COMPUTE_END_RESET(Column
, column
)
4818 SetSVGPaint(const nsCSSValuePair
& aValue
, const nsStyleSVGPaint
& parentPaint
,
4819 nsPresContext
* aPresContext
, nsStyleContext
*aContext
,
4820 nsStyleSVGPaint
& aResult
, nsStyleSVGPaintType aInitialPaintType
,
4825 if (aValue
.mXValue
.GetUnit() == eCSSUnit_Inherit
) {
4826 aResult
= parentPaint
;
4827 aInherited
= PR_TRUE
;
4828 } else if (aValue
.mXValue
.GetUnit() == eCSSUnit_None
) {
4829 aResult
.SetType(eStyleSVGPaintType_None
);
4830 } else if (aValue
.mXValue
.GetUnit() == eCSSUnit_Initial
) {
4831 aResult
.SetType(aInitialPaintType
);
4832 aResult
.mPaint
.mColor
= NS_RGB(0, 0, 0);
4833 aResult
.mFallbackColor
= NS_RGB(0, 0, 0);
4834 } else if (aValue
.mXValue
.GetUnit() == eCSSUnit_URL
) {
4835 aResult
.SetType(eStyleSVGPaintType_Server
);
4836 aResult
.mPaint
.mPaintServer
= aValue
.mXValue
.GetURLValue();
4837 NS_IF_ADDREF(aResult
.mPaint
.mPaintServer
);
4838 if (aValue
.mYValue
.GetUnit() == eCSSUnit_None
) {
4839 aResult
.mFallbackColor
= NS_RGBA(0, 0, 0, 0);
4841 NS_ASSERTION(aValue
.mYValue
.GetUnit() != eCSSUnit_Inherit
, "cannot inherit fallback colour");
4842 SetColor(aValue
.mYValue
, NS_RGB(0, 0, 0), aPresContext
, aContext
, aResult
.mFallbackColor
, aInherited
);
4844 } else if (SetColor(aValue
.mXValue
, parentPaint
.mPaint
.mColor
, aPresContext
, aContext
, color
, aInherited
)) {
4845 aResult
.SetType(eStyleSVGPaintType_Color
);
4846 aResult
.mPaint
.mColor
= color
;
4851 nsRuleNode::ComputeSVGData(void* aStartStruct
,
4852 const nsRuleDataStruct
& aData
,
4853 nsStyleContext
* aContext
,
4854 nsRuleNode
* aHighestNode
,
4855 const RuleDetail aRuleDetail
, PRBool aInherited
)
4857 COMPUTE_START_INHERITED(SVG
, (), svg
, parentSVG
, SVG
, SVGData
)
4859 // clip-rule: enum, inherit, initial
4860 SetDiscrete(SVGData
.mClipRule
, svg
->mClipRule
, inherited
,
4861 SETDSC_ENUMERATED
, parentSVG
->mClipRule
,
4862 NS_STYLE_FILL_RULE_NONZERO
, 0, 0, 0, 0);
4864 // color-interpolation: enum, auto, inherit, initial
4865 SetDiscrete(SVGData
.mColorInterpolation
, svg
->mColorInterpolation
, inherited
,
4866 SETDSC_ENUMERATED
| SETDSC_AUTO
,
4867 parentSVG
->mColorInterpolation
,
4868 NS_STYLE_COLOR_INTERPOLATION_SRGB
,
4869 NS_STYLE_COLOR_INTERPOLATION_AUTO
, 0, 0, 0);
4871 // color-interpolation-filters: enum, auto, inherit, initial
4872 SetDiscrete(SVGData
.mColorInterpolationFilters
,
4873 svg
->mColorInterpolationFilters
, inherited
,
4874 SETDSC_ENUMERATED
| SETDSC_AUTO
,
4875 parentSVG
->mColorInterpolationFilters
,
4876 NS_STYLE_COLOR_INTERPOLATION_LINEARRGB
,
4877 NS_STYLE_COLOR_INTERPOLATION_AUTO
, 0, 0, 0);
4880 SetSVGPaint(SVGData
.mFill
, parentSVG
->mFill
, mPresContext
, aContext
,
4881 svg
->mFill
, eStyleSVGPaintType_Color
, inherited
);
4883 // fill-opacity: factor, inherit, initial
4884 SetFactor(SVGData
.mFillOpacity
, svg
->mFillOpacity
, inherited
,
4885 parentSVG
->mFillOpacity
, 1.0f
, SETFCT_OPACITY
);
4887 // fill-rule: enum, inherit, initial
4888 SetDiscrete(SVGData
.mFillRule
, svg
->mFillRule
, inherited
,
4889 SETDSC_ENUMERATED
, parentSVG
->mFillRule
,
4890 NS_STYLE_FILL_RULE_NONZERO
, 0, 0, 0, 0);
4892 // marker-end: url, none, inherit
4893 if (eCSSUnit_URL
== SVGData
.mMarkerEnd
.GetUnit()) {
4894 svg
->mMarkerEnd
= SVGData
.mMarkerEnd
.GetURLValue();
4895 } else if (eCSSUnit_None
== SVGData
.mMarkerEnd
.GetUnit() ||
4896 eCSSUnit_Initial
== SVGData
.mMarkerEnd
.GetUnit()) {
4897 svg
->mMarkerEnd
= nsnull
;
4898 } else if (eCSSUnit_Inherit
== SVGData
.mMarkerEnd
.GetUnit()) {
4899 inherited
= PR_TRUE
;
4900 svg
->mMarkerEnd
= parentSVG
->mMarkerEnd
;
4903 // marker-mid: url, none, inherit
4904 if (eCSSUnit_URL
== SVGData
.mMarkerMid
.GetUnit()) {
4905 svg
->mMarkerMid
= SVGData
.mMarkerMid
.GetURLValue();
4906 } else if (eCSSUnit_None
== SVGData
.mMarkerMid
.GetUnit() ||
4907 eCSSUnit_Initial
== SVGData
.mMarkerMid
.GetUnit()) {
4908 svg
->mMarkerMid
= nsnull
;
4909 } else if (eCSSUnit_Inherit
== SVGData
.mMarkerMid
.GetUnit()) {
4910 inherited
= PR_TRUE
;
4911 svg
->mMarkerMid
= parentSVG
->mMarkerMid
;
4914 // marker-start: url, none, inherit
4915 if (eCSSUnit_URL
== SVGData
.mMarkerStart
.GetUnit()) {
4916 svg
->mMarkerStart
= SVGData
.mMarkerStart
.GetURLValue();
4917 } else if (eCSSUnit_None
== SVGData
.mMarkerStart
.GetUnit() ||
4918 eCSSUnit_Initial
== SVGData
.mMarkerStart
.GetUnit()) {
4919 svg
->mMarkerStart
= nsnull
;
4920 } else if (eCSSUnit_Inherit
== SVGData
.mMarkerStart
.GetUnit()) {
4921 inherited
= PR_TRUE
;
4922 svg
->mMarkerStart
= parentSVG
->mMarkerStart
;
4925 // pointer-events: enum, none, inherit, initial
4926 SetDiscrete(SVGData
.mPointerEvents
, svg
->mPointerEvents
, inherited
,
4927 SETDSC_ENUMERATED
| SETDSC_NONE
, parentSVG
->mPointerEvents
,
4928 NS_STYLE_POINTER_EVENTS_VISIBLEPAINTED
, 0,
4929 NS_STYLE_POINTER_EVENTS_NONE
, 0, 0);
4931 // shape-rendering: enum, auto, inherit
4932 SetDiscrete(SVGData
.mShapeRendering
, svg
->mShapeRendering
, inherited
,
4933 SETDSC_ENUMERATED
| SETDSC_AUTO
,
4934 parentSVG
->mShapeRendering
,
4935 NS_STYLE_SHAPE_RENDERING_AUTO
,
4936 NS_STYLE_SHAPE_RENDERING_AUTO
, 0, 0, 0);
4939 SetSVGPaint(SVGData
.mStroke
, parentSVG
->mStroke
, mPresContext
, aContext
,
4940 svg
->mStroke
, eStyleSVGPaintType_None
, inherited
);
4942 // stroke-dasharray: <dasharray>, none, inherit
4943 nsCSSValueList
*list
= SVGData
.mStrokeDasharray
;
4945 if (eCSSUnit_Inherit
== list
->mValue
.GetUnit()) {
4946 // only do the copy if weren't already set up by the copy constructor
4947 // FIXME Bug 389408: This is broken when aStartStruct is non-null!
4948 if (!svg
->mStrokeDasharray
) {
4949 inherited
= PR_TRUE
;
4950 svg
->mStrokeDasharrayLength
= parentSVG
->mStrokeDasharrayLength
;
4951 if (svg
->mStrokeDasharrayLength
) {
4952 svg
->mStrokeDasharray
= new nsStyleCoord
[svg
->mStrokeDasharrayLength
];
4953 if (svg
->mStrokeDasharray
)
4954 memcpy(svg
->mStrokeDasharray
,
4955 parentSVG
->mStrokeDasharray
,
4956 svg
->mStrokeDasharrayLength
* sizeof(nsStyleCoord
));
4958 svg
->mStrokeDasharrayLength
= 0;
4962 delete [] svg
->mStrokeDasharray
;
4963 svg
->mStrokeDasharray
= nsnull
;
4964 svg
->mStrokeDasharrayLength
= 0;
4966 if (eCSSUnit_Initial
!= list
->mValue
.GetUnit() &&
4967 eCSSUnit_None
!= list
->mValue
.GetUnit()) {
4968 // count number of values
4969 nsCSSValueList
*value
= SVGData
.mStrokeDasharray
;
4970 while (nsnull
!= value
) {
4971 ++svg
->mStrokeDasharrayLength
;
4972 value
= value
->mNext
;
4975 NS_ASSERTION(svg
->mStrokeDasharrayLength
!= 0, "no dasharray items");
4977 svg
->mStrokeDasharray
= new nsStyleCoord
[svg
->mStrokeDasharrayLength
];
4979 if (svg
->mStrokeDasharray
) {
4980 value
= SVGData
.mStrokeDasharray
;
4982 while (nsnull
!= value
) {
4983 SetCoord(value
->mValue
,
4984 svg
->mStrokeDasharray
[i
++], nsnull
,
4985 SETCOORD_LP
| SETCOORD_FACTOR
,
4986 aContext
, mPresContext
, inherited
);
4987 value
= value
->mNext
;
4990 svg
->mStrokeDasharrayLength
= 0;
4995 // stroke-dashoffset: <dashoffset>, inherit
4996 SetCoord(SVGData
.mStrokeDashoffset
,
4997 svg
->mStrokeDashoffset
, parentSVG
->mStrokeDashoffset
,
4998 SETCOORD_LPH
| SETCOORD_FACTOR
| SETCOORD_INITIAL_ZERO
,
4999 aContext
, mPresContext
, inherited
);
5001 // stroke-linecap: enum, inherit, initial
5002 SetDiscrete(SVGData
.mStrokeLinecap
, svg
->mStrokeLinecap
, inherited
,
5003 SETDSC_ENUMERATED
, parentSVG
->mStrokeLinecap
,
5004 NS_STYLE_STROKE_LINECAP_BUTT
, 0, 0, 0, 0);
5006 // stroke-linejoin: enum, inherit, initial
5007 SetDiscrete(SVGData
.mStrokeLinejoin
, svg
->mStrokeLinejoin
, inherited
,
5008 SETDSC_ENUMERATED
, parentSVG
->mStrokeLinejoin
,
5009 NS_STYLE_STROKE_LINEJOIN_MITER
, 0, 0, 0, 0);
5011 // stroke-miterlimit: <miterlimit>, inherit
5012 SetFactor(SVGData
.mStrokeMiterlimit
, svg
->mStrokeMiterlimit
, inherited
,
5013 parentSVG
->mStrokeMiterlimit
, 4.0f
);
5016 SetFactor(SVGData
.mStrokeOpacity
, svg
->mStrokeOpacity
, inherited
,
5017 parentSVG
->mStrokeOpacity
, 1.0f
, SETFCT_OPACITY
);
5020 if (eCSSUnit_Initial
== SVGData
.mStrokeWidth
.GetUnit()) {
5021 svg
->mStrokeWidth
.SetCoordValue(nsPresContext::CSSPixelsToAppUnits(1));
5023 SetCoord(SVGData
.mStrokeWidth
,
5024 svg
->mStrokeWidth
, parentSVG
->mStrokeWidth
,
5025 SETCOORD_LPH
| SETCOORD_FACTOR
,
5026 aContext
, mPresContext
, inherited
);
5029 // text-anchor: enum, inherit, initial
5030 SetDiscrete(SVGData
.mTextAnchor
, svg
->mTextAnchor
, inherited
,
5031 SETDSC_ENUMERATED
, parentSVG
->mTextAnchor
,
5032 NS_STYLE_TEXT_ANCHOR_START
, 0, 0, 0, 0);
5034 // text-rendering: enum, auto, inherit, initial
5035 SetDiscrete(SVGData
.mTextRendering
, svg
->mTextRendering
, inherited
,
5036 SETDSC_ENUMERATED
| SETDSC_AUTO
,
5037 parentSVG
->mTextRendering
,
5038 NS_STYLE_TEXT_RENDERING_AUTO
,
5039 NS_STYLE_TEXT_RENDERING_AUTO
, 0, 0, 0);
5041 COMPUTE_END_INHERITED(SVG
, svg
)
5045 nsRuleNode::ComputeSVGResetData(void* aStartStruct
,
5046 const nsRuleDataStruct
& aData
,
5047 nsStyleContext
* aContext
,
5048 nsRuleNode
* aHighestNode
,
5049 const RuleDetail aRuleDetail
, PRBool aInherited
)
5051 COMPUTE_START_RESET(SVGReset
, (), svgReset
, parentSVGReset
, SVG
, SVGData
)
5054 if (eCSSUnit_Initial
== SVGData
.mStopColor
.GetUnit()) {
5055 svgReset
->mStopColor
= NS_RGB(0, 0, 0);
5057 SetColor(SVGData
.mStopColor
, parentSVGReset
->mStopColor
,
5058 mPresContext
, aContext
, svgReset
->mStopColor
, inherited
);
5062 if (eCSSUnit_Initial
== SVGData
.mFloodColor
.GetUnit()) {
5063 svgReset
->mFloodColor
= NS_RGB(0, 0, 0);
5065 SetColor(SVGData
.mFloodColor
, parentSVGReset
->mFloodColor
,
5066 mPresContext
, aContext
, svgReset
->mFloodColor
, inherited
);
5070 if (eCSSUnit_Initial
== SVGData
.mLightingColor
.GetUnit()) {
5071 svgReset
->mLightingColor
= NS_RGB(255, 255, 255);
5073 SetColor(SVGData
.mLightingColor
, parentSVGReset
->mLightingColor
,
5074 mPresContext
, aContext
, svgReset
->mLightingColor
, inherited
);
5077 // clip-path: url, none, inherit
5078 if (eCSSUnit_URL
== SVGData
.mClipPath
.GetUnit()) {
5079 svgReset
->mClipPath
= SVGData
.mClipPath
.GetURLValue();
5080 } else if (eCSSUnit_None
== SVGData
.mClipPath
.GetUnit() ||
5081 eCSSUnit_Initial
== SVGData
.mClipPath
.GetUnit()) {
5082 svgReset
->mClipPath
= nsnull
;
5083 } else if (eCSSUnit_Inherit
== SVGData
.mClipPath
.GetUnit()) {
5084 inherited
= PR_TRUE
;
5085 svgReset
->mClipPath
= parentSVGReset
->mClipPath
;
5089 SetFactor(SVGData
.mStopOpacity
, svgReset
->mStopOpacity
, inherited
,
5090 parentSVGReset
->mStopOpacity
, 1.0f
, SETFCT_OPACITY
);
5093 SetFactor(SVGData
.mFloodOpacity
, svgReset
->mFloodOpacity
, inherited
,
5094 parentSVGReset
->mFloodOpacity
, 1.0f
, SETFCT_OPACITY
);
5096 // dominant-baseline: enum, auto, inherit, initial
5097 SetDiscrete(SVGData
.mDominantBaseline
, svgReset
->mDominantBaseline
,
5099 SETDSC_ENUMERATED
| SETDSC_AUTO
,
5100 parentSVGReset
->mDominantBaseline
,
5101 NS_STYLE_DOMINANT_BASELINE_AUTO
,
5102 NS_STYLE_DOMINANT_BASELINE_AUTO
, 0, 0, 0);
5104 // filter: url, none, inherit
5105 if (eCSSUnit_URL
== SVGData
.mFilter
.GetUnit()) {
5106 svgReset
->mFilter
= SVGData
.mFilter
.GetURLValue();
5107 } else if (eCSSUnit_None
== SVGData
.mFilter
.GetUnit() ||
5108 eCSSUnit_Initial
== SVGData
.mFilter
.GetUnit()) {
5109 svgReset
->mFilter
= nsnull
;
5110 } else if (eCSSUnit_Inherit
== SVGData
.mFilter
.GetUnit()) {
5111 inherited
= PR_TRUE
;
5112 svgReset
->mFilter
= parentSVGReset
->mFilter
;
5115 // mask: url, none, inherit
5116 if (eCSSUnit_URL
== SVGData
.mMask
.GetUnit()) {
5117 svgReset
->mMask
= SVGData
.mMask
.GetURLValue();
5118 } else if (eCSSUnit_None
== SVGData
.mMask
.GetUnit() ||
5119 eCSSUnit_Initial
== SVGData
.mMask
.GetUnit()) {
5120 svgReset
->mMask
= nsnull
;
5121 } else if (eCSSUnit_Inherit
== SVGData
.mMask
.GetUnit()) {
5122 inherited
= PR_TRUE
;
5123 svgReset
->mMask
= parentSVGReset
->mMask
;
5126 COMPUTE_END_RESET(SVGReset
, svgReset
)
5131 nsRuleNode::GetParentData(const nsStyleStructID aSID
)
5133 NS_PRECONDITION(mDependentBits
& nsCachedStyleData::GetBitForSID(aSID
),
5134 "should be called when node depends on parent data");
5135 NS_ASSERTION(mStyleData
.GetStyleData(aSID
) == nsnull
,
5136 "both struct and dependent bits present");
5137 // Walk up the rule tree from this rule node (towards less specific
5139 PRUint32 bit
= nsCachedStyleData::GetBitForSID(aSID
);
5140 nsRuleNode
*ruleNode
= mParent
;
5141 while (ruleNode
->mDependentBits
& bit
) {
5142 NS_ASSERTION(ruleNode
->mStyleData
.GetStyleData(aSID
) == nsnull
,
5143 "both struct and dependent bits present");
5144 ruleNode
= ruleNode
->mParent
;
5147 return ruleNode
->mStyleData
.GetStyleData(aSID
);
5150 #define STYLE_STRUCT(name_, checkdata_cb_, ctor_args_) \
5151 inline const nsStyle##name_ * \
5152 nsRuleNode::GetParent##name_() \
5154 NS_PRECONDITION(mDependentBits & \
5155 nsCachedStyleData::GetBitForSID(eStyleStruct_##name_), \
5156 "should be called when node depends on parent data"); \
5157 NS_ASSERTION(mStyleData.GetStyle##name_() == nsnull, \
5158 "both struct and dependent bits present"); \
5159 /* Walk up the rule tree from this rule node (towards less specific */ \
5161 PRUint32 bit = nsCachedStyleData::GetBitForSID(eStyleStruct_##name_); \
5162 nsRuleNode *ruleNode = mParent; \
5163 while (ruleNode->mDependentBits & bit) { \
5164 NS_ASSERTION(ruleNode->mStyleData.GetStyle##name_() == nsnull, \
5165 "both struct and dependent bits present"); \
5166 ruleNode = ruleNode->mParent; \
5169 return ruleNode->mStyleData.GetStyle##name_(); \
5171 #include "nsStyleStructList.h"
5175 nsRuleNode::GetStyleData(nsStyleStructID aSID
,
5176 nsStyleContext
* aContext
,
5177 PRBool aComputeData
)
5180 if (mDependentBits
& nsCachedStyleData::GetBitForSID(aSID
)) {
5181 // We depend on an ancestor for this struct since the cached struct
5182 // it has is also appropriate for this rule node. Just go up the
5183 // rule tree and return the first cached struct we find.
5184 data
= GetParentData(aSID
);
5185 NS_ASSERTION(data
, "dependent bits set but no cached struct present");
5189 data
= mStyleData
.GetStyleData(aSID
);
5190 if (NS_LIKELY(data
!= nsnull
))
5191 return data
; // We have a fully specified struct. Just return it.
5193 if (NS_UNLIKELY(!aComputeData
))
5196 // Nothing is cached. We'll have to delve further and examine our rules.
5197 #define STYLE_STRUCT_TEST aSID
5198 #define STYLE_STRUCT(name, checkdata_cb, ctor_args) \
5199 data = Get##name##Data(aContext);
5200 #include "nsStyleStructList.h"
5202 #undef STYLE_STRUCT_TEST
5204 if (NS_LIKELY(data
!= nsnull
))
5207 NS_NOTREACHED("could not create style struct");
5208 // To ensure that |GetStyleData| never returns null (even when we're
5209 // out of memory), we'll get the style set and get a copy of the
5210 // default values for the given style struct from the set. Note that
5211 // this works fine even if |this| is a rule node that has been
5212 // destroyed (leftover from a previous rule tree) but is somehow still
5214 return mPresContext
->PresShell()->StyleSet()->
5215 DefaultStyleData()->GetStyleData(aSID
);
5218 // See comments above in GetStyleData for an explanation of what the
5220 #define STYLE_STRUCT(name_, checkdata_cb_, ctor_args_) \
5221 const nsStyle##name_* \
5222 nsRuleNode::GetStyle##name_(nsStyleContext* aContext, PRBool aComputeData) \
5224 const nsStyle##name_ *data; \
5225 if (mDependentBits & \
5226 nsCachedStyleData::GetBitForSID(eStyleStruct_##name_)) { \
5227 data = GetParent##name_(); \
5228 NS_ASSERTION(data, "dependent bits set but no cached struct present"); \
5232 data = mStyleData.GetStyle##name_(); \
5233 if (NS_LIKELY(data != nsnull)) \
5236 if (NS_UNLIKELY(!aComputeData)) \
5240 static_cast<const nsStyle##name_ *>(Get##name_##Data(aContext)); \
5242 if (NS_LIKELY(data != nsnull)) \
5245 NS_NOTREACHED("could not create style struct"); \
5247 static_cast<const nsStyle##name_ *>( \
5248 mPresContext->PresShell()->StyleSet()-> \
5249 DefaultStyleData()->GetStyleData(eStyleStruct_##name_)); \
5251 #include "nsStyleStructList.h"
5257 for (nsRuleNode
*node
= this;
5258 node
&& !(node
->mDependentBits
& NS_RULE_NODE_GC_MARK
);
5259 node
= node
->mParent
)
5260 node
->mDependentBits
|= NS_RULE_NODE_GC_MARK
;
5263 static PLDHashOperator
5264 SweepRuleNodeChildren(PLDHashTable
*table
, PLDHashEntryHdr
*hdr
,
5265 PRUint32 number
, void *arg
)
5267 ChildrenHashEntry
*entry
= static_cast<ChildrenHashEntry
*>(hdr
);
5268 if (entry
->mRuleNode
->Sweep())
5269 return PL_DHASH_REMOVE
; // implies NEXT, unless |ed with STOP
5270 return PL_DHASH_NEXT
;
5276 // If we're not marked, then we have to delete ourself.
5277 // However, we never allow the root node to GC itself, because nsStyleSet
5278 // wants to hold onto the root node and not worry about re-creating a
5279 // rule walker if the root node is deleted.
5280 if (!(mDependentBits
& NS_RULE_NODE_GC_MARK
) && !IsRoot()) {
5285 // Clear our mark, for the next time around.
5286 mDependentBits
&= ~NS_RULE_NODE_GC_MARK
;
5288 // Call sweep on the children, since some may not be marked, and
5289 // remove any deleted children from the child lists.
5290 if (HaveChildren()) {
5291 if (ChildrenAreHashed()) {
5292 PLDHashTable
*children
= ChildrenHash();
5293 PL_DHashTableEnumerate(children
, SweepRuleNodeChildren
, nsnull
);
5295 for (nsRuleNode
**children
= ChildrenListPtr(); *children
; ) {
5296 nsRuleNode
*next
= (*children
)->mNextSibling
;
5297 if ((*children
)->Sweep()) {
5298 // This rule node was destroyed, so implicitly advance by
5299 // making *children point to the next entry.
5303 children
= &(*children
)->mNextSibling
;
5312 nsRuleNode::HasAuthorSpecifiedRules(nsStyleContext
* aStyleContext
,
5313 PRUint32 ruleTypeMask
)
5315 nsRuleDataColor colorData
;
5316 nsRuleDataMargin marginData
;
5317 PRUint32 nValues
= 0;
5319 PRUint32 inheritBits
= 0;
5320 if (ruleTypeMask
& NS_AUTHOR_SPECIFIED_BACKGROUND
)
5321 inheritBits
|= NS_STYLE_INHERIT_BIT(Background
);
5323 if (ruleTypeMask
& NS_AUTHOR_SPECIFIED_BORDER
)
5324 inheritBits
|= NS_STYLE_INHERIT_BIT(Border
);
5326 if (ruleTypeMask
& NS_AUTHOR_SPECIFIED_PADDING
)
5327 inheritBits
|= NS_STYLE_INHERIT_BIT(Padding
);
5329 /* We're relying on the use of |aStyleContext| not mutating it! */
5330 nsRuleData
ruleData(inheritBits
,
5331 aStyleContext
->PresContext(), aStyleContext
);
5332 ruleData
.mColorData
= &colorData
;
5333 ruleData
.mMarginData
= &marginData
;
5335 nsCSSValue
* backgroundValues
[] = {
5336 &colorData
.mBackColor
,
5337 &colorData
.mBackImage
5340 nsCSSValue
* borderValues
[] = {
5341 &marginData
.mBorderColor
.mTop
,
5342 &marginData
.mBorderStyle
.mTop
,
5343 &marginData
.mBorderWidth
.mTop
,
5344 &marginData
.mBorderColor
.mRight
,
5345 &marginData
.mBorderStyle
.mRight
,
5346 &marginData
.mBorderWidth
.mRight
,
5347 &marginData
.mBorderColor
.mBottom
,
5348 &marginData
.mBorderStyle
.mBottom
,
5349 &marginData
.mBorderWidth
.mBottom
,
5350 &marginData
.mBorderColor
.mLeft
,
5351 &marginData
.mBorderStyle
.mLeft
,
5352 &marginData
.mBorderWidth
.mLeft
5353 // XXX add &marginData.mBorder{Start,End}{Width,Color,Style}
5356 nsCSSValue
* paddingValues
[] = {
5357 &marginData
.mPadding
.mTop
,
5358 &marginData
.mPadding
.mRight
,
5359 &marginData
.mPadding
.mBottom
,
5360 &marginData
.mPadding
.mLeft
,
5361 &marginData
.mPaddingStart
,
5362 &marginData
.mPaddingEnd
5365 nsCSSValue
* values
[NS_ARRAY_LENGTH(backgroundValues
) +
5366 NS_ARRAY_LENGTH(borderValues
) +
5367 NS_ARRAY_LENGTH(paddingValues
)];
5369 if (ruleTypeMask
& NS_AUTHOR_SPECIFIED_BACKGROUND
) {
5370 memcpy(&values
[nValues
], backgroundValues
, NS_ARRAY_LENGTH(backgroundValues
) * sizeof(nsCSSValue
*));
5371 nValues
+= NS_ARRAY_LENGTH(backgroundValues
);
5374 if (ruleTypeMask
& NS_AUTHOR_SPECIFIED_BORDER
) {
5375 memcpy(&values
[nValues
], borderValues
, NS_ARRAY_LENGTH(borderValues
) * sizeof(nsCSSValue
*));
5376 nValues
+= NS_ARRAY_LENGTH(borderValues
);
5379 if (ruleTypeMask
& NS_AUTHOR_SPECIFIED_PADDING
) {
5380 memcpy(&values
[nValues
], paddingValues
, NS_ARRAY_LENGTH(paddingValues
) * sizeof(nsCSSValue
*));
5381 nValues
+= NS_ARRAY_LENGTH(paddingValues
);
5384 nsStyleContext
* styleContext
= aStyleContext
;
5386 // We need to be careful not to count styles covered up by user-important or
5387 // UA-important declarations. But we do want to catch explicit inherit
5388 // styling in those and check our parent style context to see whether we have
5389 // user styling for those properties. Note that we don't care here about
5390 // inheritance due to lack of a specified value, since all the properties we
5391 // care about are reset properties.
5392 PRBool haveExplicitUAInherit
;
5394 haveExplicitUAInherit
= PR_FALSE
;
5395 for (nsRuleNode
* ruleNode
= styleContext
->GetRuleNode(); ruleNode
;
5396 ruleNode
= ruleNode
->GetParent()) {
5397 nsIStyleRule
*rule
= ruleNode
->GetRule();
5399 ruleData
.mLevel
= ruleNode
->GetLevel();
5400 ruleData
.mIsImportantRule
= ruleNode
->IsImportantRule();
5401 rule
->MapRuleInfoInto(&ruleData
);
5402 // Do the same nulling out as in GetBorderData, GetBackgroundData
5403 // or GetPaddingData.
5404 // We are sharing with some style rule. It really owns the data.
5405 marginData
.mBoxShadow
= nsnull
;
5407 if (ruleData
.mLevel
== nsStyleSet::eAgentSheet
||
5408 ruleData
.mLevel
== nsStyleSet::eUserSheet
) {
5409 // This is a rule whose effect we want to ignore, so if any of
5410 // the properties we care about were set, set them to the dummy
5411 // value that they'll never otherwise get.
5412 for (PRUint32 i
= 0; i
< nValues
; ++i
) {
5413 nsCSSUnit unit
= values
[i
]->GetUnit();
5414 if (unit
!= eCSSUnit_Null
&&
5415 unit
!= eCSSUnit_Dummy
&&
5416 unit
!= eCSSUnit_DummyInherit
) {
5417 if (unit
== eCSSUnit_Inherit
) {
5418 haveExplicitUAInherit
= PR_TRUE
;
5419 values
[i
]->SetDummyInheritValue();
5421 values
[i
]->SetDummyValue();
5426 // If any of the values we care about was set by the above rule,
5427 // we have author style.
5428 for (PRUint32 i
= 0; i
< nValues
; ++i
)
5429 if (values
[i
]->GetUnit() != eCSSUnit_Null
&&
5430 values
[i
]->GetUnit() != eCSSUnit_Dummy
&& // see above
5431 values
[i
]->GetUnit() != eCSSUnit_DummyInherit
)
5437 if (haveExplicitUAInherit
) {
5438 // reset all the eCSSUnit_Null values to eCSSUnit_Dummy (since they're
5439 // not styled by the author, or by anyone else), and then reset all the
5440 // eCSSUnit_DummyInherit values to eCSSUnit_Null (so we will be able to
5441 // detect them being styled by the author) and move up to our parent
5443 for (PRUint32 i
= 0; i
< nValues
; ++i
)
5444 if (values
[i
]->GetUnit() == eCSSUnit_Null
)
5445 values
[i
]->SetDummyValue();
5446 for (PRUint32 i
= 0; i
< nValues
; ++i
)
5447 if (values
[i
]->GetUnit() == eCSSUnit_DummyInherit
)
5449 styleContext
= styleContext
->GetParent();
5451 } while (haveExplicitUAInherit
&& styleContext
);