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>
29 * Alternatively, the contents of this file may be used under the terms of
30 * either of the GNU General Public License Version 2 or later (the "GPL"),
31 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
32 * in which case the provisions of the GPL or the LGPL are applicable instead
33 * of those above. If you wish to allow use of your version of this file only
34 * under the terms of either the GPL or the LGPL, and not to allow others to
35 * use your version of this file under the terms of the MPL, indicate your
36 * decision by deleting the provisions above and replace them with the notice
37 * and other provisions required by the GPL or the LGPL. If you do not delete
38 * the provisions above, a recipient may use your version of this file under
39 * the terms of any one of the MPL, the GPL or the LGPL.
41 * ***** END LICENSE BLOCK ***** */
44 * a node in the lexicographic tree of rules that match an element,
45 * responsible for converting the rules' information into computed style
48 #include "nsRuleNode.h"
50 #include "nsIServiceManager.h"
51 #include "nsIDeviceContext.h"
52 #include "nsILookAndFeel.h"
53 #include "nsIPresShell.h"
54 #include "nsIFontMetrics.h"
55 #include "nsStyleUtil.h"
56 #include "nsCSSPseudoElements.h"
57 #include "nsThemeConstants.h"
60 #include "nsStyleContext.h"
61 #include "nsStyleSet.h"
63 #include "imgIRequest.h"
64 #include "nsRuleData.h"
65 #include "nsILanguageAtomService.h"
66 #include "nsIStyleRule.h"
67 #include "nsBidiUtils.h"
70 * For storage of an |nsRuleNode|'s children in a linked list.
73 nsRuleNode
* mRuleNode
;
77 nsRuleList(nsRuleNode
* aNode
, nsRuleList
* aNext
= nsnull
) {
78 MOZ_COUNT_CTOR(nsRuleList
);
84 MOZ_COUNT_DTOR(nsRuleList
);
87 mNext
->Destroy(mNext
->mRuleNode
->mPresContext
);
90 void* operator new(size_t sz
, nsPresContext
* aContext
) CPP_THROW_NEW
{
91 return aContext
->AllocateFromShell(sz
);
93 void operator delete(void* aPtr
) {} // Does nothing. The arena will free us up when the rule tree
96 void Destroy(nsPresContext
* aContext
) {
98 aContext
->FreeToShell(sizeof(nsRuleList
), this);
101 // Destroy this node, but not its rule node or the rest of the list.
102 nsRuleList
* DestroySelf(nsPresContext
* aContext
) {
103 nsRuleList
*next
= mNext
;
104 MOZ_COUNT_DTOR(nsRuleList
); // hack
105 aContext
->FreeToShell(sizeof(nsRuleList
), this);
111 * For storage of an |nsRuleNode|'s children in a PLDHashTable.
114 struct ChildrenHashEntry
: public PLDHashEntryHdr
{
115 // key is |mRuleNode->GetKey()|
116 nsRuleNode
*mRuleNode
;
119 /* static */ PR_CALLBACK PLDHashNumber
120 nsRuleNode::ChildrenHashHashKey(PLDHashTable
*aTable
, const void *aKey
)
122 const nsRuleNode::Key
*key
=
123 static_cast<const nsRuleNode::Key
*>(aKey
);
124 // Disagreement on importance and level for the same rule is extremely
125 // rare, so hash just on the rule.
126 return PL_DHashVoidPtrKeyStub(aTable
, key
->mRule
);
129 /* static */ PR_CALLBACK PRBool
130 nsRuleNode::ChildrenHashMatchEntry(PLDHashTable
*aTable
,
131 const PLDHashEntryHdr
*aHdr
,
134 const ChildrenHashEntry
*entry
=
135 static_cast<const ChildrenHashEntry
*>(aHdr
);
136 const nsRuleNode::Key
*key
=
137 static_cast<const nsRuleNode::Key
*>(aKey
);
138 return entry
->mRuleNode
->GetKey() == *key
;
141 /* static */ PLDHashTableOps
142 nsRuleNode::ChildrenHashOps
= {
143 // It's probably better to allocate the table itself using malloc and
144 // free rather than the pres shell's arena because the table doesn't
145 // grow very often and the pres shell's arena doesn't recycle very
146 // large size allocations.
150 ChildrenHashMatchEntry
,
151 PL_DHashMoveEntryStub
,
152 PL_DHashClearEntryStub
,
153 PL_DHashFinalizeStub
,
158 // EnsureBlockDisplay:
159 // - if the display value (argument) is not a block-type
160 // then we set it to a valid block display value
161 // - For enforcing the floated/positioned element CSS2 rules
162 static void EnsureBlockDisplay(PRUint8
& display
)
164 // see if the display value is already a block
166 case NS_STYLE_DISPLAY_NONE
:
167 // never change display:none *ever*
168 case NS_STYLE_DISPLAY_TABLE
:
169 case NS_STYLE_DISPLAY_BLOCK
:
170 case NS_STYLE_DISPLAY_LIST_ITEM
:
171 // do not muck with these at all - already blocks
172 // This is equivalent to nsStyleDisplay::IsBlockOutside. (XXX Maybe we
173 // should just call that?)
176 case NS_STYLE_DISPLAY_INLINE_TABLE
:
177 // make inline tables into tables
178 display
= NS_STYLE_DISPLAY_TABLE
;
183 display
= NS_STYLE_DISPLAY_BLOCK
;
187 // XXX This should really be done in the CSS parser.
188 static nsString
& Unquote(nsString
& aString
)
190 PRUnichar start
= aString
.First();
191 PRUnichar end
= aString
.Last();
193 if ((start
== end
) &&
194 ((start
== PRUnichar('\"')) ||
195 (start
== PRUnichar('\'')))) {
196 PRInt32 length
= aString
.Length();
197 aString
.Truncate(length
- 1);
203 static nscoord
CalcLengthWith(const nsCSSValue
& aValue
,
205 const nsStyleFont
* aStyleFont
,
206 nsStyleContext
* aStyleContext
,
207 nsPresContext
* aPresContext
,
210 NS_ASSERTION(aValue
.IsLengthUnit(), "not a length unit");
211 NS_ASSERTION(aStyleFont
|| aStyleContext
, "Must have style data");
212 NS_ASSERTION(aPresContext
, "Must have prescontext");
214 if (aValue
.IsFixedLengthUnit()) {
215 return aPresContext
->TwipsToAppUnits(aValue
.GetLengthTwips());
217 nsCSSUnit unit
= aValue
.GetUnit();
218 if (unit
== eCSSUnit_Pixel
) {
219 return nsPresContext::CSSPixelsToAppUnits(aValue
.GetFloatValue());
221 // Common code for all units other than pixels:
222 aInherited
= PR_TRUE
;
224 aStyleFont
= aStyleContext
->GetStyleFont();
226 if (aFontSize
== -1) {
227 // XXX Should this be aStyleFont->mSize instead to avoid taking minfontsize
228 // prefs into account?
229 aFontSize
= aStyleFont
->mFont
.size
;
233 case eCSSUnit_Char
: {
234 return NSToCoordRound(aValue
.GetFloatValue() * float(aFontSize
));
235 // XXX scale against font metrics height instead?
238 return NSToCoordRound((aValue
.GetFloatValue() * float(aFontSize
)) / 2.0f
);
240 case eCSSUnit_XHeight
: {
241 nsFont font
= aStyleFont
->mFont
;
242 font
.size
= aFontSize
;
243 nsCOMPtr
<nsIFontMetrics
> fm
= aPresContext
->GetMetricsFor(font
);
245 fm
->GetXHeight(xHeight
);
246 return NSToCoordRound(aValue
.GetFloatValue() * float(xHeight
));
248 case eCSSUnit_CapHeight
: {
249 NS_NOTYETIMPLEMENTED("cap height unit");
250 nscoord capHeight
= ((aFontSize
/ 3) * 2); // XXX HACK!
251 return NSToCoordRound(aValue
.GetFloatValue() * float(capHeight
));
254 NS_NOTREACHED("unexpected unit");
260 static nscoord
CalcLength(const nsCSSValue
& aValue
,
261 nsStyleContext
* aStyleContext
,
262 nsPresContext
* aPresContext
,
265 NS_ASSERTION(aStyleContext
, "Must have style data");
267 return CalcLengthWith(aValue
, -1, nsnull
, aStyleContext
, aPresContext
, aInherited
);
270 #define SETCOORD_NORMAL 0x01 // N
271 #define SETCOORD_AUTO 0x02 // A
272 #define SETCOORD_INHERIT 0x04 // H
273 #define SETCOORD_PERCENT 0x08 // P
274 #define SETCOORD_FACTOR 0x10 // F
275 #define SETCOORD_LENGTH 0x20 // L
276 #define SETCOORD_INTEGER 0x40 // I
277 #define SETCOORD_ENUMERATED 0x80 // E
278 #define SETCOORD_NONE 0x100 // O
279 #define SETCOORD_INITIAL_ZERO 0x200
280 #define SETCOORD_INITIAL_AUTO 0x400
281 #define SETCOORD_INITIAL_NONE 0x800
282 #define SETCOORD_INITIAL_NORMAL 0x1000
284 #define SETCOORD_LP (SETCOORD_LENGTH | SETCOORD_PERCENT)
285 #define SETCOORD_LH (SETCOORD_LENGTH | SETCOORD_INHERIT)
286 #define SETCOORD_AH (SETCOORD_AUTO | SETCOORD_INHERIT)
287 #define SETCOORD_LAH (SETCOORD_AUTO | SETCOORD_LENGTH | SETCOORD_INHERIT)
288 #define SETCOORD_LPH (SETCOORD_LP | SETCOORD_INHERIT)
289 #define SETCOORD_LPAH (SETCOORD_LP | SETCOORD_AH)
290 #define SETCOORD_LPEH (SETCOORD_LP | SETCOORD_ENUMERATED | SETCOORD_INHERIT)
291 #define SETCOORD_LPAEH (SETCOORD_LPAH | SETCOORD_ENUMERATED)
292 #define SETCOORD_LPOH (SETCOORD_LPH | SETCOORD_NONE)
293 #define SETCOORD_LPOEH (SETCOORD_LPOH | SETCOORD_ENUMERATED)
294 #define SETCOORD_LE (SETCOORD_LENGTH | SETCOORD_ENUMERATED)
295 #define SETCOORD_LEH (SETCOORD_LE | SETCOORD_INHERIT)
296 #define SETCOORD_IA (SETCOORD_INTEGER | SETCOORD_AUTO)
297 #define SETCOORD_LAE (SETCOORD_LENGTH | SETCOORD_AUTO | SETCOORD_ENUMERATED)
299 // changes aCoord iff it returns PR_TRUE
300 static PRBool
SetCoord(const nsCSSValue
& aValue
, nsStyleCoord
& aCoord
,
301 const nsStyleCoord
& aParentCoord
,
302 PRInt32 aMask
, nsStyleContext
* aStyleContext
,
303 nsPresContext
* aPresContext
, PRBool
& aInherited
)
305 PRBool result
= PR_TRUE
;
306 if (aValue
.GetUnit() == eCSSUnit_Null
) {
309 else if (((aMask
& SETCOORD_LENGTH
) != 0) &&
310 (aValue
.GetUnit() == eCSSUnit_Char
)) {
311 aCoord
.SetIntValue(NSToIntFloor(aValue
.GetFloatValue()), eStyleUnit_Chars
);
313 else if (((aMask
& SETCOORD_LENGTH
) != 0) &&
314 aValue
.IsLengthUnit()) {
315 aCoord
.SetCoordValue(CalcLength(aValue
, aStyleContext
, aPresContext
, aInherited
));
317 else if (((aMask
& SETCOORD_PERCENT
) != 0) &&
318 (aValue
.GetUnit() == eCSSUnit_Percent
)) {
319 aCoord
.SetPercentValue(aValue
.GetPercentValue());
321 else if (((aMask
& SETCOORD_INTEGER
) != 0) &&
322 (aValue
.GetUnit() == eCSSUnit_Integer
)) {
323 aCoord
.SetIntValue(aValue
.GetIntValue(), eStyleUnit_Integer
);
325 else if (((aMask
& SETCOORD_ENUMERATED
) != 0) &&
326 (aValue
.GetUnit() == eCSSUnit_Enumerated
)) {
327 aCoord
.SetIntValue(aValue
.GetIntValue(), eStyleUnit_Enumerated
);
329 else if (((aMask
& SETCOORD_AUTO
) != 0) &&
330 (aValue
.GetUnit() == eCSSUnit_Auto
)) {
331 aCoord
.SetAutoValue();
333 else if (((aMask
& SETCOORD_INHERIT
) != 0) &&
334 (aValue
.GetUnit() == eCSSUnit_Inherit
)) {
335 aCoord
= aParentCoord
; // just inherit value from parent
336 aInherited
= PR_TRUE
;
338 else if (((aMask
& SETCOORD_NORMAL
) != 0) &&
339 (aValue
.GetUnit() == eCSSUnit_Normal
)) {
340 aCoord
.SetNormalValue();
342 else if (((aMask
& SETCOORD_NONE
) != 0) &&
343 (aValue
.GetUnit() == eCSSUnit_None
)) {
344 aCoord
.SetNoneValue();
346 else if (((aMask
& SETCOORD_FACTOR
) != 0) &&
347 (aValue
.GetUnit() == eCSSUnit_Number
)) {
348 aCoord
.SetFactorValue(aValue
.GetFloatValue());
350 else if (((aMask
& SETCOORD_INITIAL_AUTO
) != 0) &&
351 (aValue
.GetUnit() == eCSSUnit_Initial
)) {
352 aCoord
.SetAutoValue();
354 else if (((aMask
& SETCOORD_INITIAL_ZERO
) != 0) &&
355 (aValue
.GetUnit() == eCSSUnit_Initial
)) {
356 aCoord
.SetCoordValue(0);
358 else if (((aMask
& SETCOORD_INITIAL_NONE
) != 0) &&
359 (aValue
.GetUnit() == eCSSUnit_Initial
)) {
360 aCoord
.SetNoneValue();
362 else if (((aMask
& SETCOORD_INITIAL_NORMAL
) != 0) &&
363 (aValue
.GetUnit() == eCSSUnit_Initial
)) {
364 aCoord
.SetNormalValue();
367 result
= PR_FALSE
; // didn't set anything
372 static PRBool
SetColor(const nsCSSValue
& aValue
, const nscolor aParentColor
,
373 nsPresContext
* aPresContext
, nsStyleContext
*aContext
,
374 nscolor
& aResult
, PRBool
& aInherited
)
376 PRBool result
= PR_FALSE
;
377 nsCSSUnit unit
= aValue
.GetUnit();
379 if (eCSSUnit_Color
== unit
) {
380 aResult
= aValue
.GetColorValue();
383 else if (eCSSUnit_String
== unit
) {
385 aValue
.GetStringValue(value
);
387 if (NS_ColorNameToRGB(value
, &rgba
)) {
392 else if (eCSSUnit_EnumColor
== unit
) {
393 PRInt32 intValue
= aValue
.GetIntValue();
395 nsILookAndFeel
* look
= aPresContext
->LookAndFeel();
396 nsILookAndFeel::nsColorID colorID
= (nsILookAndFeel::nsColorID
) intValue
;
397 if (NS_SUCCEEDED(look
->GetColor(colorID
, aResult
))) {
403 case NS_COLOR_MOZ_HYPERLINKTEXT
:
404 aResult
= aPresContext
->DefaultLinkColor();
406 case NS_COLOR_MOZ_VISITEDHYPERLINKTEXT
:
407 aResult
= aPresContext
->DefaultVisitedLinkColor();
409 case NS_COLOR_MOZ_ACTIVEHYPERLINKTEXT
:
410 aResult
= aPresContext
->DefaultActiveLinkColor();
412 case NS_COLOR_CURRENTCOLOR
:
413 // The data computed from this can't be shared in the rule tree
414 // because they could be used on a node with a different color
415 aInherited
= PR_TRUE
;
416 aResult
= aContext
->GetStyleColor()->mColor
;
419 NS_NOTREACHED("Should never have an unknown negative colorID.");
425 else if (eCSSUnit_Inherit
== unit
) {
426 aResult
= aParentColor
;
428 aInherited
= PR_TRUE
;
433 // Overloaded new operator. Initializes the memory to 0 and relies on an arena
434 // (which comes from the presShell) to perform the allocation.
436 nsRuleNode::operator new(size_t sz
, nsPresContext
* aPresContext
) CPP_THROW_NEW
438 // Check the recycle list first.
439 return aPresContext
->AllocateFromShell(sz
);
442 // Overridden to prevent the global delete from being called, since the memory
443 // came out of an nsIArena instead of the global delete operator's heap.
445 nsRuleNode::Destroy()
447 // Destroy ourselves.
450 // Don't let the memory be freed, since it will be recycled
451 // instead. Don't call the global operator delete.
452 mPresContext
->FreeToShell(sizeof(nsRuleNode
), this);
455 nsRuleNode
* nsRuleNode::CreateRootNode(nsPresContext
* aPresContext
)
457 return new (aPresContext
)
458 nsRuleNode(aPresContext
, nsnull
, nsnull
, 0xff, PR_FALSE
);
461 nsILanguageAtomService
* nsRuleNode::gLangService
= nsnull
;
463 nsRuleNode::nsRuleNode(nsPresContext
* aContext
, nsRuleNode
* aParent
,
464 nsIStyleRule
* aRule
, PRUint8 aLevel
,
466 : mPresContext(aContext
),
469 mChildrenTaggedPtr(nsnull
),
470 mDependentBits((PRUint32(aLevel
) << NS_RULE_NODE_LEVEL_SHIFT
) |
471 (aIsImportant
? NS_RULE_NODE_IS_IMPORTANT
: 0)),
474 MOZ_COUNT_CTOR(nsRuleNode
);
477 NS_ASSERTION(IsRoot() || GetLevel() == aLevel
, "not enough bits");
478 NS_ASSERTION(IsRoot() || IsImportantRule() == aIsImportant
, "yikes");
481 PR_STATIC_CALLBACK(PLDHashOperator
)
482 DeleteRuleNodeChildren(PLDHashTable
*table
, PLDHashEntryHdr
*hdr
,
483 PRUint32 number
, void *arg
)
485 ChildrenHashEntry
*entry
= static_cast<ChildrenHashEntry
*>(hdr
);
486 entry
->mRuleNode
->Destroy();
487 return PL_DHASH_NEXT
;
490 nsRuleNode::~nsRuleNode()
492 MOZ_COUNT_DTOR(nsRuleNode
);
493 if (mStyleData
.mResetData
|| mStyleData
.mInheritedData
)
494 mStyleData
.Destroy(0, mPresContext
);
495 if (ChildrenAreHashed()) {
496 PLDHashTable
*children
= ChildrenHash();
497 PL_DHashTableEnumerate(children
, DeleteRuleNodeChildren
, nsnull
);
498 PL_DHashTableDestroy(children
);
499 } else if (HaveChildren())
500 ChildrenList()->Destroy(mPresContext
);
501 NS_IF_RELEASE(mRule
);
505 nsRuleNode::Transition(nsIStyleRule
* aRule
, PRUint8 aLevel
,
506 PRPackedBool aIsImportantRule
)
508 nsRuleNode
* next
= nsnull
;
509 nsRuleNode::Key
key(aRule
, aLevel
, aIsImportantRule
);
511 if (HaveChildren() && !ChildrenAreHashed()) {
513 nsRuleList
* curr
= ChildrenList();
514 while (curr
&& curr
->mRuleNode
->GetKey() != key
) {
519 next
= curr
->mRuleNode
;
520 else if (numKids
>= kMaxChildrenInList
)
521 ConvertChildrenToHash();
524 if (ChildrenAreHashed()) {
525 ChildrenHashEntry
*entry
= static_cast<ChildrenHashEntry
*>
526 (PL_DHashTableOperate(ChildrenHash(), &key
, PL_DHASH_ADD
));
530 if (entry
->mRuleNode
)
531 next
= entry
->mRuleNode
;
533 next
= entry
->mRuleNode
= new (mPresContext
)
534 nsRuleNode(mPresContext
, this, aRule
, aLevel
, aIsImportantRule
);
536 PL_DHashTableRawRemove(ChildrenHash(), entry
);
541 // Create the new entry in our list.
542 next
= new (mPresContext
)
543 nsRuleNode(mPresContext
, this, aRule
, aLevel
, aIsImportantRule
);
547 nsRuleList
* newChildrenList
= new (mPresContext
) nsRuleList(next
, ChildrenList());
548 if (NS_UNLIKELY(!newChildrenList
)) {
552 SetChildrenList(newChildrenList
);
559 nsRuleNode::ConvertChildrenToHash()
561 NS_ASSERTION(!ChildrenAreHashed() && HaveChildren(),
562 "must have a non-empty list of children");
563 PLDHashTable
*hash
= PL_NewDHashTable(&ChildrenHashOps
, nsnull
,
564 sizeof(ChildrenHashEntry
),
565 kMaxChildrenInList
* 4);
568 for (nsRuleList
* curr
= ChildrenList(); curr
;
569 curr
= curr
->DestroySelf(mPresContext
)) {
570 // This will never fail because of the initial size we gave the table.
571 ChildrenHashEntry
*entry
= static_cast<ChildrenHashEntry
*>
572 (PL_DHashTableOperate(hash
, curr
->mRuleNode
->mRule
, PL_DHASH_ADD
));
573 NS_ASSERTION(!entry
->mRuleNode
, "duplicate entries in list");
574 entry
->mRuleNode
= curr
->mRuleNode
;
576 SetChildrenHash(hash
);
580 nsRuleNode::PropagateNoneBit(PRUint32 aBit
, nsRuleNode
* aHighestNode
)
582 nsRuleNode
* curr
= this;
584 NS_ASSERTION(!(curr
->mNoneBits
& aBit
), "propagating too far");
585 curr
->mNoneBits
|= aBit
;
586 if (curr
== aHighestNode
)
588 curr
= curr
->mParent
;
593 nsRuleNode::PropagateDependentBit(PRUint32 aBit
, nsRuleNode
* aHighestNode
)
595 for (nsRuleNode
* curr
= this; curr
!= aHighestNode
; curr
= curr
->mParent
) {
596 if (curr
->mDependentBits
& aBit
) {
598 while (curr
!= aHighestNode
) {
599 NS_ASSERTION(curr
->mDependentBits
& aBit
, "bit not set");
600 curr
= curr
->mParent
;
606 curr
->mDependentBits
|= aBit
;
611 * The following "Check" functions are used for determining what type of
612 * sharing can be used for the data on this rule node. MORE HERE...
615 /* the information for a property (or in some cases, a rect group of
618 struct PropertyCheckData
{
624 * a callback function that that can revise the result of
625 * CheckSpecifiedProperties before finishing; aResult is the current
626 * result, and it returns the revised one.
628 typedef nsRuleNode::RuleDetail
629 (* PR_CALLBACK CheckCallbackFn
)(const nsRuleDataStruct
& aData
,
630 nsRuleNode::RuleDetail aResult
);
632 /* the information for all the properties in a style struct */
633 struct StructCheckData
{
634 const PropertyCheckData
* props
;
636 CheckCallbackFn callback
;
641 * @param aValue the value being examined
642 * @param aSpecifiedCount to be incremented by one if the value is specified
643 * @param aInherited to be incremented by one if the value is set to inherit
646 ExamineCSSValue(const nsCSSValue
& aValue
,
647 PRUint32
& aSpecifiedCount
, PRUint32
& aInheritedCount
)
649 if (aValue
.GetUnit() != eCSSUnit_Null
) {
651 if (aValue
.GetUnit() == eCSSUnit_Inherit
) {
658 ExamineCSSValuePair(const nsCSSValuePair
* aValuePair
,
659 PRUint32
& aSpecifiedCount
, PRUint32
& aInheritedCount
)
661 NS_PRECONDITION(aValuePair
, "Must have a value pair");
663 ExamineCSSValue(aValuePair
->mXValue
, aSpecifiedCount
, aInheritedCount
);
664 ExamineCSSValue(aValuePair
->mYValue
, aSpecifiedCount
, aInheritedCount
);
668 ExamineCSSRect(const nsCSSRect
* aRect
,
669 PRUint32
& aSpecifiedCount
, PRUint32
& aInheritedCount
)
671 NS_PRECONDITION(aRect
, "Must have a rect");
673 NS_FOR_CSS_SIDES(side
) {
674 ExamineCSSValue(aRect
->*(nsCSSRect::sides
[side
]),
675 aSpecifiedCount
, aInheritedCount
);
679 PR_STATIC_CALLBACK(nsRuleNode::RuleDetail
)
680 CheckFontCallback(const nsRuleDataStruct
& aData
,
681 nsRuleNode::RuleDetail aResult
)
683 const nsRuleDataFont
& fontData
=
684 static_cast<const nsRuleDataFont
&>(aData
);
686 // em, ex, percent, 'larger', and 'smaller' values on font-size depend
687 // on the parent context's font-size
688 // Likewise, 'lighter' and 'bolder' values of 'font-weight' depend on
690 const nsCSSValue
& size
= fontData
.mSize
;
691 const nsCSSValue
& weight
= fontData
.mWeight
;
692 if ((size
.IsRelativeLengthUnit() && size
.GetUnit() != eCSSUnit_Pixel
) ||
693 size
.GetUnit() == eCSSUnit_Percent
||
694 (size
.GetUnit() == eCSSUnit_Enumerated
&&
695 (size
.GetIntValue() == NS_STYLE_FONT_SIZE_SMALLER
||
696 size
.GetIntValue() == NS_STYLE_FONT_SIZE_LARGER
)) ||
698 fontData
.mScriptLevel
.GetUnit() == eCSSUnit_Integer
||
700 (weight
.GetUnit() == eCSSUnit_Enumerated
&&
701 (weight
.GetIntValue() == NS_STYLE_FONT_WEIGHT_BOLDER
||
702 weight
.GetIntValue() == NS_STYLE_FONT_WEIGHT_LIGHTER
))) {
703 NS_ASSERTION(aResult
== nsRuleNode::eRulePartialReset
||
704 aResult
== nsRuleNode::eRuleFullReset
||
705 aResult
== nsRuleNode::eRulePartialMixed
||
706 aResult
== nsRuleNode::eRuleFullMixed
,
707 "we know we already have a reset-counted property");
708 // Promote reset to mixed since we have something that depends on
709 // the parent. But never promote to inherited since that could
710 // cause inheritance of the exact value.
711 if (aResult
== nsRuleNode::eRulePartialReset
)
712 aResult
= nsRuleNode::eRulePartialMixed
;
713 else if (aResult
== nsRuleNode::eRuleFullReset
)
714 aResult
= nsRuleNode::eRuleFullMixed
;
720 PR_STATIC_CALLBACK(nsRuleNode::RuleDetail
)
721 CheckColorCallback(const nsRuleDataStruct
& aData
,
722 nsRuleNode::RuleDetail aResult
)
724 const nsRuleDataColor
& colorData
=
725 static_cast<const nsRuleDataColor
&>(aData
);
727 // currentColor values for color require inheritance
728 if (colorData
.mColor
.GetUnit() == eCSSUnit_EnumColor
&&
729 colorData
.mColor
.GetIntValue() == NS_COLOR_CURRENTCOLOR
) {
730 NS_ASSERTION(aResult
== nsRuleNode::eRuleFullReset
,
731 "we should already be counted as full-reset");
732 aResult
= nsRuleNode::eRuleFullInherited
;
739 // for nsCSSPropList.h, so we get information on things in the style
740 // structs but not nsCSS*
741 #define CSS_PROP_INCLUDE_NOT_CSS
743 static const PropertyCheckData FontCheckProperties
[] = {
744 #define CSS_PROP_FONT(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
745 { offsetof(nsRuleData##datastruct_, member_), type_ },
746 #include "nsCSSPropList.h"
750 static const PropertyCheckData DisplayCheckProperties
[] = {
751 #define CSS_PROP_DISPLAY(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
752 { offsetof(nsRuleData##datastruct_, member_), type_ },
753 #include "nsCSSPropList.h"
754 #undef CSS_PROP_DISPLAY
757 static const PropertyCheckData VisibilityCheckProperties
[] = {
758 #define CSS_PROP_VISIBILITY(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
759 { offsetof(nsRuleData##datastruct_, member_), type_ },
760 #include "nsCSSPropList.h"
761 #undef CSS_PROP_VISIBILITY
764 static const PropertyCheckData MarginCheckProperties
[] = {
765 #define CSS_PROP_MARGIN(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
766 { offsetof(nsRuleData##datastruct_, member_), type_ },
767 #include "nsCSSPropList.h"
768 #undef CSS_PROP_MARGIN
771 static const PropertyCheckData BorderCheckProperties
[] = {
772 #define CSS_PROP_BORDER(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
773 { offsetof(nsRuleData##datastruct_, member_), type_ },
774 #include "nsCSSPropList.h"
775 #undef CSS_PROP_BORDER
778 static const PropertyCheckData PaddingCheckProperties
[] = {
779 #define CSS_PROP_PADDING(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
780 { offsetof(nsRuleData##datastruct_, member_), type_ },
781 #include "nsCSSPropList.h"
782 #undef CSS_PROP_PADDING
785 static const PropertyCheckData OutlineCheckProperties
[] = {
786 #define CSS_PROP_OUTLINE(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
787 { offsetof(nsRuleData##datastruct_, member_), type_ },
788 #include "nsCSSPropList.h"
789 #undef CSS_PROP_OUTLINE
792 static const PropertyCheckData ListCheckProperties
[] = {
793 #define CSS_PROP_LIST(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
794 { offsetof(nsRuleData##datastruct_, member_), type_ },
795 #include "nsCSSPropList.h"
799 static const PropertyCheckData ColorCheckProperties
[] = {
800 #define CSS_PROP_COLOR(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
801 { offsetof(nsRuleData##datastruct_, member_), type_ },
802 #include "nsCSSPropList.h"
803 #undef CSS_PROP_COLOR
806 static const PropertyCheckData BackgroundCheckProperties
[] = {
807 #define CSS_PROP_BACKGROUND(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
808 { offsetof(nsRuleData##datastruct_, member_), type_ },
809 #include "nsCSSPropList.h"
810 #undef CSS_PROP_BACKGROUND
813 static const PropertyCheckData PositionCheckProperties
[] = {
814 #define CSS_PROP_POSITION(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
815 { offsetof(nsRuleData##datastruct_, member_), type_ },
816 #include "nsCSSPropList.h"
817 #undef CSS_PROP_POSITION
820 static const PropertyCheckData TableCheckProperties
[] = {
821 #define CSS_PROP_TABLE(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
822 { offsetof(nsRuleData##datastruct_, member_), type_ },
823 #include "nsCSSPropList.h"
824 #undef CSS_PROP_TABLE
827 static const PropertyCheckData TableBorderCheckProperties
[] = {
828 #define CSS_PROP_TABLEBORDER(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
829 { offsetof(nsRuleData##datastruct_, member_), type_ },
830 #include "nsCSSPropList.h"
831 #undef CSS_PROP_TABLEBORDER
834 static const PropertyCheckData ContentCheckProperties
[] = {
835 #define CSS_PROP_CONTENT(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
836 { offsetof(nsRuleData##datastruct_, member_), type_ },
837 #include "nsCSSPropList.h"
838 #undef CSS_PROP_CONTENT
841 static const PropertyCheckData QuotesCheckProperties
[] = {
842 #define CSS_PROP_QUOTES(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
843 { offsetof(nsRuleData##datastruct_, member_), type_ },
844 #include "nsCSSPropList.h"
845 #undef CSS_PROP_QUOTES
848 static const PropertyCheckData TextCheckProperties
[] = {
849 #define CSS_PROP_TEXT(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
850 { offsetof(nsRuleData##datastruct_, member_), type_ },
851 #include "nsCSSPropList.h"
855 static const PropertyCheckData TextResetCheckProperties
[] = {
856 #define CSS_PROP_TEXTRESET(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
857 { offsetof(nsRuleData##datastruct_, member_), type_ },
858 #include "nsCSSPropList.h"
859 #undef CSS_PROP_TEXTRESET
862 static const PropertyCheckData UserInterfaceCheckProperties
[] = {
863 #define CSS_PROP_USERINTERFACE(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
864 { offsetof(nsRuleData##datastruct_, member_), type_ },
865 #include "nsCSSPropList.h"
866 #undef CSS_PROP_USERINTERFACE
869 static const PropertyCheckData UIResetCheckProperties
[] = {
870 #define CSS_PROP_UIRESET(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
871 { offsetof(nsRuleData##datastruct_, member_), type_ },
872 #include "nsCSSPropList.h"
873 #undef CSS_PROP_UIRESET
876 static const PropertyCheckData XULCheckProperties
[] = {
877 #define CSS_PROP_XUL(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
878 { offsetof(nsRuleData##datastruct_, member_), type_ },
879 #include "nsCSSPropList.h"
884 static const PropertyCheckData SVGCheckProperties
[] = {
885 #define CSS_PROP_SVG(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
886 { offsetof(nsRuleData##datastruct_, member_), type_ },
887 #include "nsCSSPropList.h"
891 static const PropertyCheckData SVGResetCheckProperties
[] = {
892 #define CSS_PROP_SVGRESET(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
893 { offsetof(nsRuleData##datastruct_, member_), type_ },
894 #include "nsCSSPropList.h"
895 #undef CSS_PROP_SVGRESET
899 static const PropertyCheckData ColumnCheckProperties
[] = {
900 #define CSS_PROP_COLUMN(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
901 { offsetof(nsRuleData##datastruct_, member_), type_ },
902 #include "nsCSSPropList.h"
903 #undef CSS_PROP_COLUMN
906 #undef CSS_PROP_INCLUDE_NOT_CSS
908 static const StructCheckData gCheckProperties
[] = {
910 #define STYLE_STRUCT(name, checkdata_cb, ctor_args) \
911 {name##CheckProperties, \
912 sizeof(name##CheckProperties)/sizeof(PropertyCheckData), \
914 #include "nsStyleStructList.h"
922 // XXXldb Taking the address of a reference is evil.
924 inline const nsCSSValue
&
925 ValueAtOffset(const nsRuleDataStruct
& aRuleDataStruct
, size_t aOffset
)
927 return * reinterpret_cast<const nsCSSValue
*>
928 (reinterpret_cast<const char*>(&aRuleDataStruct
) + aOffset
);
931 inline const nsCSSRect
*
932 RectAtOffset(const nsRuleDataStruct
& aRuleDataStruct
, size_t aOffset
)
934 return reinterpret_cast<const nsCSSRect
*>
935 (reinterpret_cast<const char*>(&aRuleDataStruct
) + aOffset
);
938 inline const nsCSSValuePair
*
939 ValuePairAtOffset(const nsRuleDataStruct
& aRuleDataStruct
, size_t aOffset
)
941 return reinterpret_cast<const nsCSSValuePair
*>
942 (reinterpret_cast<const char*>(&aRuleDataStruct
) + aOffset
);
945 inline const nsCSSValueList
*
946 ValueListAtOffset(const nsRuleDataStruct
& aRuleDataStruct
, size_t aOffset
)
948 return * reinterpret_cast<const nsCSSValueList
*const*>
949 (reinterpret_cast<const char*>(&aRuleDataStruct
) + aOffset
);
952 inline const nsCSSValueList
**
953 ValueListArrayAtOffset(const nsRuleDataStruct
& aRuleDataStruct
, size_t aOffset
)
955 return * reinterpret_cast<const nsCSSValueList
**const*>
956 (reinterpret_cast<const char*>(&aRuleDataStruct
) + aOffset
);
959 inline const nsCSSCounterData
*
960 CounterDataAtOffset(const nsRuleDataStruct
& aRuleDataStruct
, size_t aOffset
)
962 return * reinterpret_cast<const nsCSSCounterData
*const*>
963 (reinterpret_cast<const char*>(&aRuleDataStruct
) + aOffset
);
966 inline const nsCSSQuotes
*
967 QuotesAtOffset(const nsRuleDataStruct
& aRuleDataStruct
, size_t aOffset
)
969 return * reinterpret_cast<const nsCSSQuotes
*const*>
970 (reinterpret_cast<const char*>(&aRuleDataStruct
) + aOffset
);
973 #if defined(MOZ_MATHML) && defined(DEBUG)
975 AreAllMathMLPropertiesUndefined(const nsCSSFont
& aRuleData
)
977 return aRuleData
.mScriptLevel
.GetUnit() == eCSSUnit_Null
&&
978 aRuleData
.mScriptSizeMultiplier
.GetUnit() == eCSSUnit_Null
&&
979 aRuleData
.mScriptMinSize
.GetUnit() == eCSSUnit_Null
;
983 inline nsRuleNode::RuleDetail
984 nsRuleNode::CheckSpecifiedProperties(const nsStyleStructID aSID
,
985 const nsRuleDataStruct
& aRuleDataStruct
)
987 const StructCheckData
*structData
= gCheckProperties
+ aSID
;
989 // Build a count of the:
990 PRUint32 total
= 0, // total number of props in the struct
991 specified
= 0, // number that were specified for this node
992 inherited
= 0; // number that were 'inherit' (and not
993 // eCSSUnit_Inherit) for this node
995 for (const PropertyCheckData
*prop
= structData
->props
,
996 *prop_end
= prop
+ structData
->nprops
;
999 switch (prop
->type
) {
1001 case eCSSType_Value
:
1003 ExamineCSSValue(ValueAtOffset(aRuleDataStruct
, prop
->offset
),
1004 specified
, inherited
);
1009 ExamineCSSRect(RectAtOffset(aRuleDataStruct
, prop
->offset
),
1010 specified
, inherited
);
1013 case eCSSType_ValuePair
:
1015 ExamineCSSValuePair(ValuePairAtOffset(aRuleDataStruct
, prop
->offset
),
1016 specified
, inherited
);
1019 case eCSSType_ValueList
:
1022 const nsCSSValueList
* valueList
=
1023 ValueListAtOffset(aRuleDataStruct
, prop
->offset
);
1026 if (eCSSUnit_Inherit
== valueList
->mValue
.GetUnit()) {
1033 case eCSSType_CounterData
:
1036 const nsCSSCounterData
* counterData
=
1037 CounterDataAtOffset(aRuleDataStruct
, prop
->offset
);
1040 if (eCSSUnit_Inherit
== counterData
->mCounter
.GetUnit()) {
1047 case eCSSType_Quotes
:
1050 const nsCSSQuotes
* quotes
=
1051 QuotesAtOffset(aRuleDataStruct
, prop
->offset
);
1054 if (eCSSUnit_Inherit
== quotes
->mOpen
.GetUnit()) {
1062 NS_NOTREACHED("unknown type");
1068 printf("CheckSpecifiedProperties: SID=%d total=%d spec=%d inh=%d.\n",
1069 aSID
, total
, specified
, inherited
);
1073 NS_ASSERTION(aSID
!= eStyleStruct_Font
||
1074 mPresContext
->Document()->GetMathMLEnabled() ||
1075 AreAllMathMLPropertiesUndefined(static_cast<const nsCSSFont
&>(aRuleDataStruct
)),
1076 "MathML style property was defined even though MathML is disabled");
1080 * Return the most specific information we can: prefer None or Full
1081 * over Partial, and Reset or Inherited over Mixed, since we can
1082 * optimize based on the edge cases and not the in-between cases.
1084 nsRuleNode::RuleDetail result
;
1085 if (inherited
== total
)
1086 result
= eRuleFullInherited
;
1087 else if (specified
== total
1089 // MathML defines 3 properties in Font that will never be set when
1090 // MathML is not in use. Therefore if all but three
1091 // properties have been set, and MathML is not enabled, we can treat
1092 // this as fully specified. Code in nsMathMLElementFactory will
1093 // rebuild the rule tree and style data when MathML is first enabled
1094 // (see nsMathMLElement::BindToTree).
1095 || (aSID
== eStyleStruct_Font
&& specified
+ 3 == total
&&
1096 !mPresContext
->Document()->GetMathMLEnabled())
1100 result
= eRuleFullReset
;
1102 result
= eRuleFullMixed
;
1103 } else if (specified
== 0)
1105 else if (specified
== inherited
)
1106 result
= eRulePartialInherited
;
1107 else if (inherited
== 0)
1108 result
= eRulePartialReset
;
1110 result
= eRulePartialMixed
;
1112 if (structData
->callback
) {
1113 result
= (*structData
->callback
)(aRuleDataStruct
, result
);
1120 nsRuleNode::GetDisplayData(nsStyleContext
* aContext
)
1122 nsRuleDataDisplay displayData
; // Declare a struct with null CSS values.
1123 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Display
), mPresContext
, aContext
);
1124 ruleData
.mDisplayData
= &displayData
;
1126 return WalkRuleTree(eStyleStruct_Display
, aContext
, &ruleData
, &displayData
);
1130 nsRuleNode::GetVisibilityData(nsStyleContext
* aContext
)
1132 nsRuleDataDisplay displayData
; // Declare a struct with null CSS values.
1133 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Visibility
), mPresContext
, aContext
);
1134 ruleData
.mDisplayData
= &displayData
;
1136 return WalkRuleTree(eStyleStruct_Visibility
, aContext
, &ruleData
, &displayData
);
1140 nsRuleNode::GetTextData(nsStyleContext
* aContext
)
1142 nsRuleDataText textData
; // Declare a struct with null CSS values.
1143 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Text
), mPresContext
, aContext
);
1144 ruleData
.mTextData
= &textData
;
1146 return WalkRuleTree(eStyleStruct_Text
, aContext
, &ruleData
, &textData
);
1150 nsRuleNode::GetTextResetData(nsStyleContext
* aContext
)
1152 nsRuleDataText textData
; // Declare a struct with null CSS values.
1153 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(TextReset
), mPresContext
, aContext
);
1154 ruleData
.mTextData
= &textData
;
1156 const void* res
= WalkRuleTree(eStyleStruct_TextReset
, aContext
, &ruleData
, &textData
);
1157 textData
.mTextShadow
= nsnull
; // We are sharing with some style rule. It really owns the data.
1162 nsRuleNode::GetUserInterfaceData(nsStyleContext
* aContext
)
1164 nsRuleDataUserInterface uiData
; // Declare a struct with null CSS values.
1165 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(UserInterface
), mPresContext
, aContext
);
1166 ruleData
.mUserInterfaceData
= &uiData
;
1168 const void* res
= WalkRuleTree(eStyleStruct_UserInterface
, aContext
, &ruleData
, &uiData
);
1169 uiData
.mCursor
= nsnull
; // We are sharing with some style rule. It really owns the data.
1174 nsRuleNode::GetUIResetData(nsStyleContext
* aContext
)
1176 nsRuleDataUserInterface uiData
; // Declare a struct with null CSS values.
1177 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(UIReset
), mPresContext
, aContext
);
1178 ruleData
.mUserInterfaceData
= &uiData
;
1180 const void* res
= WalkRuleTree(eStyleStruct_UIReset
, aContext
, &ruleData
, &uiData
);
1185 nsRuleNode::GetFontData(nsStyleContext
* aContext
)
1187 nsRuleDataFont fontData
; // Declare a struct with null CSS values.
1188 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Font
), mPresContext
, aContext
);
1189 ruleData
.mFontData
= &fontData
;
1191 return WalkRuleTree(eStyleStruct_Font
, aContext
, &ruleData
, &fontData
);
1195 nsRuleNode::GetColorData(nsStyleContext
* aContext
)
1197 nsRuleDataColor colorData
; // Declare a struct with null CSS values.
1198 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Color
), mPresContext
, aContext
);
1199 ruleData
.mColorData
= &colorData
;
1201 return WalkRuleTree(eStyleStruct_Color
, aContext
, &ruleData
, &colorData
);
1205 nsRuleNode::GetBackgroundData(nsStyleContext
* aContext
)
1207 nsRuleDataColor colorData
; // Declare a struct with null CSS values.
1208 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Background
), mPresContext
, aContext
);
1209 ruleData
.mColorData
= &colorData
;
1211 return WalkRuleTree(eStyleStruct_Background
, aContext
, &ruleData
, &colorData
);
1215 nsRuleNode::GetMarginData(nsStyleContext
* aContext
)
1217 nsRuleDataMargin marginData
; // Declare a struct with null CSS values.
1218 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Margin
), mPresContext
, aContext
);
1219 ruleData
.mMarginData
= &marginData
;
1221 return WalkRuleTree(eStyleStruct_Margin
, aContext
, &ruleData
, &marginData
);
1225 nsRuleNode::GetBorderData(nsStyleContext
* aContext
)
1227 nsRuleDataMargin marginData
; // Declare a struct with null CSS values.
1228 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Border
), mPresContext
, aContext
);
1229 ruleData
.mMarginData
= &marginData
;
1231 return WalkRuleTree(eStyleStruct_Border
, aContext
, &ruleData
, &marginData
);
1235 nsRuleNode::GetPaddingData(nsStyleContext
* aContext
)
1237 nsRuleDataMargin marginData
; // Declare a struct with null CSS values.
1238 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Padding
), mPresContext
, aContext
);
1239 ruleData
.mMarginData
= &marginData
;
1241 return WalkRuleTree(eStyleStruct_Padding
, aContext
, &ruleData
, &marginData
);
1245 nsRuleNode::GetOutlineData(nsStyleContext
* aContext
)
1247 nsRuleDataMargin marginData
; // Declare a struct with null CSS values.
1248 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Outline
), mPresContext
, aContext
);
1249 ruleData
.mMarginData
= &marginData
;
1251 return WalkRuleTree(eStyleStruct_Outline
, aContext
, &ruleData
, &marginData
);
1255 nsRuleNode::GetListData(nsStyleContext
* aContext
)
1257 nsRuleDataList listData
; // Declare a struct with null CSS values.
1258 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(List
), mPresContext
, aContext
);
1259 ruleData
.mListData
= &listData
;
1261 return WalkRuleTree(eStyleStruct_List
, aContext
, &ruleData
, &listData
);
1265 nsRuleNode::GetPositionData(nsStyleContext
* aContext
)
1267 nsRuleDataPosition posData
; // Declare a struct with null CSS values.
1268 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Position
), mPresContext
, aContext
);
1269 ruleData
.mPositionData
= &posData
;
1271 return WalkRuleTree(eStyleStruct_Position
, aContext
, &ruleData
, &posData
);
1275 nsRuleNode::GetTableData(nsStyleContext
* aContext
)
1277 nsRuleDataTable tableData
; // Declare a struct with null CSS values.
1278 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Table
), mPresContext
, aContext
);
1279 ruleData
.mTableData
= &tableData
;
1281 return WalkRuleTree(eStyleStruct_Table
, aContext
, &ruleData
, &tableData
);
1285 nsRuleNode::GetTableBorderData(nsStyleContext
* aContext
)
1287 nsRuleDataTable tableData
; // Declare a struct with null CSS values.
1288 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(TableBorder
), mPresContext
, aContext
);
1289 ruleData
.mTableData
= &tableData
;
1291 return WalkRuleTree(eStyleStruct_TableBorder
, aContext
, &ruleData
, &tableData
);
1295 nsRuleNode::GetContentData(nsStyleContext
* aContext
)
1297 nsRuleDataContent contentData
; // Declare a struct with null CSS values.
1298 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Content
), mPresContext
, aContext
);
1299 ruleData
.mContentData
= &contentData
;
1301 const void* res
= WalkRuleTree(eStyleStruct_Content
, aContext
, &ruleData
, &contentData
);
1302 contentData
.mCounterIncrement
= contentData
.mCounterReset
= nsnull
;
1303 contentData
.mContent
= nsnull
; // We are sharing with some style rule. It really owns the data.
1308 nsRuleNode::GetQuotesData(nsStyleContext
* aContext
)
1310 nsRuleDataContent contentData
; // Declare a struct with null CSS values.
1311 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Quotes
), mPresContext
, aContext
);
1312 ruleData
.mContentData
= &contentData
;
1314 const void* res
= WalkRuleTree(eStyleStruct_Quotes
, aContext
, &ruleData
, &contentData
);
1315 contentData
.mQuotes
= nsnull
; // We are sharing with some style rule. It really owns the data.
1320 nsRuleNode::GetXULData(nsStyleContext
* aContext
)
1322 nsRuleDataXUL xulData
; // Declare a struct with null CSS values.
1323 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(XUL
), mPresContext
, aContext
);
1324 ruleData
.mXULData
= &xulData
;
1326 return WalkRuleTree(eStyleStruct_XUL
, aContext
, &ruleData
, &xulData
);
1330 nsRuleNode::GetColumnData(nsStyleContext
* aContext
)
1332 nsRuleDataColumn columnData
; // Declare a struct with null CSS values.
1333 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Column
), mPresContext
, aContext
);
1334 ruleData
.mColumnData
= &columnData
;
1336 return WalkRuleTree(eStyleStruct_Column
, aContext
, &ruleData
, &columnData
);
1341 nsRuleNode::GetSVGData(nsStyleContext
* aContext
)
1343 nsRuleDataSVG svgData
; // Declare a struct with null CSS values.
1344 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(SVG
), mPresContext
, aContext
);
1345 ruleData
.mSVGData
= &svgData
;
1347 const void *res
= WalkRuleTree(eStyleStruct_SVG
, aContext
, &ruleData
, &svgData
);
1348 svgData
.mStrokeDasharray
= nsnull
; // We are sharing with some style rule. It really owns the data.
1353 nsRuleNode::GetSVGResetData(nsStyleContext
* aContext
)
1355 nsRuleDataSVG svgData
; // Declare a struct with null CSS values.
1356 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(SVGReset
), mPresContext
, aContext
);
1357 ruleData
.mSVGData
= &svgData
;
1359 return WalkRuleTree(eStyleStruct_SVGReset
, aContext
, &ruleData
, &svgData
);
1364 nsRuleNode::WalkRuleTree(const nsStyleStructID aSID
,
1365 nsStyleContext
* aContext
,
1366 nsRuleData
* aRuleData
,
1367 nsRuleDataStruct
* aSpecificData
)
1369 // We start at the most specific rule in the tree.
1370 void* startStruct
= nsnull
;
1372 nsRuleNode
* ruleNode
= this;
1373 nsRuleNode
* highestNode
= nsnull
; // The highest node in the rule tree
1374 // that has the same properties
1375 // specified for struct |aSID| as
1377 nsRuleNode
* rootNode
= this; // After the loop below, this will be the
1378 // highest node that we've walked without
1379 // finding cached data on the rule tree.
1380 // If we don't find any cached data, it
1381 // will be the root. (XXX misnamed)
1382 RuleDetail detail
= eRuleNone
;
1383 PRUint32 bit
= nsCachedStyleData::GetBitForSID(aSID
);
1386 // See if this rule node has cached the fact that the remaining
1387 // nodes along this path specify no data whatsoever.
1388 if (ruleNode
->mNoneBits
& bit
)
1391 // If the dependent bit is set on a rule node for this struct, that
1392 // means its rule won't have any information to add, so skip it.
1393 // XXXldb I don't understand why we need to check |detail| here, but
1395 if (detail
== eRuleNone
)
1396 while (ruleNode
->mDependentBits
& bit
) {
1397 NS_ASSERTION(ruleNode
->mStyleData
.GetStyleData(aSID
) == nsnull
,
1398 "dependent bit with cached data makes no sense");
1399 // Climb up to the next rule in the tree (a less specific rule).
1400 rootNode
= ruleNode
;
1401 ruleNode
= ruleNode
->mParent
;
1402 NS_ASSERTION(!(ruleNode
->mNoneBits
& bit
), "can't have both bits set");
1405 // Check for cached data after the inner loop above -- otherwise
1407 startStruct
= ruleNode
->mStyleData
.GetStyleData(aSID
);
1409 break; // We found a rule with fully specified data. We don't
1410 // need to go up the tree any further, since the remainder
1411 // of this branch has already been computed.
1413 // Ask the rule to fill in the properties that it specifies.
1414 nsIStyleRule
*rule
= ruleNode
->mRule
;
1416 aRuleData
->mLevel
= ruleNode
->GetLevel();
1417 aRuleData
->mIsImportantRule
= ruleNode
->IsImportantRule();
1418 rule
->MapRuleInfoInto(aRuleData
);
1421 // Now we check to see how many properties have been specified by
1422 // the rules we've examined so far.
1423 RuleDetail oldDetail
= detail
;
1424 detail
= CheckSpecifiedProperties(aSID
, *aSpecificData
);
1426 if (oldDetail
== eRuleNone
&& detail
!= eRuleNone
)
1427 highestNode
= ruleNode
;
1429 if (detail
== eRuleFullReset
||
1430 detail
== eRuleFullMixed
||
1431 detail
== eRuleFullInherited
)
1432 break; // We don't need to examine any more rules. All properties
1433 // have been fully specified.
1435 // Climb up to the next rule in the tree (a less specific rule).
1436 rootNode
= ruleNode
;
1437 ruleNode
= ruleNode
->mParent
;
1440 NS_ASSERTION(!startStruct
|| (detail
!= eRuleFullReset
&&
1441 detail
!= eRuleFullMixed
&&
1442 detail
!= eRuleFullInherited
),
1443 "can't have start struct and be fully specified");
1445 PRBool isReset
= nsCachedStyleData::IsReset(aSID
);
1447 highestNode
= rootNode
;
1449 if (!aRuleData
->mCanStoreInRuleTree
)
1450 detail
= eRulePartialMixed
; // Treat as though some data is specified to avoid
1451 // the optimizations and force data computation.
1453 if (detail
== eRuleNone
&& startStruct
&& !aRuleData
->mPostResolveCallback
) {
1454 // We specified absolutely no rule information, but a parent rule in the tree
1455 // specified all the rule information. We set a bit along the branch from our
1456 // node in the tree to the node that specified the data that tells nodes on that
1457 // branch that they never need to examine their rules for this particular struct type
1459 PropagateDependentBit(bit
, ruleNode
);
1462 // FIXME Do we need to check for mPostResolveCallback?
1463 if ((!startStruct
&& !isReset
&&
1464 (detail
== eRuleNone
|| detail
== eRulePartialInherited
)) ||
1465 detail
== eRuleFullInherited
) {
1466 // We specified no non-inherited information and neither did any of
1467 // our parent rules.
1469 // We set a bit along the branch from the highest node (ruleNode)
1470 // down to our node (this) indicating that no non-inherited data was
1471 // specified. This bit is guaranteed to be set already on the path
1472 // from the highest node to the root node in the case where
1473 // (detail == eRuleNone), which is the most common case here.
1474 // We must check |!isReset| because the Compute*Data functions for
1475 // reset structs wouldn't handle none bits correctly.
1476 if (highestNode
!= this && !isReset
)
1477 PropagateNoneBit(bit
, highestNode
);
1479 // All information must necessarily be inherited from our parent style context.
1480 // In the absence of any computed data in the rule tree and with
1481 // no rules specified that didn't have values of 'inherit', we should check our parent.
1482 nsStyleContext
* parentContext
= aContext
->GetParent();
1483 if (parentContext
) {
1484 // We have a parent, and so we should just inherit from the parent.
1485 // Set the inherit bits on our context. These bits tell the style context that
1486 // it never has to go back to the rule tree for data. Instead the style context tree
1487 // should be walked to find the data.
1488 const void* parentStruct
= parentContext
->GetStyleData(aSID
);
1489 aContext
->AddStyleBit(bit
); // makes const_cast OK.
1490 aContext
->SetStyle(aSID
, const_cast<void*>(parentStruct
));
1491 return parentStruct
;
1494 // We are the root. In the case of fonts, the default values just
1495 // come from the pres context.
1496 return SetDefaultOnRoot(aSID
, aContext
);
1499 // We need to compute the data from the information that the rules specified.
1501 #define STYLE_STRUCT_TEST aSID
1502 #define STYLE_STRUCT(name, checkdata_cb, ctor_args) \
1503 res = Compute##name##Data(startStruct, *aSpecificData, aContext, \
1504 highestNode, detail, !aRuleData->mCanStoreInRuleTree);
1505 #include "nsStyleStructList.h"
1507 #undef STYLE_STRUCT_TEST
1509 // If we have a post-resolve callback, handle that now.
1510 if (aRuleData
->mPostResolveCallback
&& (NS_LIKELY(res
!= nsnull
)))
1511 (*aRuleData
->mPostResolveCallback
)(const_cast<void*>(res
), aRuleData
);
1513 // Now return the result.
1518 nsRuleNode::SetDefaultOnRoot(const nsStyleStructID aSID
, nsStyleContext
* aContext
)
1521 case eStyleStruct_Font
:
1523 nsStyleFont
* fontData
= new (mPresContext
) nsStyleFont(mPresContext
);
1524 if (NS_LIKELY(fontData
!= nsnull
)) {
1525 nscoord minimumFontSize
=
1526 mPresContext
->GetCachedIntPref(kPresContext_MinimumFontSize
);
1528 if (minimumFontSize
> 0 && !mPresContext
->IsChrome()) {
1529 fontData
->mFont
.size
= PR_MAX(fontData
->mSize
, minimumFontSize
);
1532 fontData
->mFont
.size
= fontData
->mSize
;
1534 aContext
->SetStyle(eStyleStruct_Font
, fontData
);
1538 case eStyleStruct_Display
:
1540 nsStyleDisplay
* disp
= new (mPresContext
) nsStyleDisplay();
1541 if (NS_LIKELY(disp
!= nsnull
)) {
1542 aContext
->SetStyle(eStyleStruct_Display
, disp
);
1546 case eStyleStruct_Visibility
:
1548 nsStyleVisibility
* vis
= new (mPresContext
) nsStyleVisibility(mPresContext
);
1549 if (NS_LIKELY(vis
!= nsnull
)) {
1550 aContext
->SetStyle(eStyleStruct_Visibility
, vis
);
1554 case eStyleStruct_Text
:
1556 nsStyleText
* text
= new (mPresContext
) nsStyleText();
1557 if (NS_LIKELY(text
!= nsnull
)) {
1558 aContext
->SetStyle(eStyleStruct_Text
, text
);
1562 case eStyleStruct_TextReset
:
1564 nsStyleTextReset
* text
= new (mPresContext
) nsStyleTextReset();
1565 if (NS_LIKELY(text
!= nsnull
)) {
1566 aContext
->SetStyle(eStyleStruct_TextReset
, text
);
1570 case eStyleStruct_Color
:
1572 nsStyleColor
* color
= new (mPresContext
) nsStyleColor(mPresContext
);
1573 if (NS_LIKELY(color
!= nsnull
)) {
1574 aContext
->SetStyle(eStyleStruct_Color
, color
);
1578 case eStyleStruct_Background
:
1580 nsStyleBackground
* bg
= new (mPresContext
) nsStyleBackground(mPresContext
);
1581 if (NS_LIKELY(bg
!= nsnull
)) {
1582 aContext
->SetStyle(eStyleStruct_Background
, bg
);
1586 case eStyleStruct_Margin
:
1588 nsStyleMargin
* margin
= new (mPresContext
) nsStyleMargin();
1589 if (NS_LIKELY(margin
!= nsnull
)) {
1590 aContext
->SetStyle(eStyleStruct_Margin
, margin
);
1594 case eStyleStruct_Border
:
1596 nsStyleBorder
* border
= new (mPresContext
) nsStyleBorder(mPresContext
);
1597 if (NS_LIKELY(border
!= nsnull
)) {
1598 aContext
->SetStyle(eStyleStruct_Border
, border
);
1602 case eStyleStruct_Padding
:
1604 nsStylePadding
* padding
= new (mPresContext
) nsStylePadding();
1605 if (NS_LIKELY(padding
!= nsnull
)) {
1606 aContext
->SetStyle(eStyleStruct_Padding
, padding
);
1610 case eStyleStruct_Outline
:
1612 nsStyleOutline
* outline
= new (mPresContext
) nsStyleOutline(mPresContext
);
1613 if (NS_LIKELY(outline
!= nsnull
)) {
1614 aContext
->SetStyle(eStyleStruct_Outline
, outline
);
1618 case eStyleStruct_List
:
1620 nsStyleList
* list
= new (mPresContext
) nsStyleList();
1621 if (NS_LIKELY(list
!= nsnull
)) {
1622 aContext
->SetStyle(eStyleStruct_List
, list
);
1626 case eStyleStruct_Position
:
1628 nsStylePosition
* pos
= new (mPresContext
) nsStylePosition();
1629 if (NS_LIKELY(pos
!= nsnull
)) {
1630 aContext
->SetStyle(eStyleStruct_Position
, pos
);
1634 case eStyleStruct_Table
:
1636 nsStyleTable
* table
= new (mPresContext
) nsStyleTable();
1637 if (NS_LIKELY(table
!= nsnull
)) {
1638 aContext
->SetStyle(eStyleStruct_Table
, table
);
1642 case eStyleStruct_TableBorder
:
1644 nsStyleTableBorder
* table
= new (mPresContext
) nsStyleTableBorder(mPresContext
);
1645 if (NS_LIKELY(table
!= nsnull
)) {
1646 aContext
->SetStyle(eStyleStruct_TableBorder
, table
);
1650 case eStyleStruct_Content
:
1652 nsStyleContent
* content
= new (mPresContext
) nsStyleContent();
1653 if (NS_LIKELY(content
!= nsnull
)) {
1654 aContext
->SetStyle(eStyleStruct_Content
, content
);
1658 case eStyleStruct_Quotes
:
1660 nsStyleQuotes
* quotes
= new (mPresContext
) nsStyleQuotes();
1661 if (NS_LIKELY(quotes
!= nsnull
)) {
1662 aContext
->SetStyle(eStyleStruct_Quotes
, quotes
);
1666 case eStyleStruct_UserInterface
:
1668 nsStyleUserInterface
* ui
= new (mPresContext
) nsStyleUserInterface();
1669 if (NS_LIKELY(ui
!= nsnull
)) {
1670 aContext
->SetStyle(eStyleStruct_UserInterface
, ui
);
1674 case eStyleStruct_UIReset
:
1676 nsStyleUIReset
* ui
= new (mPresContext
) nsStyleUIReset();
1677 if (NS_LIKELY(ui
!= nsnull
)) {
1678 aContext
->SetStyle(eStyleStruct_UIReset
, ui
);
1683 case eStyleStruct_XUL
:
1685 nsStyleXUL
* xul
= new (mPresContext
) nsStyleXUL();
1686 if (NS_LIKELY(xul
!= nsnull
)) {
1687 aContext
->SetStyle(eStyleStruct_XUL
, xul
);
1692 case eStyleStruct_Column
:
1694 nsStyleColumn
* column
= new (mPresContext
) nsStyleColumn();
1695 if (NS_LIKELY(column
!= nsnull
)) {
1696 aContext
->SetStyle(eStyleStruct_Column
, column
);
1702 case eStyleStruct_SVG
:
1704 nsStyleSVG
* svg
= new (mPresContext
) nsStyleSVG();
1705 if (NS_LIKELY(svg
!= nsnull
)) {
1706 aContext
->SetStyle(eStyleStruct_SVG
, svg
);
1711 case eStyleStruct_SVGReset
:
1713 nsStyleSVGReset
* svgReset
= new (mPresContext
) nsStyleSVGReset();
1714 if (NS_LIKELY(svgReset
!= nsnull
)) {
1715 aContext
->SetStyle(eStyleStruct_SVGReset
, svgReset
);
1725 * This function handles cascading of *-left or *-right box properties
1726 * against *-start (which is L for LTR and R for RTL) or *-end (which is
1727 * R for LTR and L for RTL).
1729 * Cascading these properties correctly is hard because we need to
1730 * cascade two properties as one, but which two properties depends on a
1731 * third property ('direction'). We solve this by treating each of
1732 * these properties (say, 'margin-start') as a shorthand that sets a
1733 * property containing the value of the property specified
1734 * ('margin-start-value') and sets a pair of properties
1735 * ('margin-left-ltr-source' and 'margin-right-rtl-source') saying which
1736 * of the properties we use. Thus, when we want to compute the value of
1737 * 'margin-left' when 'direction' is 'ltr', we look at the value of
1738 * 'margin-left-ltr-source', which tells us whether to use the highest
1739 * 'margin-left' in the cascade or the highest 'margin-start'.
1741 * Finally, since we can compute the normal (*-left and *-right)
1742 * properties in a loop, this function works by modifying the data we
1743 * will use in that loop (which the caller must copy from the const
1747 nsRuleNode::AdjustLogicalBoxProp(nsStyleContext
* aContext
,
1748 const nsCSSValue
& aLTRSource
,
1749 const nsCSSValue
& aRTLSource
,
1750 const nsCSSValue
& aLTRLogicalValue
,
1751 const nsCSSValue
& aRTLLogicalValue
,
1753 nsCSSRect
& aValueRect
,
1756 PRBool LTRlogical
= aLTRSource
.GetUnit() == eCSSUnit_Enumerated
&&
1757 aLTRSource
.GetIntValue() == NS_BOXPROP_SOURCE_LOGICAL
;
1758 PRBool RTLlogical
= aRTLSource
.GetUnit() == eCSSUnit_Enumerated
&&
1759 aRTLSource
.GetIntValue() == NS_BOXPROP_SOURCE_LOGICAL
;
1760 if (LTRlogical
|| RTLlogical
) {
1761 // We can't cache anything on the rule tree if we use any data from
1762 // the style context, since data cached in the rule tree could be
1763 // used with a style context with a different value.
1764 aInherited
= PR_TRUE
;
1765 PRUint8 dir
= aContext
->GetStyleVisibility()->mDirection
;
1767 if (dir
== NS_STYLE_DIRECTION_LTR
) {
1769 aValueRect
.*(nsCSSRect::sides
[aSide
]) = aLTRLogicalValue
;
1772 aValueRect
.*(nsCSSRect::sides
[aSide
]) = aRTLLogicalValue
;
1778 * Begin an nsRuleNode::Compute*Data function for an inherited struct.
1780 * @param type_ The nsStyle* type this function computes.
1781 * @param ctorargs_ The arguments used for the default nsStyle* constructor.
1782 * @param data_ Variable (declared here) holding the result of this
1784 * @param parentdata_ Variable (declared here) holding the parent style
1785 * context's data for this struct.
1786 * @param rdtype_ The nsCSS* struct type used to compute this struct's data.
1787 * @param rdata_ Variable (declared here) holding the nsCSS* used here.
1789 #define COMPUTE_START_INHERITED(type_, ctorargs_, data_, parentdata_, rdtype_, rdata_) \
1790 NS_ASSERTION(aRuleDetail != eRuleFullInherited, \
1791 "should not have bothered calling Compute*Data"); \
1793 nsStyleContext* parentContext = aContext->GetParent(); \
1795 const nsRuleData##rdtype_& rdata_ = \
1796 static_cast<const nsRuleData##rdtype_&>(aData); \
1797 nsStyle##type_* data_ = nsnull; \
1798 const nsStyle##type_* parentdata_ = nsnull; \
1799 PRBool inherited = aInherited; \
1801 /* If |inherited| might be false by the time we're done, we can't call */ \
1802 /* parentContext->GetStyle##type_() since it could recur into setting */ \
1803 /* the same struct on the same rule node, causing a leak. */ \
1804 if (parentContext && aRuleDetail != eRuleFullReset && \
1805 (!aStartStruct || (aRuleDetail != eRulePartialReset && \
1806 aRuleDetail != eRuleNone))) \
1807 parentdata_ = parentContext->GetStyle##type_(); \
1809 /* We only need to compute the delta between this computed data and */ \
1810 /* our computed data. */ \
1811 data_ = new (mPresContext) \
1812 nsStyle##type_(*static_cast<nsStyle##type_*>(aStartStruct)); \
1814 if (aRuleDetail != eRuleFullMixed && aRuleDetail != eRuleFullReset) { \
1815 /* No question. We will have to inherit. Go ahead and init */ \
1816 /* with inherited vals from parent. */ \
1817 inherited = PR_TRUE; \
1819 data_ = new (mPresContext) nsStyle##type_(*parentdata_); \
1821 data_ = new (mPresContext) nsStyle##type_ ctorargs_; \
1824 data_ = new (mPresContext) nsStyle##type_ ctorargs_; \
1827 if (NS_UNLIKELY(!data_)) \
1828 return nsnull; /* Out Of Memory */ \
1830 parentdata_ = data_;
1833 * Begin an nsRuleNode::Compute*Data function for a reset struct.
1835 * @param type_ The nsStyle* type this function computes.
1836 * @param ctorargs_ The arguments used for the default nsStyle* constructor.
1837 * @param data_ Variable (declared here) holding the result of this
1839 * @param parentdata_ Variable (declared here) holding the parent style
1840 * context's data for this struct.
1841 * @param rdtype_ The nsCSS* struct type used to compute this struct's data.
1842 * @param rdata_ Variable (declared here) holding the nsCSS* used here.
1844 #define COMPUTE_START_RESET(type_, ctorargs_, data_, parentdata_, rdtype_, rdata_) \
1845 NS_ASSERTION(aRuleDetail != eRuleFullInherited, \
1846 "should not have bothered calling Compute*Data"); \
1848 nsStyleContext* parentContext = aContext->GetParent(); \
1849 if (parentContext && \
1850 parentContext->GetPseudoType() == nsCSSPseudoElements::firstLine) { \
1851 /* Reset structs don't inherit from first-line */ \
1852 parentContext = parentContext->GetParent(); \
1855 const nsRuleData##rdtype_& rdata_ = \
1856 static_cast<const nsRuleData##rdtype_&>(aData); \
1857 nsStyle##type_* data_; \
1859 /* We only need to compute the delta between this computed data and */ \
1860 /* our computed data. */ \
1861 data_ = new (mPresContext) \
1862 nsStyle##type_(*static_cast<nsStyle##type_*>(aStartStruct)); \
1864 data_ = new (mPresContext) nsStyle##type_ ctorargs_; \
1866 if (NS_UNLIKELY(!data_)) \
1867 return nsnull; /* Out Of Memory */ \
1869 /* If |inherited| might be false by the time we're done, we can't call */ \
1870 /* parentContext->GetStyle##type_() since it could recur into setting */ \
1871 /* the same struct on the same rule node, causing a leak. */ \
1872 const nsStyle##type_* parentdata_ = data_; \
1873 if (parentContext && \
1874 aRuleDetail != eRuleFullReset && \
1875 aRuleDetail != eRulePartialReset && \
1876 aRuleDetail != eRuleNone) \
1877 parentdata_ = parentContext->GetStyle##type_(); \
1878 PRBool inherited = aInherited;
1881 * Begin an nsRuleNode::Compute*Data function for an inherited struct.
1883 * @param type_ The nsStyle* type this function computes.
1884 * @param data_ Variable holding the result of this function.
1886 #define COMPUTE_END_INHERITED(type_, data_) \
1888 /* We inherited, and therefore can't be cached in the rule node. We */ \
1889 /* have to be put right on the style context. */ \
1890 aContext->SetStyle(eStyleStruct_##type_, data_); \
1892 /* We were fully specified and can therefore be cached right on the */ \
1894 if (!aHighestNode->mStyleData.mInheritedData) { \
1895 aHighestNode->mStyleData.mInheritedData = \
1896 new (mPresContext) nsInheritedStyleData; \
1897 if (NS_UNLIKELY(!aHighestNode->mStyleData.mInheritedData)) { \
1898 data_->Destroy(mPresContext); \
1902 aHighestNode->mStyleData.mInheritedData->m##type_##Data = data_; \
1903 /* Propagate the bit down. */ \
1904 PropagateDependentBit(NS_STYLE_INHERIT_BIT(type_), aHighestNode); \
1910 * Begin an nsRuleNode::Compute*Data function for a reset struct.
1912 * @param type_ The nsStyle* type this function computes.
1913 * @param data_ Variable holding the result of this function.
1915 #define COMPUTE_END_RESET(type_, data_) \
1917 /* We inherited, and therefore can't be cached in the rule node. We */ \
1918 /* have to be put right on the style context. */ \
1919 aContext->SetStyle(eStyleStruct_##type_, data_); \
1921 /* We were fully specified and can therefore be cached right on the */ \
1923 if (!aHighestNode->mStyleData.mResetData) { \
1924 aHighestNode->mStyleData.mResetData = \
1925 new (mPresContext) nsResetStyleData; \
1926 if (NS_UNLIKELY(!aHighestNode->mStyleData.mResetData)) { \
1927 data_->Destroy(mPresContext); \
1931 aHighestNode->mStyleData.mResetData->m##type_##Data = data_; \
1932 /* Propagate the bit down. */ \
1933 PropagateDependentBit(NS_STYLE_INHERIT_BIT(type_), aHighestNode); \
1939 // This function figures out how much scaling should be suppressed to
1940 // satisfy scriptminsize. This is our attempt to implement
1941 // http://www.w3.org/TR/MathML2/chapter3.html#id.3.3.4.2.2
1942 // This is called after mScriptLevel, mScriptMinSize and mScriptSizeMultiplier
1943 // have been set in aFont.
1945 // Here are the invariants we enforce:
1946 // 1) A decrease in size must not reduce the size below minscriptsize.
1947 // 2) An increase in size must not increase the size above the size we would
1948 // have if minscriptsize had not been applied anywhere.
1949 // 3) The scriptlevel-induced size change must between 1.0 and the parent's
1950 // scriptsizemultiplier^(new script level - old script level), as close to the
1951 // latter as possible subject to constraints 1 and 2.
1953 ComputeScriptLevelSize(const nsStyleFont
* aFont
, const nsStyleFont
* aParentFont
,
1954 nsPresContext
* aPresContext
, nscoord
* aUnconstrainedSize
)
1956 PRInt32 scriptLevelChange
=
1957 aFont
->mScriptLevel
- aParentFont
->mScriptLevel
;
1958 if (scriptLevelChange
== 0) {
1959 *aUnconstrainedSize
= aParentFont
->mScriptUnconstrainedSize
;
1960 // Constraint #3 says that we cannot change size, and #1 and #2 are always
1961 // satisfied with no change. It's important this be fast because it covers
1962 // all non-MathML content.
1963 return aParentFont
->mSize
;
1966 // Compute actual value of minScriptSize
1967 nscoord minScriptSize
=
1968 nsStyleFont::ZoomText(aPresContext
, aParentFont
->mScriptMinSize
);
1970 double scriptLevelScale
=
1971 pow(aParentFont
->mScriptSizeMultiplier
, scriptLevelChange
);
1972 // Compute the size we would have had if minscriptsize had never been
1973 // applied, also prevent overflow (bug 413274)
1974 *aUnconstrainedSize
=
1975 NSToCoordRound(PR_MIN(aParentFont
->mScriptUnconstrainedSize
*scriptLevelScale
,
1977 // Compute the size we could get via scriptlevel change
1978 nscoord scriptLevelSize
=
1979 NSToCoordRound(PR_MIN(aParentFont
->mSize
*scriptLevelScale
,
1981 if (scriptLevelScale
<= 1.0) {
1982 if (aParentFont
->mSize
<= minScriptSize
) {
1983 // We can't decrease the font size at all, so just stick to no change
1984 // (authors are allowed to explicitly set the font size smaller than
1986 return aParentFont
->mSize
;
1988 // We can decrease, so apply constraint #1
1989 return PR_MAX(minScriptSize
, scriptLevelSize
);
1991 // scriptminsize can only make sizes larger than the unconstrained size
1992 NS_ASSERTION(*aUnconstrainedSize
<= scriptLevelSize
, "How can this ever happen?");
1993 // Apply constraint #2
1994 return PR_MIN(scriptLevelSize
, PR_MAX(*aUnconstrainedSize
, minScriptSize
));
2000 nsRuleNode::SetFontSize(nsPresContext
* aPresContext
,
2001 const nsRuleDataFont
& aFontData
,
2002 const nsStyleFont
* aFont
,
2003 const nsStyleFont
* aParentFont
,
2005 const nsFont
& aSystemFont
,
2006 nscoord aParentSize
,
2007 nscoord aScriptLevelAdjustedParentSize
,
2008 PRBool aUsedStartStruct
,
2011 PRBool zoom
= PR_FALSE
;
2012 PRInt32 baseSize
= (PRInt32
) aPresContext
->
2013 GetDefaultFont(aFont
->mFlags
& NS_STYLE_FONT_FACE_MASK
)->size
;
2014 if (eCSSUnit_Enumerated
== aFontData
.mSize
.GetUnit()) {
2015 PRInt32 value
= aFontData
.mSize
.GetIntValue();
2016 PRInt32 scaler
= aPresContext
->FontScaler();
2017 float scaleFactor
= nsStyleUtil::GetScalingFactor(scaler
);
2020 if ((NS_STYLE_FONT_SIZE_XXSMALL
<= value
) &&
2021 (value
<= NS_STYLE_FONT_SIZE_XXLARGE
)) {
2022 *aSize
= nsStyleUtil::CalcFontPointSize(value
, baseSize
,
2023 scaleFactor
, aPresContext
, eFontSize_CSS
);
2025 else if (NS_STYLE_FONT_SIZE_XXXLARGE
== value
) {
2026 // <font size="7"> is not specified in CSS, so we don't use eFontSize_CSS.
2027 *aSize
= nsStyleUtil::CalcFontPointSize(value
, baseSize
,
2028 scaleFactor
, aPresContext
);
2030 else if (NS_STYLE_FONT_SIZE_LARGER
== value
||
2031 NS_STYLE_FONT_SIZE_SMALLER
== value
) {
2032 aInherited
= PR_TRUE
;
2034 // Un-zoom so we use the tables correctly. We'll then rezoom due
2035 // to the |zoom = PR_TRUE| above.
2036 // Note that relative units here use the parent's size unadjusted
2037 // for scriptlevel changes. A scriptlevel change between us and the parent
2038 // is simply ignored.
2039 nscoord parentSize
=
2040 nsStyleFont::UnZoomText(aPresContext
, aParentSize
);
2042 if (NS_STYLE_FONT_SIZE_LARGER
== value
) {
2043 *aSize
= nsStyleUtil::FindNextLargerFontSize(parentSize
,
2044 baseSize
, scaleFactor
, aPresContext
, eFontSize_CSS
);
2045 NS_ASSERTION(*aSize
> parentSize
,
2046 "FindNextLargerFontSize failed");
2049 *aSize
= nsStyleUtil::FindNextSmallerFontSize(parentSize
,
2050 baseSize
, scaleFactor
, aPresContext
, eFontSize_CSS
);
2051 NS_ASSERTION(*aSize
< parentSize
||
2052 parentSize
<= nsPresContext::CSSPixelsToAppUnits(1),
2053 "FindNextSmallerFontSize failed");
2056 NS_NOTREACHED("unexpected value");
2059 else if (aFontData
.mSize
.IsLengthUnit()) {
2060 // Note that font-based length units use the parent's size unadjusted
2061 // for scriptlevel changes. A scriptlevel change between us and the parent
2062 // is simply ignored.
2063 *aSize
= CalcLengthWith(aFontData
.mSize
, aParentSize
, aParentFont
, nsnull
,
2064 aPresContext
, aInherited
);
2065 zoom
= aFontData
.mSize
.IsFixedLengthUnit() ||
2066 aFontData
.mSize
.GetUnit() == eCSSUnit_Pixel
;
2068 else if (eCSSUnit_Percent
== aFontData
.mSize
.GetUnit()) {
2069 aInherited
= PR_TRUE
;
2070 // Note that % units use the parent's size unadjusted for scriptlevel
2071 // changes. A scriptlevel change between us and the parent is simply
2073 *aSize
= NSToCoordRound(aParentSize
*
2074 aFontData
.mSize
.GetPercentValue());
2077 else if (eCSSUnit_System_Font
== aFontData
.mSize
.GetUnit()) {
2078 // this becomes our cascading size
2079 *aSize
= aSystemFont
.size
;
2082 else if (eCSSUnit_Inherit
== aFontData
.mSize
.GetUnit()) {
2083 aInherited
= PR_TRUE
;
2084 // We apply scriptlevel change for this case, because the default is
2085 // to inherit and we don't want explicit "inherit" to differ from the
2087 *aSize
= aScriptLevelAdjustedParentSize
;
2090 else if (eCSSUnit_Initial
== aFontData
.mSize
.GetUnit()) {
2091 // The initial value is 'medium', which has magical sizing based on
2092 // the generic font family, so do that here too.
2096 NS_ASSERTION(eCSSUnit_Null
== aFontData
.mSize
.GetUnit(),
2097 "What kind of font-size value is this?");
2099 // if aUsedStartStruct is true, then every single property in the
2100 // font struct is being set all at once. This means scriptlevel is not
2101 // going to have any influence on the font size; there is no need to
2102 // do anything here.
2103 if (!aUsedStartStruct
&& aParentSize
!= aScriptLevelAdjustedParentSize
) {
2104 // There was no rule affecting the size but the size has been
2105 // affected by the parent's size via scriptlevel change. So treat
2106 // this as inherited.
2107 aInherited
= PR_TRUE
;
2108 *aSize
= aScriptLevelAdjustedParentSize
;
2113 // We want to zoom the cascaded size so that em-based measurements,
2114 // line-heights, etc., work.
2116 *aSize
= nsStyleFont::ZoomText(aPresContext
, *aSize
);
2120 static PRInt8
ClampTo8Bit(PRInt32 aValue
) {
2125 return PRInt8(aValue
);
2129 nsRuleNode::SetFont(nsPresContext
* aPresContext
, nsStyleContext
* aContext
,
2130 nscoord aMinFontSize
,
2131 PRUint8 aGenericFontID
, const nsRuleDataFont
& aFontData
,
2132 const nsStyleFont
* aParentFont
,
2133 nsStyleFont
* aFont
, PRBool aUsedStartStruct
,
2136 const nsFont
* defaultVariableFont
=
2137 aPresContext
->GetDefaultFont(kPresContext_DefaultVariableFont_ID
);
2139 // -moz-system-font: enum (never inherit!)
2141 if (eCSSUnit_Enumerated
== aFontData
.mSystemFont
.GetUnit()) {
2142 nsSystemFontID sysID
;
2143 switch (aFontData
.mSystemFont
.GetIntValue()) {
2144 case NS_STYLE_FONT_CAPTION
: sysID
= eSystemFont_Caption
; break; // css2
2145 case NS_STYLE_FONT_ICON
: sysID
= eSystemFont_Icon
; break;
2146 case NS_STYLE_FONT_MENU
: sysID
= eSystemFont_Menu
; break;
2147 case NS_STYLE_FONT_MESSAGE_BOX
: sysID
= eSystemFont_MessageBox
; break;
2148 case NS_STYLE_FONT_SMALL_CAPTION
: sysID
= eSystemFont_SmallCaption
; break;
2149 case NS_STYLE_FONT_STATUS_BAR
: sysID
= eSystemFont_StatusBar
; break;
2150 case NS_STYLE_FONT_WINDOW
: sysID
= eSystemFont_Window
; break; // css3
2151 case NS_STYLE_FONT_DOCUMENT
: sysID
= eSystemFont_Document
; break;
2152 case NS_STYLE_FONT_WORKSPACE
: sysID
= eSystemFont_Workspace
; break;
2153 case NS_STYLE_FONT_DESKTOP
: sysID
= eSystemFont_Desktop
; break;
2154 case NS_STYLE_FONT_INFO
: sysID
= eSystemFont_Info
; break;
2155 case NS_STYLE_FONT_DIALOG
: sysID
= eSystemFont_Dialog
; break;
2156 case NS_STYLE_FONT_BUTTON
: sysID
= eSystemFont_Button
; break;
2157 case NS_STYLE_FONT_PULL_DOWN_MENU
:sysID
= eSystemFont_PullDownMenu
; break;
2158 case NS_STYLE_FONT_LIST
: sysID
= eSystemFont_List
; break;
2159 case NS_STYLE_FONT_FIELD
: sysID
= eSystemFont_Field
; break;
2162 // GetSystemFont sets the font face but not necessarily the size
2163 // XXX Or at least it used to -- no longer true for thebes. Maybe
2164 // it should be again, though.
2165 systemFont
.size
= defaultVariableFont
->size
;
2167 if (NS_FAILED(aPresContext
->DeviceContext()->GetSystemFont(sysID
,
2169 systemFont
.name
= defaultVariableFont
->name
;
2172 // XXXldb All of this platform-specific stuff should be in the
2173 // nsIDeviceContext implementations, not here.
2177 // As far as I can tell the system default fonts and sizes for
2178 // on MS-Windows for Buttons, Listboxes/Comboxes and Text Fields are
2179 // all pre-determined and cannot be changed by either the control panel
2180 // or programmtically.
2183 // Fields (text fields)
2184 // Button and Selects (listboxes/comboboxes)
2185 // We use whatever font is defined by the system. Which it appears
2186 // (and the assumption is) it is always a proportional font. Then we
2187 // always use 2 points smaller than what the browser has defined as
2188 // the default proportional font.
2189 case eSystemFont_Field
:
2190 case eSystemFont_Button
:
2191 case eSystemFont_List
:
2192 // Assumption: system defined font is proportional
2194 PR_MAX(defaultVariableFont
->size
- aPresContext
->PointsToAppUnits(2), 0);
2199 // In case somebody explicitly used -moz-use-system-font.
2200 systemFont
= *defaultVariableFont
;
2204 // font-family: string list, enum, inherit
2205 NS_ASSERTION(eCSSUnit_Enumerated
!= aFontData
.mFamily
.GetUnit(),
2206 "system fonts should not be in mFamily anymore");
2207 if (eCSSUnit_String
== aFontData
.mFamily
.GetUnit()) {
2208 // set the correct font if we are using DocumentFonts OR we are overriding for XUL
2210 if (aGenericFontID
== kGenericFont_NONE
) {
2211 // only bother appending fallback fonts if this isn't a fallback generic font itself
2212 if (!aFont
->mFont
.name
.IsEmpty())
2213 aFont
->mFont
.name
.Append((PRUnichar
)',');
2214 // defaultVariableFont.name should always be "serif" or "sans-serif".
2215 aFont
->mFont
.name
.Append(defaultVariableFont
->name
);
2217 aFont
->mFont
.familyNameQuirks
=
2218 (aPresContext
->CompatibilityMode() == eCompatibility_NavQuirks
&&
2219 aFontData
.mFamilyFromHTML
);
2220 aFont
->mFont
.systemFont
= PR_FALSE
;
2221 aFont
->mFlags
&= ~NS_STYLE_FONT_FACE_MASK
;
2222 // Technically this is redundant with the code below, but it's good
2223 // to have since we'll still want it once we get rid of
2224 // SetGenericFont (bug 380915).
2225 aFont
->mFlags
|= aGenericFontID
;
2227 else if (eCSSUnit_System_Font
== aFontData
.mFamily
.GetUnit()) {
2228 aFont
->mFont
.name
= systemFont
.name
;
2229 aFont
->mFont
.familyNameQuirks
= PR_FALSE
;
2230 aFont
->mFont
.systemFont
= PR_TRUE
;
2231 aFont
->mFlags
&= ~NS_STYLE_FONT_FACE_MASK
;
2233 else if (eCSSUnit_Inherit
== aFontData
.mFamily
.GetUnit()) {
2234 aInherited
= PR_TRUE
;
2235 aFont
->mFont
.name
= aParentFont
->mFont
.name
;
2236 aFont
->mFont
.familyNameQuirks
= aParentFont
->mFont
.familyNameQuirks
;
2237 aFont
->mFont
.systemFont
= aParentFont
->mFont
.systemFont
;
2238 aFont
->mFlags
&= ~NS_STYLE_FONT_FACE_MASK
;
2239 aFont
->mFlags
|= (aParentFont
->mFlags
& NS_STYLE_FONT_FACE_MASK
);
2241 else if (eCSSUnit_Initial
== aFontData
.mFamily
.GetUnit()) {
2242 aFont
->mFont
.name
= defaultVariableFont
->name
;
2243 aFont
->mFont
.familyNameQuirks
= PR_FALSE
;
2244 aFont
->mFont
.systemFont
= defaultVariableFont
->systemFont
;
2245 aFont
->mFlags
&= ~NS_STYLE_FONT_FACE_MASK
;
2248 // When we're in the loop in SetGenericFont, we must ensure that we
2249 // always keep aFont->mFlags set to the correct generic. But we have
2250 // to be careful not to touch it when we're called directly from
2251 // ComputeFontData, because we could have a start struct.
2252 if (aGenericFontID
!= kGenericFont_NONE
) {
2253 aFont
->mFlags
&= ~NS_STYLE_FONT_FACE_MASK
;
2254 aFont
->mFlags
|= aGenericFontID
;
2257 // font-style: enum, normal, inherit
2258 if (eCSSUnit_Enumerated
== aFontData
.mStyle
.GetUnit()) {
2259 aFont
->mFont
.style
= aFontData
.mStyle
.GetIntValue();
2261 else if (eCSSUnit_Normal
== aFontData
.mStyle
.GetUnit()) {
2262 aFont
->mFont
.style
= NS_STYLE_FONT_STYLE_NORMAL
;
2264 else if (eCSSUnit_System_Font
== aFontData
.mStyle
.GetUnit()) {
2265 aFont
->mFont
.style
= systemFont
.style
;
2267 else if (eCSSUnit_Inherit
== aFontData
.mStyle
.GetUnit()) {
2268 aInherited
= PR_TRUE
;
2269 aFont
->mFont
.style
= aParentFont
->mFont
.style
;
2271 else if (eCSSUnit_Initial
== aFontData
.mStyle
.GetUnit()) {
2272 aFont
->mFont
.style
= defaultVariableFont
->style
;
2275 // font-variant: enum, normal, inherit
2276 if (eCSSUnit_Enumerated
== aFontData
.mVariant
.GetUnit()) {
2277 aFont
->mFont
.variant
= aFontData
.mVariant
.GetIntValue();
2279 else if (eCSSUnit_Normal
== aFontData
.mVariant
.GetUnit()) {
2280 aFont
->mFont
.variant
= NS_STYLE_FONT_VARIANT_NORMAL
;
2282 else if (eCSSUnit_System_Font
== aFontData
.mVariant
.GetUnit()) {
2283 aFont
->mFont
.variant
= systemFont
.variant
;
2285 else if (eCSSUnit_Inherit
== aFontData
.mVariant
.GetUnit()) {
2286 aInherited
= PR_TRUE
;
2287 aFont
->mFont
.variant
= aParentFont
->mFont
.variant
;
2289 else if (eCSSUnit_Initial
== aFontData
.mVariant
.GetUnit()) {
2290 aFont
->mFont
.variant
= defaultVariableFont
->variant
;
2293 // font-weight: int, enum, normal, inherit
2294 if (eCSSUnit_Integer
== aFontData
.mWeight
.GetUnit()) {
2295 aFont
->mFont
.weight
= aFontData
.mWeight
.GetIntValue();
2297 else if (eCSSUnit_Enumerated
== aFontData
.mWeight
.GetUnit()) {
2298 PRInt32 value
= aFontData
.mWeight
.GetIntValue();
2300 case NS_STYLE_FONT_WEIGHT_NORMAL
:
2301 case NS_STYLE_FONT_WEIGHT_BOLD
:
2302 aFont
->mFont
.weight
= value
;
2304 case NS_STYLE_FONT_WEIGHT_BOLDER
:
2305 case NS_STYLE_FONT_WEIGHT_LIGHTER
:
2306 aInherited
= PR_TRUE
;
2307 aFont
->mFont
.weight
= nsStyleUtil::ConstrainFontWeight(aParentFont
->mFont
.weight
+ value
);
2311 else if (eCSSUnit_Normal
== aFontData
.mWeight
.GetUnit()) {
2312 aFont
->mFont
.weight
= NS_STYLE_FONT_WEIGHT_NORMAL
;
2314 else if (eCSSUnit_System_Font
== aFontData
.mWeight
.GetUnit()) {
2315 aFont
->mFont
.weight
= systemFont
.weight
;
2317 else if (eCSSUnit_Inherit
== aFontData
.mWeight
.GetUnit()) {
2318 aInherited
= PR_TRUE
;
2319 aFont
->mFont
.weight
= aParentFont
->mFont
.weight
;
2321 else if (eCSSUnit_Initial
== aFontData
.mWeight
.GetUnit()) {
2322 aFont
->mFont
.weight
= defaultVariableFont
->weight
;
2326 // Compute scriptlevel, scriptminsize and scriptsizemultiplier now so
2327 // they're available for font-size computation.
2329 // -moz-script-min-size: length
2330 if (aFontData
.mScriptMinSize
.IsLengthUnit()) {
2331 // scriptminsize in font units (em, ex) has to be interpreted relative
2332 // to the parent font, or the size definitions are circular and we
2334 aFont
->mScriptMinSize
=
2335 CalcLengthWith(aFontData
.mScriptMinSize
, aParentFont
->mSize
, aParentFont
, nsnull
,
2336 aPresContext
, aInherited
);
2339 // -moz-script-size-multiplier: factor, inherit
2340 if (eCSSUnit_Number
== aFontData
.mScriptSizeMultiplier
.GetUnit()) {
2341 aFont
->mScriptSizeMultiplier
= aFontData
.mScriptSizeMultiplier
.GetFloatValue();
2342 NS_ASSERTION(aFont
->mScriptSizeMultiplier
>= 0.0f
, "Cannot have negative script size multiplier");
2344 else if (eCSSUnit_Inherit
== aFontData
.mScriptSizeMultiplier
.GetUnit()) {
2345 aInherited
= PR_TRUE
;
2346 aFont
->mScriptSizeMultiplier
= aParentFont
->mScriptSizeMultiplier
;
2348 else if (eCSSUnit_Initial
== aFontData
.mScriptSizeMultiplier
.GetUnit()) {
2349 aFont
->mScriptSizeMultiplier
= NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER
;
2352 // -moz-script-level: integer, number, inherit
2353 if (eCSSUnit_Integer
== aFontData
.mScriptLevel
.GetUnit()) {
2355 aFont
->mScriptLevel
= ClampTo8Bit(aParentFont
->mScriptLevel
+ aFontData
.mScriptLevel
.GetIntValue());
2357 else if (eCSSUnit_Number
== aFontData
.mScriptLevel
.GetUnit()) {
2359 aFont
->mScriptLevel
= ClampTo8Bit(PRInt32(aFontData
.mScriptLevel
.GetFloatValue()));
2361 else if (eCSSUnit_Inherit
== aFontData
.mScriptSizeMultiplier
.GetUnit()) {
2362 aInherited
= PR_TRUE
;
2363 aFont
->mScriptLevel
= aParentFont
->mScriptLevel
;
2365 else if (eCSSUnit_Initial
== aFontData
.mScriptSizeMultiplier
.GetUnit()) {
2366 aFont
->mScriptLevel
= 0;
2370 // font-size: enum, length, percent, inherit
2371 nscoord scriptLevelAdjustedParentSize
= aParentFont
->mSize
;
2373 nscoord scriptLevelAdjustedUnconstrainedParentSize
;
2374 scriptLevelAdjustedParentSize
=
2375 ComputeScriptLevelSize(aFont
, aParentFont
, aPresContext
,
2376 &scriptLevelAdjustedUnconstrainedParentSize
);
2377 NS_ASSERTION(!aUsedStartStruct
|| aFont
->mScriptUnconstrainedSize
== aFont
->mSize
,
2378 "If we have a start struct, we should have reset everything coming in here");
2380 SetFontSize(aPresContext
, aFontData
, aFont
, aParentFont
, &aFont
->mSize
,
2381 systemFont
, aParentFont
->mSize
, scriptLevelAdjustedParentSize
,
2382 aUsedStartStruct
, aInherited
);
2384 if (aParentFont
->mSize
== aParentFont
->mScriptUnconstrainedSize
&&
2385 scriptLevelAdjustedParentSize
== scriptLevelAdjustedUnconstrainedParentSize
) {
2386 // Fast path: we have not been affected by scriptminsize so we don't
2387 // need to call SetFontSize again to compute the
2388 // scriptminsize-unconstrained size. This is OK even if we have a
2389 // start struct, because if we have a start struct then 'font-size'
2390 // was specified and so scriptminsize has no effect.
2391 aFont
->mScriptUnconstrainedSize
= aFont
->mSize
;
2393 SetFontSize(aPresContext
, aFontData
, aFont
, aParentFont
,
2394 &aFont
->mScriptUnconstrainedSize
, systemFont
,
2395 aParentFont
->mScriptUnconstrainedSize
,
2396 scriptLevelAdjustedUnconstrainedParentSize
,
2397 aUsedStartStruct
, aInherited
);
2399 NS_ASSERTION(aFont
->mScriptUnconstrainedSize
<= aFont
->mSize
,
2400 "scriptminsize should never be making things bigger");
2403 // enforce the user' specified minimum font-size on the value that we expose
2404 // (but don't change font-size:0)
2405 if (0 < aFont
->mSize
&& aFont
->mSize
< aMinFontSize
)
2406 aFont
->mFont
.size
= aMinFontSize
;
2408 aFont
->mFont
.size
= aFont
->mSize
;
2410 // font-size-adjust: number, none, inherit
2411 if (eCSSUnit_Number
== aFontData
.mSizeAdjust
.GetUnit()) {
2412 aFont
->mFont
.sizeAdjust
= aFontData
.mSizeAdjust
.GetFloatValue();
2414 else if (eCSSUnit_None
== aFontData
.mSizeAdjust
.GetUnit()) {
2415 aFont
->mFont
.sizeAdjust
= 0.0f
;
2417 else if (eCSSUnit_System_Font
== aFontData
.mSizeAdjust
.GetUnit()) {
2418 aFont
->mFont
.sizeAdjust
= systemFont
.sizeAdjust
;
2420 else if (eCSSUnit_Inherit
== aFontData
.mSizeAdjust
.GetUnit()) {
2421 aInherited
= PR_TRUE
;
2422 aFont
->mFont
.sizeAdjust
= aParentFont
->mFont
.sizeAdjust
;
2424 else if (eCSSUnit_Initial
== aFontData
.mSizeAdjust
.GetUnit()) {
2425 aFont
->mFont
.sizeAdjust
= 0.0f
;
2430 // - backtrack to an ancestor with the same generic font name (possibly
2431 // up to the root where default values come from the presentation context)
2432 // - re-apply cascading rules from there without caching intermediate values
2434 nsRuleNode::SetGenericFont(nsPresContext
* aPresContext
,
2435 nsStyleContext
* aContext
,
2436 PRUint8 aGenericFontID
, nscoord aMinFontSize
,
2439 // walk up the contexts until a context with the desired generic font
2440 nsAutoVoidArray contextPath
;
2441 contextPath
.AppendElement(aContext
);
2442 nsStyleContext
* higherContext
= aContext
->GetParent();
2443 while (higherContext
) {
2444 if (higherContext
->GetStyleFont()->mFlags
& aGenericFontID
) {
2445 // done walking up the higher contexts
2448 contextPath
.AppendElement(higherContext
);
2449 higherContext
= higherContext
->GetParent();
2452 // re-apply the cascading rules, starting from the higher context
2454 // If we stopped earlier because we reached the root of the style tree,
2455 // we will start with the default generic font from the presentation
2456 // context. Otherwise we start with the higher context.
2457 const nsFont
* defaultFont
= aPresContext
->GetDefaultFont(aGenericFontID
);
2458 nsStyleFont
parentFont(*defaultFont
, aPresContext
);
2459 if (higherContext
) {
2460 const nsStyleFont
* tmpFont
= higherContext
->GetStyleFont();
2461 parentFont
= *tmpFont
;
2463 *aFont
= parentFont
;
2466 PRUint32 fontBit
= nsCachedStyleData::GetBitForSID(eStyleStruct_Font
);
2468 for (PRInt32 i
= contextPath
.Count() - 1; i
>= 0; --i
) {
2469 nsStyleContext
* context
= (nsStyleContext
*)contextPath
[i
];
2470 nsRuleDataFont fontData
; // Declare a struct with null CSS values.
2471 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Font
), aPresContext
, context
);
2472 ruleData
.mFontData
= &fontData
;
2474 // Trimmed down version of ::WalkRuleTree() to re-apply the style rules
2475 // Note that we *do* need to do this for our own data, since what is
2476 // in |fontData| in ComputeFontData is only for the rules below
2478 for (nsRuleNode
* ruleNode
= context
->GetRuleNode(); ruleNode
;
2479 ruleNode
= ruleNode
->GetParent()) {
2480 if (ruleNode
->mNoneBits
& fontBit
)
2481 // no more font rules on this branch, get out
2484 nsIStyleRule
*rule
= ruleNode
->GetRule();
2486 ruleData
.mLevel
= ruleNode
->GetLevel();
2487 ruleData
.mIsImportantRule
= ruleNode
->IsImportantRule();
2488 rule
->MapRuleInfoInto(&ruleData
);
2492 // Compute the delta from the information that the rules specified
2494 // Avoid unnecessary operations in SetFont(). But we care if it's
2495 // the final value that we're computing.
2497 fontData
.mFamily
.Reset();
2499 nsRuleNode::SetFont(aPresContext
, context
, aMinFontSize
,
2500 aGenericFontID
, fontData
, &parentFont
, aFont
,
2503 // XXX Not sure if we need to do this here
2504 // If we have a post-resolve callback, handle that now.
2505 if (ruleData
.mPostResolveCallback
)
2506 (ruleData
.mPostResolveCallback
)(aFont
, &ruleData
);
2508 parentFont
= *aFont
;
2512 static PRBool
ExtractGeneric(const nsString
& aFamily
, PRBool aGeneric
,
2515 nsAutoString
*data
= static_cast<nsAutoString
*>(aData
);
2519 return PR_FALSE
; // stop enumeration
2525 nsRuleNode::ComputeFontData(void* aStartStruct
,
2526 const nsRuleDataStruct
& aData
,
2527 nsStyleContext
* aContext
,
2528 nsRuleNode
* aHighestNode
,
2529 const RuleDetail aRuleDetail
, PRBool aInherited
)
2531 COMPUTE_START_INHERITED(Font
, (mPresContext
), font
, parentFont
,
2534 // NOTE: The |aRuleDetail| passed in is a little bit conservative due
2535 // to the -moz-system-font property. We really don't need to consider
2536 // it here in determining whether to cache in the rule tree. However,
2537 // we do need to consider it in WalkRuleTree when deciding whether to
2538 // walk further up the tree. So this means that when the font struct
2539 // is fully specified using *longhand* properties (excluding
2540 // -moz-system-font), we won't cache in the rule tree even though we
2541 // could. However, it's pretty unlikely authors will do that
2542 // (although there is a pretty good chance they'll fully specify it
2543 // using the 'font' shorthand).
2545 // See if there is a minimum font-size constraint to honor
2546 nscoord minimumFontSize
=
2547 mPresContext
->GetCachedIntPref(kPresContext_MinimumFontSize
);
2549 if (minimumFontSize
< 0)
2550 minimumFontSize
= 0;
2552 PRBool useDocumentFonts
=
2553 mPresContext
->GetCachedBoolPref(kPresContext_UseDocumentFonts
);
2555 // See if we are in the chrome
2556 // We only need to know this to determine if we have to use the
2557 // document fonts (overriding the useDocumentFonts flag), or to
2558 // determine if we have to override the minimum font-size constraint.
2559 if ((!useDocumentFonts
|| minimumFontSize
> 0) && mPresContext
->IsChrome()) {
2560 // if we are not using document fonts, but this is a XUL document,
2561 // then we use the document fonts anyway
2562 useDocumentFonts
= PR_TRUE
;
2563 minimumFontSize
= 0;
2566 // Figure out if we are a generic font
2567 PRUint8 generic
= kGenericFont_NONE
;
2568 // XXXldb What if we would have had a string if we hadn't been doing
2569 // the optimization with a non-null aStartStruct?
2570 if (eCSSUnit_String
== fontData
.mFamily
.GetUnit()) {
2571 fontData
.mFamily
.GetStringValue(font
->mFont
.name
);
2572 // XXXldb Do we want to extract the generic for this if it's not only a
2574 nsFont::GetGenericID(font
->mFont
.name
, &generic
);
2576 // If we aren't allowed to use document fonts, then we are only entitled
2577 // to use the user's default variable-width font and fixed-width font
2578 if (!useDocumentFonts
) {
2579 // Extract the generic from the specified font family...
2580 nsAutoString genericName
;
2581 if (!font
->mFont
.EnumerateFamilies(ExtractGeneric
, &genericName
)) {
2582 // The specified font had a generic family.
2583 font
->mFont
.name
= genericName
;
2584 nsFont::GetGenericID(genericName
, &generic
);
2586 // ... and only use it if it's -moz-fixed or monospace
2587 if (generic
!= kGenericFont_moz_fixed
&&
2588 generic
!= kGenericFont_monospace
) {
2589 font
->mFont
.name
.Truncate();
2590 generic
= kGenericFont_NONE
;
2593 // The specified font did not have a generic family.
2594 font
->mFont
.name
.Truncate();
2595 generic
= kGenericFont_NONE
;
2600 // Now compute our font struct
2601 if (generic
== kGenericFont_NONE
) {
2602 // continue the normal processing
2603 nsRuleNode::SetFont(mPresContext
, aContext
, minimumFontSize
, generic
,
2604 fontData
, parentFont
, font
,
2605 aStartStruct
!= nsnull
, inherited
);
2608 // re-calculate the font as a generic font
2609 inherited
= PR_TRUE
;
2610 nsRuleNode::SetGenericFont(mPresContext
, aContext
, generic
,
2611 minimumFontSize
, font
);
2614 COMPUTE_END_INHERITED(Font
, font
)
2618 nsRuleNode::ComputeTextData(void* aStartStruct
,
2619 const nsRuleDataStruct
& aData
,
2620 nsStyleContext
* aContext
,
2621 nsRuleNode
* aHighestNode
,
2622 const RuleDetail aRuleDetail
, PRBool aInherited
)
2624 COMPUTE_START_INHERITED(Text
, (), text
, parentText
, Text
, textData
)
2626 // letter-spacing: normal, length, inherit
2627 SetCoord(textData
.mLetterSpacing
, text
->mLetterSpacing
, parentText
->mLetterSpacing
,
2628 SETCOORD_LH
| SETCOORD_NORMAL
| SETCOORD_INITIAL_NORMAL
,
2629 aContext
, mPresContext
, inherited
);
2631 // line-height: normal, number, length, percent, inherit
2632 if (eCSSUnit_Percent
== textData
.mLineHeight
.GetUnit()) {
2633 inherited
= PR_TRUE
;
2634 // Use |mFont.size| to pick up minimum font size.
2635 text
->mLineHeight
.SetCoordValue(
2636 nscoord(float(aContext
->GetStyleFont()->mFont
.size
) *
2637 textData
.mLineHeight
.GetPercentValue()));
2639 else if (eCSSUnit_Initial
== textData
.mLineHeight
.GetUnit() ||
2640 eCSSUnit_System_Font
== textData
.mLineHeight
.GetUnit()) {
2641 text
->mLineHeight
.SetNormalValue();
2644 SetCoord(textData
.mLineHeight
, text
->mLineHeight
, parentText
->mLineHeight
,
2645 SETCOORD_LH
| SETCOORD_FACTOR
| SETCOORD_NORMAL
,
2646 aContext
, mPresContext
, inherited
);
2647 if (textData
.mLineHeight
.IsFixedLengthUnit() ||
2648 textData
.mLineHeight
.GetUnit() == eCSSUnit_Pixel
) {
2649 nscoord lh
= nsStyleFont::ZoomText(mPresContext
,
2650 text
->mLineHeight
.GetCoordValue());
2651 nscoord minimumFontSize
=
2652 mPresContext
->GetCachedIntPref(kPresContext_MinimumFontSize
);
2654 if (minimumFontSize
> 0 && !mPresContext
->IsChrome()) {
2655 // If we applied a minimum font size, scale the line height by
2656 // the same ratio. (If we *might* have applied a minimum font
2657 // size, we can't cache in the rule tree.)
2658 inherited
= PR_TRUE
;
2659 const nsStyleFont
*font
= aContext
->GetStyleFont();
2660 if (font
->mSize
!= 0) {
2661 lh
= nscoord(float(lh
) * float(font
->mFont
.size
) / float(font
->mSize
));
2663 lh
= minimumFontSize
;
2666 text
->mLineHeight
.SetCoordValue(lh
);
2671 // text-align: enum, string, inherit
2672 if (eCSSUnit_Enumerated
== textData
.mTextAlign
.GetUnit()) {
2673 text
->mTextAlign
= textData
.mTextAlign
.GetIntValue();
2675 else if (eCSSUnit_String
== textData
.mTextAlign
.GetUnit()) {
2676 NS_NOTYETIMPLEMENTED("align string");
2678 else if (eCSSUnit_Inherit
== textData
.mTextAlign
.GetUnit()) {
2679 inherited
= PR_TRUE
;
2680 text
->mTextAlign
= parentText
->mTextAlign
;
2682 else if (eCSSUnit_Initial
== textData
.mTextAlign
.GetUnit())
2683 text
->mTextAlign
= NS_STYLE_TEXT_ALIGN_DEFAULT
;
2685 // text-indent: length, percent, inherit
2686 SetCoord(textData
.mTextIndent
, text
->mTextIndent
, parentText
->mTextIndent
,
2687 SETCOORD_LPH
| SETCOORD_INITIAL_ZERO
, aContext
,
2688 mPresContext
, inherited
);
2690 // text-transform: enum, none, inherit
2691 if (eCSSUnit_Enumerated
== textData
.mTextTransform
.GetUnit()) {
2692 text
->mTextTransform
= textData
.mTextTransform
.GetIntValue();
2694 else if (eCSSUnit_None
== textData
.mTextTransform
.GetUnit() ||
2695 eCSSUnit_Initial
== textData
.mTextTransform
.GetUnit()) {
2696 text
->mTextTransform
= NS_STYLE_TEXT_TRANSFORM_NONE
;
2698 else if (eCSSUnit_Inherit
== textData
.mTextTransform
.GetUnit()) {
2699 inherited
= PR_TRUE
;
2700 text
->mTextTransform
= parentText
->mTextTransform
;
2703 // white-space: enum, normal, inherit
2704 if (eCSSUnit_Enumerated
== textData
.mWhiteSpace
.GetUnit()) {
2705 text
->mWhiteSpace
= textData
.mWhiteSpace
.GetIntValue();
2707 else if (eCSSUnit_Normal
== textData
.mWhiteSpace
.GetUnit() ||
2708 eCSSUnit_Initial
== textData
.mWhiteSpace
.GetUnit()) {
2709 text
->mWhiteSpace
= NS_STYLE_WHITESPACE_NORMAL
;
2711 else if (eCSSUnit_Inherit
== textData
.mWhiteSpace
.GetUnit()) {
2712 inherited
= PR_TRUE
;
2713 text
->mWhiteSpace
= parentText
->mWhiteSpace
;
2716 // word-spacing: normal, length, inherit
2717 SetCoord(textData
.mWordSpacing
, text
->mWordSpacing
, parentText
->mWordSpacing
,
2718 SETCOORD_LH
| SETCOORD_NORMAL
| SETCOORD_INITIAL_NORMAL
,
2719 aContext
, mPresContext
, inherited
);
2721 COMPUTE_END_INHERITED(Text
, text
)
2725 nsRuleNode::ComputeTextResetData(void* aStartStruct
,
2726 const nsRuleDataStruct
& aData
,
2727 nsStyleContext
* aContext
,
2728 nsRuleNode
* aHighestNode
,
2729 const RuleDetail aRuleDetail
, PRBool aInherited
)
2731 COMPUTE_START_RESET(TextReset
, (), text
, parentText
, Text
, textData
)
2733 // vertical-align: enum, length, percent, inherit
2734 if (!SetCoord(textData
.mVerticalAlign
, text
->mVerticalAlign
,
2735 parentText
->mVerticalAlign
, SETCOORD_LPH
| SETCOORD_ENUMERATED
,
2736 aContext
, mPresContext
, inherited
)) {
2737 if (eCSSUnit_Initial
== textData
.mVerticalAlign
.GetUnit()) {
2738 text
->mVerticalAlign
.SetIntValue(NS_STYLE_VERTICAL_ALIGN_BASELINE
,
2739 eStyleUnit_Enumerated
);
2743 // text-decoration: none, enum (bit field), inherit
2744 if (eCSSUnit_Enumerated
== textData
.mDecoration
.GetUnit()) {
2745 PRInt32 td
= textData
.mDecoration
.GetIntValue();
2746 text
->mTextDecoration
= td
;
2747 if (td
& NS_STYLE_TEXT_DECORATION_PREF_ANCHORS
) {
2748 PRBool underlineLinks
=
2749 mPresContext
->GetCachedBoolPref(kPresContext_UnderlineLinks
);
2750 if (underlineLinks
) {
2751 text
->mTextDecoration
|= NS_STYLE_TEXT_DECORATION_UNDERLINE
;
2754 text
->mTextDecoration
&= ~NS_STYLE_TEXT_DECORATION_UNDERLINE
;
2758 else if (eCSSUnit_None
== textData
.mDecoration
.GetUnit() ||
2759 eCSSUnit_Initial
== textData
.mDecoration
.GetUnit()) {
2760 text
->mTextDecoration
= NS_STYLE_TEXT_DECORATION_NONE
;
2762 else if (eCSSUnit_Inherit
== textData
.mDecoration
.GetUnit()) {
2763 inherited
= PR_TRUE
;
2764 text
->mTextDecoration
= parentText
->mTextDecoration
;
2767 // unicode-bidi: enum, normal, inherit
2768 if (eCSSUnit_Normal
== textData
.mUnicodeBidi
.GetUnit() ||
2769 eCSSUnit_Initial
== textData
.mUnicodeBidi
.GetUnit()) {
2770 text
->mUnicodeBidi
= NS_STYLE_UNICODE_BIDI_NORMAL
;
2772 else if (eCSSUnit_Enumerated
== textData
.mUnicodeBidi
.GetUnit() ) {
2773 text
->mUnicodeBidi
= textData
.mUnicodeBidi
.GetIntValue();
2775 else if (eCSSUnit_Inherit
== textData
.mUnicodeBidi
.GetUnit() ) {
2776 inherited
= PR_TRUE
;
2777 text
->mUnicodeBidi
= parentText
->mUnicodeBidi
;
2780 COMPUTE_END_RESET(TextReset
, text
)
2784 nsRuleNode::ComputeUserInterfaceData(void* aStartStruct
,
2785 const nsRuleDataStruct
& aData
,
2786 nsStyleContext
* aContext
,
2787 nsRuleNode
* aHighestNode
,
2788 const RuleDetail aRuleDetail
,
2791 COMPUTE_START_INHERITED(UserInterface
, (), ui
, parentUI
,
2792 UserInterface
, uiData
)
2794 // cursor: enum, auto, url, inherit
2795 nsCSSValueList
* list
= uiData
.mCursor
;
2796 if (nsnull
!= list
) {
2797 delete [] ui
->mCursorArray
;
2798 ui
->mCursorArray
= nsnull
;
2799 ui
->mCursorArrayLength
= 0;
2801 if (eCSSUnit_Inherit
== list
->mValue
.GetUnit()) {
2802 inherited
= PR_TRUE
;
2803 ui
->mCursor
= parentUI
->mCursor
;
2804 ui
->CopyCursorArrayFrom(*parentUI
);
2806 else if (eCSSUnit_Initial
== list
->mValue
.GetUnit()) {
2807 ui
->mCursor
= NS_STYLE_CURSOR_AUTO
;
2810 // The parser will never create a list that is *all* URL values --
2812 PRUint32 arrayLength
= 0;
2813 nsCSSValueList
* list2
= list
;
2814 for ( ; list
->mValue
.GetUnit() == eCSSUnit_Array
; list
= list
->mNext
)
2815 if (list
->mValue
.GetArrayValue()->Item(0).GetImageValue())
2818 if (arrayLength
!= 0) {
2819 ui
->mCursorArray
= new nsCursorImage
[arrayLength
];
2820 if (ui
->mCursorArray
) {
2821 ui
->mCursorArrayLength
= arrayLength
;
2823 for (nsCursorImage
*item
= ui
->mCursorArray
;
2824 list2
->mValue
.GetUnit() == eCSSUnit_Array
;
2825 list2
= list2
->mNext
) {
2826 nsCSSValue::Array
*arr
= list2
->mValue
.GetArrayValue();
2827 imgIRequest
*req
= arr
->Item(0).GetImageValue();
2830 if (arr
->Item(1).GetUnit() != eCSSUnit_Null
) {
2831 item
->mHaveHotspot
= PR_TRUE
;
2832 item
->mHotspotX
= arr
->Item(1).GetFloatValue(),
2833 item
->mHotspotY
= arr
->Item(2).GetFloatValue();
2841 NS_ASSERTION(list
, "Must have non-array value at the end");
2842 NS_ASSERTION(list
->mValue
.GetUnit() == eCSSUnit_Enumerated
||
2843 list
->mValue
.GetUnit() == eCSSUnit_Auto
,
2844 "Unexpected fallback value at end of cursor list");
2846 if (eCSSUnit_Enumerated
== list
->mValue
.GetUnit()) {
2847 ui
->mCursor
= list
->mValue
.GetIntValue();
2849 else if (eCSSUnit_Auto
== list
->mValue
.GetUnit()) {
2850 ui
->mCursor
= NS_STYLE_CURSOR_AUTO
;
2855 // user-input: auto, none, enum, inherit
2856 if (eCSSUnit_Enumerated
== uiData
.mUserInput
.GetUnit()) {
2857 ui
->mUserInput
= uiData
.mUserInput
.GetIntValue();
2859 else if (eCSSUnit_Auto
== uiData
.mUserInput
.GetUnit() ||
2860 eCSSUnit_Initial
== uiData
.mUserInput
.GetUnit()) {
2861 ui
->mUserInput
= NS_STYLE_USER_INPUT_AUTO
;
2863 else if (eCSSUnit_None
== uiData
.mUserInput
.GetUnit()) {
2864 ui
->mUserInput
= NS_STYLE_USER_INPUT_NONE
;
2866 else if (eCSSUnit_Inherit
== uiData
.mUserInput
.GetUnit()) {
2867 inherited
= PR_TRUE
;
2868 ui
->mUserInput
= parentUI
->mUserInput
;
2871 // user-modify: enum, inherit
2872 if (eCSSUnit_Enumerated
== uiData
.mUserModify
.GetUnit()) {
2873 ui
->mUserModify
= uiData
.mUserModify
.GetIntValue();
2875 else if (eCSSUnit_Inherit
== uiData
.mUserModify
.GetUnit()) {
2876 inherited
= PR_TRUE
;
2877 ui
->mUserModify
= parentUI
->mUserModify
;
2879 else if (eCSSUnit_Initial
== uiData
.mUserModify
.GetUnit()) {
2880 ui
->mUserModify
= NS_STYLE_USER_MODIFY_READ_ONLY
;
2883 // user-focus: none, normal, enum, inherit
2884 if (eCSSUnit_Enumerated
== uiData
.mUserFocus
.GetUnit()) {
2885 ui
->mUserFocus
= uiData
.mUserFocus
.GetIntValue();
2887 else if (eCSSUnit_None
== uiData
.mUserFocus
.GetUnit() ||
2888 eCSSUnit_Initial
== uiData
.mUserFocus
.GetUnit()) {
2889 ui
->mUserFocus
= NS_STYLE_USER_FOCUS_NONE
;
2891 else if (eCSSUnit_Normal
== uiData
.mUserFocus
.GetUnit()) {
2892 ui
->mUserFocus
= NS_STYLE_USER_FOCUS_NORMAL
;
2894 else if (eCSSUnit_Inherit
== uiData
.mUserFocus
.GetUnit()) {
2895 inherited
= PR_TRUE
;
2896 ui
->mUserFocus
= parentUI
->mUserFocus
;
2899 COMPUTE_END_INHERITED(UserInterface
, ui
)
2903 nsRuleNode::ComputeUIResetData(void* aStartStruct
,
2904 const nsRuleDataStruct
& aData
,
2905 nsStyleContext
* aContext
,
2906 nsRuleNode
* aHighestNode
,
2907 const RuleDetail aRuleDetail
, PRBool aInherited
)
2909 COMPUTE_START_RESET(UIReset
, (), ui
, parentUI
, UserInterface
, uiData
)
2911 // user-select: none, enum, inherit
2912 if (eCSSUnit_Enumerated
== uiData
.mUserSelect
.GetUnit()) {
2913 ui
->mUserSelect
= uiData
.mUserSelect
.GetIntValue();
2915 else if (eCSSUnit_None
== uiData
.mUserSelect
.GetUnit()) {
2916 ui
->mUserSelect
= NS_STYLE_USER_SELECT_NONE
;
2918 else if (eCSSUnit_Inherit
== uiData
.mUserSelect
.GetUnit()) {
2919 inherited
= PR_TRUE
;
2920 ui
->mUserSelect
= parentUI
->mUserSelect
;
2922 else if (eCSSUnit_Initial
== uiData
.mUserSelect
.GetUnit()) {
2923 // FIXME There's no other way to specify this value!
2924 ui
->mUserSelect
= NS_STYLE_USER_SELECT_AUTO
;
2927 // ime-mode: auto, normal, enum, inherit
2928 if (eCSSUnit_Auto
== uiData
.mIMEMode
.GetUnit() ||
2929 eCSSUnit_Initial
== uiData
.mIMEMode
.GetUnit()) {
2930 ui
->mIMEMode
= NS_STYLE_IME_MODE_AUTO
;
2932 else if (eCSSUnit_Normal
== uiData
.mIMEMode
.GetUnit()) {
2933 ui
->mIMEMode
= NS_STYLE_IME_MODE_NORMAL
;
2935 else if (eCSSUnit_Enumerated
== uiData
.mIMEMode
.GetUnit()) {
2936 ui
->mIMEMode
= uiData
.mIMEMode
.GetIntValue();
2938 else if (eCSSUnit_Inherit
== uiData
.mIMEMode
.GetUnit()) {
2939 inherited
= PR_TRUE
;
2940 ui
->mIMEMode
= parentUI
->mIMEMode
;
2943 // force-broken-image-icons: integer
2944 if (eCSSUnit_Integer
== uiData
.mForceBrokenImageIcon
.GetUnit()) {
2945 ui
->mForceBrokenImageIcon
= uiData
.mForceBrokenImageIcon
.GetIntValue();
2946 } else if (eCSSUnit_Inherit
== uiData
.mForceBrokenImageIcon
.GetUnit()) {
2947 inherited
= PR_TRUE
;
2948 ui
->mForceBrokenImageIcon
= parentUI
->mForceBrokenImageIcon
;
2949 } else if (eCSSUnit_Initial
== uiData
.mForceBrokenImageIcon
.GetUnit()) {
2950 ui
->mForceBrokenImageIcon
= 0;
2952 COMPUTE_END_RESET(UIReset
, ui
)
2956 nsRuleNode::ComputeDisplayData(void* aStartStruct
,
2957 const nsRuleDataStruct
& aData
,
2958 nsStyleContext
* aContext
,
2959 nsRuleNode
* aHighestNode
,
2960 const RuleDetail aRuleDetail
, PRBool aInherited
)
2962 COMPUTE_START_RESET(Display
, (), display
, parentDisplay
,
2963 Display
, displayData
)
2964 nsIAtom
* pseudoTag
= aContext
->GetPseudoType();
2965 PRBool generatedContent
= (pseudoTag
== nsCSSPseudoElements::before
||
2966 pseudoTag
== nsCSSPseudoElements::after
);
2967 NS_ASSERTION(!generatedContent
|| parentContext
,
2968 "Must have parent context for generated content");
2969 if (parentDisplay
== display
&& generatedContent
)
2970 parentDisplay
= parentContext
->GetStyleDisplay();
2972 // opacity: factor, inherit
2973 if (eCSSUnit_Number
== displayData
.mOpacity
.GetUnit()) {
2974 display
->mOpacity
= displayData
.mOpacity
.GetFloatValue();
2975 if (display
->mOpacity
> 1.0f
)
2976 display
->mOpacity
= 1.0f
;
2977 if (display
->mOpacity
< 0.0f
)
2978 display
->mOpacity
= 0.0f
;
2980 else if (eCSSUnit_Inherit
== displayData
.mOpacity
.GetUnit()) {
2981 inherited
= PR_TRUE
;
2982 display
->mOpacity
= parentDisplay
->mOpacity
;
2984 else if (eCSSUnit_Initial
== displayData
.mOpacity
.GetUnit()) {
2985 display
->mOpacity
= 1.0f
;
2988 // display: enum, none, inherit
2989 if (eCSSUnit_Enumerated
== displayData
.mDisplay
.GetUnit()) {
2990 display
->mDisplay
= displayData
.mDisplay
.GetIntValue();
2992 else if (eCSSUnit_None
== displayData
.mDisplay
.GetUnit()) {
2993 display
->mDisplay
= NS_STYLE_DISPLAY_NONE
;
2995 else if (eCSSUnit_Inherit
== displayData
.mDisplay
.GetUnit()) {
2996 inherited
= PR_TRUE
;
2997 display
->mDisplay
= parentDisplay
->mDisplay
;
2999 else if (eCSSUnit_Initial
== displayData
.mDisplay
.GetUnit()) {
3000 display
->mDisplay
= NS_STYLE_DISPLAY_INLINE
;
3003 // appearance: enum, none, inherit
3004 if (eCSSUnit_Enumerated
== displayData
.mAppearance
.GetUnit()) {
3005 display
->mAppearance
= displayData
.mAppearance
.GetIntValue();
3007 else if (eCSSUnit_None
== displayData
.mAppearance
.GetUnit() ||
3008 eCSSUnit_Initial
== displayData
.mAppearance
.GetUnit()) {
3009 display
->mAppearance
= NS_THEME_NONE
;
3011 else if (eCSSUnit_Inherit
== displayData
.mAppearance
.GetUnit()) {
3012 inherited
= PR_TRUE
;
3013 display
->mAppearance
= parentDisplay
->mAppearance
;
3016 // binding: url, none, inherit
3017 if (eCSSUnit_URL
== displayData
.mBinding
.GetUnit()) {
3018 nsCSSValue::URL
* url
= displayData
.mBinding
.GetURLStructValue();
3019 NS_ASSERTION(url
, "What's going on here?");
3021 if (NS_LIKELY(url
->mURI
)) {
3022 display
->mBinding
= url
;
3024 display
->mBinding
= nsnull
;
3027 else if (eCSSUnit_None
== displayData
.mBinding
.GetUnit() ||
3028 eCSSUnit_Initial
== displayData
.mBinding
.GetUnit()) {
3029 display
->mBinding
= nsnull
;
3031 else if (eCSSUnit_Inherit
== displayData
.mBinding
.GetUnit()) {
3032 inherited
= PR_TRUE
;
3033 display
->mBinding
= parentDisplay
->mBinding
;
3036 // position: enum, inherit
3037 if (eCSSUnit_Enumerated
== displayData
.mPosition
.GetUnit()) {
3038 display
->mPosition
= displayData
.mPosition
.GetIntValue();
3040 else if (eCSSUnit_Inherit
== displayData
.mPosition
.GetUnit()) {
3041 inherited
= PR_TRUE
;
3042 display
->mPosition
= parentDisplay
->mPosition
;
3044 else if (eCSSUnit_Initial
== displayData
.mPosition
.GetUnit()) {
3045 display
->mPosition
= NS_STYLE_POSITION_STATIC
;
3048 // clear: enum, none, inherit
3049 if (eCSSUnit_Enumerated
== displayData
.mClear
.GetUnit()) {
3050 display
->mBreakType
= displayData
.mClear
.GetIntValue();
3052 else if (eCSSUnit_None
== displayData
.mClear
.GetUnit() ||
3053 eCSSUnit_Initial
== displayData
.mClear
.GetUnit()) {
3054 display
->mBreakType
= NS_STYLE_CLEAR_NONE
;
3056 else if (eCSSUnit_Inherit
== displayData
.mClear
.GetUnit()) {
3057 inherited
= PR_TRUE
;
3058 display
->mBreakType
= parentDisplay
->mBreakType
;
3061 // temp fix for bug 24000
3062 // Map 'auto' and 'avoid' to PR_FALSE, and 'always', 'left', and
3063 // 'right' to PR_TRUE.
3064 // "A conforming user agent may interpret the values 'left' and
3065 // 'right' as 'always'." - CSS2.1, section 13.3.1
3066 if (eCSSUnit_Enumerated
== displayData
.mBreakBefore
.GetUnit()) {
3067 display
->mBreakBefore
= (NS_STYLE_PAGE_BREAK_AVOID
!= displayData
.mBreakBefore
.GetIntValue());
3069 else if (eCSSUnit_Auto
== displayData
.mBreakBefore
.GetUnit() ||
3070 eCSSUnit_Initial
== displayData
.mBreakBefore
.GetUnit()) {
3071 display
->mBreakBefore
= PR_FALSE
;
3073 else if (eCSSUnit_Inherit
== displayData
.mBreakBefore
.GetUnit()) {
3074 inherited
= PR_TRUE
;
3075 display
->mBreakBefore
= parentDisplay
->mBreakBefore
;
3078 if (eCSSUnit_Enumerated
== displayData
.mBreakAfter
.GetUnit()) {
3079 display
->mBreakAfter
= (NS_STYLE_PAGE_BREAK_AVOID
!= displayData
.mBreakAfter
.GetIntValue());
3081 else if (eCSSUnit_Auto
== displayData
.mBreakAfter
.GetUnit() ||
3082 eCSSUnit_Initial
== displayData
.mBreakAfter
.GetUnit()) {
3083 display
->mBreakAfter
= PR_FALSE
;
3085 else if (eCSSUnit_Inherit
== displayData
.mBreakAfter
.GetUnit()) {
3086 inherited
= PR_TRUE
;
3087 display
->mBreakAfter
= parentDisplay
->mBreakAfter
;
3091 // float: enum, none, inherit
3092 if (eCSSUnit_Enumerated
== displayData
.mFloat
.GetUnit()) {
3093 display
->mFloats
= displayData
.mFloat
.GetIntValue();
3095 else if (eCSSUnit_None
== displayData
.mFloat
.GetUnit() ||
3096 eCSSUnit_Initial
== displayData
.mFloat
.GetUnit()) {
3097 display
->mFloats
= NS_STYLE_FLOAT_NONE
;
3099 else if (eCSSUnit_Inherit
== displayData
.mFloat
.GetUnit()) {
3100 inherited
= PR_TRUE
;
3101 display
->mFloats
= parentDisplay
->mFloats
;
3104 // overflow-x: enum, auto, inherit
3105 if (eCSSUnit_Enumerated
== displayData
.mOverflowX
.GetUnit()) {
3106 display
->mOverflowX
= displayData
.mOverflowX
.GetIntValue();
3108 else if (eCSSUnit_Auto
== displayData
.mOverflowX
.GetUnit()) {
3109 display
->mOverflowX
= NS_STYLE_OVERFLOW_AUTO
;
3111 else if (eCSSUnit_Inherit
== displayData
.mOverflowX
.GetUnit()) {
3112 inherited
= PR_TRUE
;
3113 display
->mOverflowX
= parentDisplay
->mOverflowX
;
3115 else if (eCSSUnit_Initial
== displayData
.mOverflowX
.GetUnit()) {
3116 display
->mOverflowX
= NS_STYLE_OVERFLOW_VISIBLE
;
3119 // overflow-y: enum, auto, inherit
3120 if (eCSSUnit_Enumerated
== displayData
.mOverflowY
.GetUnit()) {
3121 display
->mOverflowY
= displayData
.mOverflowY
.GetIntValue();
3123 else if (eCSSUnit_Auto
== displayData
.mOverflowY
.GetUnit()) {
3124 display
->mOverflowY
= NS_STYLE_OVERFLOW_AUTO
;
3126 else if (eCSSUnit_Inherit
== displayData
.mOverflowY
.GetUnit()) {
3127 inherited
= PR_TRUE
;
3128 display
->mOverflowY
= parentDisplay
->mOverflowY
;
3130 else if (eCSSUnit_Initial
== displayData
.mOverflowY
.GetUnit()) {
3131 display
->mOverflowY
= NS_STYLE_OVERFLOW_VISIBLE
;
3134 // CSS3 overflow-x and overflow-y require some fixup as well in some
3135 // cases. NS_STYLE_OVERFLOW_VISIBLE and NS_STYLE_OVERFLOW_CLIP are
3136 // meaningful only when used in both dimensions.
3137 if (display
->mOverflowX
!= display
->mOverflowY
&&
3138 (display
->mOverflowX
== NS_STYLE_OVERFLOW_VISIBLE
||
3139 display
->mOverflowX
== NS_STYLE_OVERFLOW_CLIP
||
3140 display
->mOverflowY
== NS_STYLE_OVERFLOW_VISIBLE
||
3141 display
->mOverflowY
== NS_STYLE_OVERFLOW_CLIP
)) {
3142 // We can't store in the rule tree since a more specific rule might
3143 // change these conditions.
3144 inherited
= PR_TRUE
;
3146 // NS_STYLE_OVERFLOW_CLIP is a deprecated value, so if it's specified
3147 // in only one dimension, convert it to NS_STYLE_OVERFLOW_HIDDEN.
3148 if (display
->mOverflowX
== NS_STYLE_OVERFLOW_CLIP
)
3149 display
->mOverflowX
= NS_STYLE_OVERFLOW_HIDDEN
;
3150 if (display
->mOverflowY
== NS_STYLE_OVERFLOW_CLIP
)
3151 display
->mOverflowY
= NS_STYLE_OVERFLOW_HIDDEN
;
3153 // If 'visible' is specified but doesn't match the other dimension, it
3154 // turns into 'auto'.
3155 if (display
->mOverflowX
== NS_STYLE_OVERFLOW_VISIBLE
)
3156 display
->mOverflowX
= NS_STYLE_OVERFLOW_AUTO
;
3157 if (display
->mOverflowY
== NS_STYLE_OVERFLOW_VISIBLE
)
3158 display
->mOverflowY
= NS_STYLE_OVERFLOW_AUTO
;
3161 // clip property: length, auto, inherit
3162 if (eCSSUnit_Inherit
== displayData
.mClip
.mTop
.GetUnit()) { // if one is inherit, they all are
3163 inherited
= PR_TRUE
;
3164 display
->mClipFlags
= parentDisplay
->mClipFlags
;
3165 display
->mClip
= parentDisplay
->mClip
;
3167 // if one is initial, they all are
3168 else if (eCSSUnit_Initial
== displayData
.mClip
.mTop
.GetUnit()) {
3169 display
->mClipFlags
= NS_STYLE_CLIP_AUTO
;
3170 display
->mClip
.SetRect(0,0,0,0);
3173 PRBool fullAuto
= PR_TRUE
;
3175 display
->mClipFlags
= 0; // clear it
3177 if (eCSSUnit_Auto
== displayData
.mClip
.mTop
.GetUnit()) {
3178 display
->mClip
.y
= 0;
3179 display
->mClipFlags
|= NS_STYLE_CLIP_TOP_AUTO
;
3181 else if (displayData
.mClip
.mTop
.IsLengthUnit()) {
3182 display
->mClip
.y
= CalcLength(displayData
.mClip
.mTop
, aContext
, mPresContext
, inherited
);
3183 fullAuto
= PR_FALSE
;
3185 if (eCSSUnit_Auto
== displayData
.mClip
.mBottom
.GetUnit()) {
3186 // Setting to NS_MAXSIZE for the 'auto' case ensures that
3187 // the clip rect is nonempty. It is important that mClip be
3188 // nonempty if the actual clip rect could be nonempty.
3189 display
->mClip
.height
= NS_MAXSIZE
;
3190 display
->mClipFlags
|= NS_STYLE_CLIP_BOTTOM_AUTO
;
3192 else if (displayData
.mClip
.mBottom
.IsLengthUnit()) {
3193 display
->mClip
.height
= CalcLength(displayData
.mClip
.mBottom
, aContext
, mPresContext
, inherited
) -
3195 fullAuto
= PR_FALSE
;
3197 if (eCSSUnit_Auto
== displayData
.mClip
.mLeft
.GetUnit()) {
3198 display
->mClip
.x
= 0;
3199 display
->mClipFlags
|= NS_STYLE_CLIP_LEFT_AUTO
;
3201 else if (displayData
.mClip
.mLeft
.IsLengthUnit()) {
3202 display
->mClip
.x
= CalcLength(displayData
.mClip
.mLeft
, aContext
, mPresContext
, inherited
);
3203 fullAuto
= PR_FALSE
;
3205 if (eCSSUnit_Auto
== displayData
.mClip
.mRight
.GetUnit()) {
3206 // Setting to NS_MAXSIZE for the 'auto' case ensures that
3207 // the clip rect is nonempty. It is important that mClip be
3208 // nonempty if the actual clip rect could be nonempty.
3209 display
->mClip
.width
= NS_MAXSIZE
;
3210 display
->mClipFlags
|= NS_STYLE_CLIP_RIGHT_AUTO
;
3212 else if (displayData
.mClip
.mRight
.IsLengthUnit()) {
3213 display
->mClip
.width
= CalcLength(displayData
.mClip
.mRight
, aContext
, mPresContext
, inherited
) -
3215 fullAuto
= PR_FALSE
;
3217 display
->mClipFlags
&= ~NS_STYLE_CLIP_TYPE_MASK
;
3219 display
->mClipFlags
|= NS_STYLE_CLIP_AUTO
;
3222 display
->mClipFlags
|= NS_STYLE_CLIP_RECT
;
3226 // CSS2 specified fixups:
3227 if (generatedContent
) {
3228 // According to CSS2 section 12.1, :before and :after
3229 // pseudo-elements must not be positioned or floated (CSS2 12.1) and
3230 // must be limited to certain display types (depending on the
3231 // display type of the element to which they are attached).
3232 // XXX These restrictions are no longer present in CSS2.1. We
3233 // should ensure that we support removing them before doing so,
3235 // XXXbz For example, the calls to WipeContainingBlock in the
3236 // frame constructor will need to be changedif we allow
3237 // block-level generated content inside inlines.
3239 if (display
->mPosition
!= NS_STYLE_POSITION_STATIC
)
3240 display
->mPosition
= NS_STYLE_POSITION_STATIC
;
3241 if (display
->mFloats
!= NS_STYLE_FLOAT_NONE
)
3242 display
->mFloats
= NS_STYLE_FLOAT_NONE
;
3244 PRUint8 displayValue
= display
->mDisplay
;
3245 if (displayValue
!= NS_STYLE_DISPLAY_NONE
&&
3246 displayValue
!= NS_STYLE_DISPLAY_INLINE
&&
3247 displayValue
!= NS_STYLE_DISPLAY_INLINE_BLOCK
) {
3248 inherited
= PR_TRUE
;
3249 if (parentDisplay
->IsBlockOutside() ||
3250 parentDisplay
->mDisplay
== NS_STYLE_DISPLAY_INLINE_BLOCK
||
3251 parentDisplay
->mDisplay
== NS_STYLE_DISPLAY_TABLE_CELL
||
3252 parentDisplay
->mDisplay
== NS_STYLE_DISPLAY_TABLE_CAPTION
) {
3253 // If the subject of the selector is a block-level element,
3254 // allowed values are 'none', 'inline', 'block', and 'marker'.
3255 // If the value of the 'display' has any other value, the
3256 // pseudo-element will behave as if the value were 'block'.
3257 if (displayValue
!= NS_STYLE_DISPLAY_BLOCK
&&
3258 displayValue
!= NS_STYLE_DISPLAY_MARKER
)
3259 display
->mDisplay
= NS_STYLE_DISPLAY_BLOCK
;
3261 // If the subject of the selector is an inline-level element,
3262 // allowed values are 'none' and 'inline'. If the value of the
3263 // 'display' has any other value, the pseudo-element will behave
3264 // as if the value were 'inline'.
3265 display
->mDisplay
= NS_STYLE_DISPLAY_INLINE
;
3269 else if (display
->mDisplay
!= NS_STYLE_DISPLAY_NONE
) {
3270 // CSS2 9.7 specifies display type corrections dealing with 'float'
3271 // and 'position'. Since generated content can't be floated or
3272 // positioned, we can deal with it here.
3274 if (nsCSSPseudoElements::firstLetter
== pseudoTag
) {
3275 // a non-floating first-letter must be inline
3276 // XXX this fix can go away once bug 103189 is fixed correctly
3277 display
->mDisplay
= NS_STYLE_DISPLAY_INLINE
;
3279 // We can't cache the data in the rule tree since if a more specific
3280 // rule has 'float: left' we'll end up with the wrong 'display'
3282 inherited
= PR_TRUE
;
3285 if (display
->IsAbsolutelyPositioned()) {
3286 // 1) if position is 'absolute' or 'fixed' then display must be
3287 // block-level and float must be 'none'
3289 // Backup original display value for calculation of a hypothetical
3290 // box (CSS2 10.6.4/10.6.5).
3291 // See nsHTMLReflowState::CalculateHypotheticalBox
3292 display
->mOriginalDisplay
= display
->mDisplay
;
3293 EnsureBlockDisplay(display
->mDisplay
);
3294 display
->mFloats
= NS_STYLE_FLOAT_NONE
;
3296 // We can't cache the data in the rule tree since if a more specific
3297 // rule has 'position: static' we'll end up with problems with the
3298 // 'display' and 'float' properties.
3299 inherited
= PR_TRUE
;
3300 } else if (display
->mFloats
!= NS_STYLE_FLOAT_NONE
) {
3301 // 2) if float is not none, and display is not none, then we must
3302 // set a block-level 'display' type per CSS2.1 section 9.7.
3304 EnsureBlockDisplay(display
->mDisplay
);
3306 // We can't cache the data in the rule tree since if a more specific
3307 // rule has 'float: none' we'll end up with the wrong 'display'
3309 inherited
= PR_TRUE
;
3314 COMPUTE_END_RESET(Display
, display
)
3318 nsRuleNode::ComputeVisibilityData(void* aStartStruct
,
3319 const nsRuleDataStruct
& aData
,
3320 nsStyleContext
* aContext
,
3321 nsRuleNode
* aHighestNode
,
3322 const RuleDetail aRuleDetail
, PRBool aInherited
)
3324 COMPUTE_START_INHERITED(Visibility
, (mPresContext
),
3325 visibility
, parentVisibility
,
3326 Display
, displayData
)
3328 // direction: enum, inherit
3329 if (eCSSUnit_Enumerated
== displayData
.mDirection
.GetUnit()) {
3330 visibility
->mDirection
= displayData
.mDirection
.GetIntValue();
3331 if (NS_STYLE_DIRECTION_RTL
== visibility
->mDirection
)
3332 mPresContext
->SetBidiEnabled();
3334 else if (eCSSUnit_Inherit
== displayData
.mDirection
.GetUnit()) {
3335 inherited
= PR_TRUE
;
3336 visibility
->mDirection
= parentVisibility
->mDirection
;
3338 else if (eCSSUnit_Initial
== displayData
.mDirection
.GetUnit()) {
3339 PRUint32 bidiOptions
= mPresContext
->GetBidi();
3340 if (GET_BIDI_OPTION_DIRECTION(bidiOptions
) == IBMBIDI_TEXTDIRECTION_RTL
)
3341 visibility
->mDirection
= NS_STYLE_DIRECTION_RTL
;
3343 visibility
->mDirection
= NS_STYLE_DIRECTION_LTR
;
3346 // visibility: enum, inherit
3347 if (eCSSUnit_Enumerated
== displayData
.mVisibility
.GetUnit()) {
3348 visibility
->mVisible
= displayData
.mVisibility
.GetIntValue();
3350 else if (eCSSUnit_Inherit
== displayData
.mVisibility
.GetUnit()) {
3351 inherited
= PR_TRUE
;
3352 visibility
->mVisible
= parentVisibility
->mVisible
;
3354 else if (eCSSUnit_Initial
== displayData
.mVisibility
.GetUnit()) {
3355 visibility
->mVisible
= NS_STYLE_VISIBILITY_VISIBLE
;
3358 // lang: string, inherit
3359 // this is not a real CSS property, it is a html attribute mapped to CSS struture
3360 if (eCSSUnit_String
== displayData
.mLang
.GetUnit()) {
3361 if (!gLangService
) {
3362 CallGetService(NS_LANGUAGEATOMSERVICE_CONTRACTID
, &gLangService
);
3367 displayData
.mLang
.GetStringValue(lang
);
3368 visibility
->mLangGroup
= gLangService
->LookupLanguage(lang
);
3372 COMPUTE_END_INHERITED(Visibility
, visibility
)
3376 nsRuleNode::ComputeColorData(void* aStartStruct
,
3377 const nsRuleDataStruct
& aData
,
3378 nsStyleContext
* aContext
,
3379 nsRuleNode
* aHighestNode
,
3380 const RuleDetail aRuleDetail
, PRBool aInherited
)
3382 COMPUTE_START_INHERITED(Color
, (mPresContext
), color
, parentColor
,
3385 // color: color, string, inherit
3386 // Special case for currentColor. According to CSS3, setting color to 'currentColor'
3387 // should behave as if it is inherited
3388 if (colorData
.mColor
.GetUnit() == eCSSUnit_EnumColor
&&
3389 colorData
.mColor
.GetIntValue() == NS_COLOR_CURRENTCOLOR
) {
3390 color
->mColor
= parentColor
->mColor
;
3391 inherited
= PR_TRUE
;
3393 else if (colorData
.mColor
.GetUnit() == eCSSUnit_Initial
) {
3394 color
->mColor
= mPresContext
->DefaultColor();
3397 SetColor(colorData
.mColor
, parentColor
->mColor
, mPresContext
, aContext
, color
->mColor
,
3401 COMPUTE_END_INHERITED(Color
, color
)
3405 nsRuleNode::ComputeBackgroundData(void* aStartStruct
,
3406 const nsRuleDataStruct
& aData
,
3407 nsStyleContext
* aContext
,
3408 nsRuleNode
* aHighestNode
,
3409 const RuleDetail aRuleDetail
, PRBool aInherited
)
3411 COMPUTE_START_RESET(Background
, (mPresContext
), bg
, parentBG
,
3414 // save parentFlags in case bg == parentBG and we clobber them later
3415 PRUint8 parentFlags
= parentBG
->mBackgroundFlags
;
3417 // background-color: color, string, enum (flags), inherit
3418 if (eCSSUnit_Inherit
== colorData
.mBackColor
.GetUnit()) { // do inherit first, so SetColor doesn't do it
3419 bg
->mBackgroundColor
= parentBG
->mBackgroundColor
;
3420 bg
->mBackgroundFlags
&= ~NS_STYLE_BG_COLOR_TRANSPARENT
;
3421 bg
->mBackgroundFlags
|= (parentFlags
& NS_STYLE_BG_COLOR_TRANSPARENT
);
3422 inherited
= PR_TRUE
;
3424 else if (SetColor(colorData
.mBackColor
, parentBG
->mBackgroundColor
,
3425 mPresContext
, aContext
, bg
->mBackgroundColor
, inherited
)) {
3426 bg
->mBackgroundFlags
&= ~NS_STYLE_BG_COLOR_TRANSPARENT
;
3428 else if (eCSSUnit_Enumerated
== colorData
.mBackColor
.GetUnit() ||
3429 eCSSUnit_Initial
== colorData
.mBackColor
.GetUnit()) {
3430 bg
->mBackgroundFlags
|= NS_STYLE_BG_COLOR_TRANSPARENT
;
3433 // background-image: url (stored as image), none, inherit
3434 if (eCSSUnit_Image
== colorData
.mBackImage
.GetUnit()) {
3435 bg
->mBackgroundImage
= colorData
.mBackImage
.GetImageValue();
3437 else if (eCSSUnit_None
== colorData
.mBackImage
.GetUnit() ||
3438 eCSSUnit_Initial
== colorData
.mBackImage
.GetUnit()) {
3439 bg
->mBackgroundImage
= nsnull
;
3441 else if (eCSSUnit_Inherit
== colorData
.mBackImage
.GetUnit()) {
3442 inherited
= PR_TRUE
;
3443 bg
->mBackgroundImage
= parentBG
->mBackgroundImage
;
3446 if (bg
->mBackgroundImage
) {
3447 bg
->mBackgroundFlags
&= ~NS_STYLE_BG_IMAGE_NONE
;
3449 bg
->mBackgroundFlags
|= NS_STYLE_BG_IMAGE_NONE
;
3452 // background-repeat: enum, inherit
3453 if (eCSSUnit_Enumerated
== colorData
.mBackRepeat
.GetUnit()) {
3454 bg
->mBackgroundRepeat
= colorData
.mBackRepeat
.GetIntValue();
3456 else if (eCSSUnit_Inherit
== colorData
.mBackRepeat
.GetUnit()) {
3457 inherited
= PR_TRUE
;
3458 bg
->mBackgroundRepeat
= parentBG
->mBackgroundRepeat
;
3460 else if (eCSSUnit_Initial
== colorData
.mBackRepeat
.GetUnit()) {
3461 bg
->mBackgroundRepeat
= NS_STYLE_BG_REPEAT_XY
;
3464 // background-attachment: enum, inherit
3465 if (eCSSUnit_Enumerated
== colorData
.mBackAttachment
.GetUnit()) {
3466 bg
->mBackgroundAttachment
= colorData
.mBackAttachment
.GetIntValue();
3468 else if (eCSSUnit_Inherit
== colorData
.mBackAttachment
.GetUnit()) {
3469 inherited
= PR_TRUE
;
3470 bg
->mBackgroundAttachment
= parentBG
->mBackgroundAttachment
;
3472 else if (eCSSUnit_Initial
== colorData
.mBackAttachment
.GetUnit()) {
3473 bg
->mBackgroundAttachment
= NS_STYLE_BG_ATTACHMENT_SCROLL
;
3476 // background-clip: enum, inherit, initial
3477 if (eCSSUnit_Enumerated
== colorData
.mBackClip
.GetUnit()) {
3478 bg
->mBackgroundClip
= colorData
.mBackClip
.GetIntValue();
3480 else if (eCSSUnit_Inherit
== colorData
.mBackClip
.GetUnit()) {
3481 bg
->mBackgroundClip
= parentBG
->mBackgroundClip
;
3483 else if (eCSSUnit_Initial
== colorData
.mBackClip
.GetUnit()) {
3484 bg
->mBackgroundClip
= NS_STYLE_BG_CLIP_BORDER
;
3487 // background-inline-policy: enum, inherit, initial
3488 if (eCSSUnit_Enumerated
== colorData
.mBackInlinePolicy
.GetUnit()) {
3489 bg
->mBackgroundInlinePolicy
= colorData
.mBackInlinePolicy
.GetIntValue();
3491 else if (eCSSUnit_Inherit
== colorData
.mBackInlinePolicy
.GetUnit()) {
3492 bg
->mBackgroundInlinePolicy
= parentBG
->mBackgroundInlinePolicy
;
3494 else if (eCSSUnit_Initial
== colorData
.mBackInlinePolicy
.GetUnit()) {
3495 bg
->mBackgroundInlinePolicy
= NS_STYLE_BG_INLINE_POLICY_CONTINUOUS
;
3498 // background-origin: enum, inherit, initial
3499 if (eCSSUnit_Enumerated
== colorData
.mBackOrigin
.GetUnit()) {
3500 bg
->mBackgroundOrigin
= colorData
.mBackOrigin
.GetIntValue();
3502 else if (eCSSUnit_Inherit
== colorData
.mBackOrigin
.GetUnit()) {
3503 bg
->mBackgroundOrigin
= parentBG
->mBackgroundOrigin
;
3505 else if (eCSSUnit_Initial
== colorData
.mBackOrigin
.GetUnit()) {
3506 bg
->mBackgroundOrigin
= NS_STYLE_BG_ORIGIN_PADDING
;
3509 // background-position: enum, length, percent (flags), inherit
3510 if (eCSSUnit_Percent
== colorData
.mBackPosition
.mXValue
.GetUnit()) {
3511 bg
->mBackgroundXPosition
.mFloat
= colorData
.mBackPosition
.mXValue
.GetPercentValue();
3512 bg
->mBackgroundFlags
|= NS_STYLE_BG_X_POSITION_PERCENT
;
3513 bg
->mBackgroundFlags
&= ~NS_STYLE_BG_X_POSITION_LENGTH
;
3515 else if (colorData
.mBackPosition
.mXValue
.IsLengthUnit()) {
3516 bg
->mBackgroundXPosition
.mCoord
= CalcLength(colorData
.mBackPosition
.mXValue
,
3517 aContext
, mPresContext
, inherited
);
3518 bg
->mBackgroundFlags
|= NS_STYLE_BG_X_POSITION_LENGTH
;
3519 bg
->mBackgroundFlags
&= ~NS_STYLE_BG_X_POSITION_PERCENT
;
3521 else if (eCSSUnit_Enumerated
== colorData
.mBackPosition
.mXValue
.GetUnit()) {
3522 switch (colorData
.mBackPosition
.mXValue
.GetIntValue()) {
3523 case NS_STYLE_BG_POSITION_LEFT
:
3524 bg
->mBackgroundXPosition
.mFloat
= 0.0f
;
3526 case NS_STYLE_BG_POSITION_RIGHT
:
3527 bg
->mBackgroundXPosition
.mFloat
= 1.0f
;
3530 NS_NOTREACHED("unexpected value");
3532 case NS_STYLE_BG_POSITION_CENTER
:
3533 bg
->mBackgroundXPosition
.mFloat
= 0.5f
;
3536 bg
->mBackgroundFlags
|= NS_STYLE_BG_X_POSITION_PERCENT
;
3537 bg
->mBackgroundFlags
&= ~NS_STYLE_BG_X_POSITION_LENGTH
;
3539 else if (eCSSUnit_Inherit
== colorData
.mBackPosition
.mXValue
.GetUnit()) {
3540 inherited
= PR_TRUE
;
3541 bg
->mBackgroundXPosition
= parentBG
->mBackgroundXPosition
;
3542 bg
->mBackgroundFlags
&= ~(NS_STYLE_BG_X_POSITION_LENGTH
| NS_STYLE_BG_X_POSITION_PERCENT
);
3543 bg
->mBackgroundFlags
|= (parentFlags
& (NS_STYLE_BG_X_POSITION_LENGTH
| NS_STYLE_BG_X_POSITION_PERCENT
));
3545 else if (eCSSUnit_Initial
== colorData
.mBackPosition
.mXValue
.GetUnit()) {
3546 bg
->mBackgroundFlags
&= ~(NS_STYLE_BG_X_POSITION_LENGTH
| NS_STYLE_BG_X_POSITION_PERCENT
);
3549 if (eCSSUnit_Percent
== colorData
.mBackPosition
.mYValue
.GetUnit()) {
3550 bg
->mBackgroundYPosition
.mFloat
= colorData
.mBackPosition
.mYValue
.GetPercentValue();
3551 bg
->mBackgroundFlags
|= NS_STYLE_BG_Y_POSITION_PERCENT
;
3552 bg
->mBackgroundFlags
&= ~NS_STYLE_BG_Y_POSITION_LENGTH
;
3554 else if (colorData
.mBackPosition
.mYValue
.IsLengthUnit()) {
3555 bg
->mBackgroundYPosition
.mCoord
= CalcLength(colorData
.mBackPosition
.mYValue
,
3556 aContext
, mPresContext
, inherited
);
3557 bg
->mBackgroundFlags
|= NS_STYLE_BG_Y_POSITION_LENGTH
;
3558 bg
->mBackgroundFlags
&= ~NS_STYLE_BG_Y_POSITION_PERCENT
;
3560 else if (eCSSUnit_Enumerated
== colorData
.mBackPosition
.mYValue
.GetUnit()) {
3561 switch (colorData
.mBackPosition
.mYValue
.GetIntValue()) {
3562 case NS_STYLE_BG_POSITION_TOP
:
3563 bg
->mBackgroundYPosition
.mFloat
= 0.0f
;
3565 case NS_STYLE_BG_POSITION_BOTTOM
:
3566 bg
->mBackgroundYPosition
.mFloat
= 1.0f
;
3569 NS_NOTREACHED("unexpected value");
3571 case NS_STYLE_BG_POSITION_CENTER
:
3572 bg
->mBackgroundYPosition
.mFloat
= 0.5f
;
3575 bg
->mBackgroundFlags
|= NS_STYLE_BG_Y_POSITION_PERCENT
;
3576 bg
->mBackgroundFlags
&= ~NS_STYLE_BG_Y_POSITION_LENGTH
;
3578 else if (eCSSUnit_Inherit
== colorData
.mBackPosition
.mYValue
.GetUnit()) {
3579 inherited
= PR_TRUE
;
3580 bg
->mBackgroundYPosition
= parentBG
->mBackgroundYPosition
;
3581 bg
->mBackgroundFlags
&= ~(NS_STYLE_BG_Y_POSITION_LENGTH
| NS_STYLE_BG_Y_POSITION_PERCENT
);
3582 bg
->mBackgroundFlags
|= (parentFlags
& (NS_STYLE_BG_Y_POSITION_LENGTH
| NS_STYLE_BG_Y_POSITION_PERCENT
));
3584 else if (eCSSUnit_Initial
== colorData
.mBackPosition
.mYValue
.GetUnit()) {
3585 bg
->mBackgroundFlags
&= ~(NS_STYLE_BG_Y_POSITION_LENGTH
| NS_STYLE_BG_Y_POSITION_PERCENT
);
3588 COMPUTE_END_RESET(Background
, bg
)
3592 nsRuleNode::ComputeMarginData(void* aStartStruct
,
3593 const nsRuleDataStruct
& aData
,
3594 nsStyleContext
* aContext
,
3595 nsRuleNode
* aHighestNode
,
3596 const RuleDetail aRuleDetail
, PRBool aInherited
)
3598 COMPUTE_START_RESET(Margin
, (), margin
, parentMargin
, Margin
, marginData
)
3600 // margin: length, percent, auto, inherit
3602 nsCSSRect
ourMargin(marginData
.mMargin
);
3603 AdjustLogicalBoxProp(aContext
,
3604 marginData
.mMarginLeftLTRSource
,
3605 marginData
.mMarginLeftRTLSource
,
3606 marginData
.mMarginStart
, marginData
.mMarginEnd
,
3607 NS_SIDE_LEFT
, ourMargin
, inherited
);
3608 AdjustLogicalBoxProp(aContext
,
3609 marginData
.mMarginRightLTRSource
,
3610 marginData
.mMarginRightRTLSource
,
3611 marginData
.mMarginEnd
, marginData
.mMarginStart
,
3612 NS_SIDE_RIGHT
, ourMargin
, inherited
);
3613 NS_FOR_CSS_SIDES(side
) {
3614 nsStyleCoord parentCoord
= parentMargin
->mMargin
.Get(side
);
3615 if (SetCoord(ourMargin
.*(nsCSSRect::sides
[side
]),
3616 coord
, parentCoord
, SETCOORD_LPAH
| SETCOORD_INITIAL_ZERO
,
3617 aContext
, mPresContext
, inherited
)) {
3618 margin
->mMargin
.Set(side
, coord
);
3622 margin
->RecalcData();
3623 COMPUTE_END_RESET(Margin
, margin
)
3627 nsRuleNode::ComputeBorderData(void* aStartStruct
,
3628 const nsRuleDataStruct
& aData
,
3629 nsStyleContext
* aContext
,
3630 nsRuleNode
* aHighestNode
,
3631 const RuleDetail aRuleDetail
, PRBool aInherited
)
3633 COMPUTE_START_RESET(Border
, (mPresContext
), border
, parentBorder
,
3636 // border-width, border-*-width: length, enum, inherit
3638 nsCSSRect
ourBorderWidth(marginData
.mBorderWidth
);
3639 AdjustLogicalBoxProp(aContext
,
3640 marginData
.mBorderLeftWidthLTRSource
,
3641 marginData
.mBorderLeftWidthRTLSource
,
3642 marginData
.mBorderStartWidth
,
3643 marginData
.mBorderEndWidth
,
3644 NS_SIDE_LEFT
, ourBorderWidth
, inherited
);
3645 AdjustLogicalBoxProp(aContext
,
3646 marginData
.mBorderRightWidthLTRSource
,
3647 marginData
.mBorderRightWidthRTLSource
,
3648 marginData
.mBorderEndWidth
,
3649 marginData
.mBorderStartWidth
,
3650 NS_SIDE_RIGHT
, ourBorderWidth
, inherited
);
3651 { // scope for compilers with broken |for| loop scoping
3652 NS_FOR_CSS_SIDES(side
) {
3653 const nsCSSValue
&value
= ourBorderWidth
.*(nsCSSRect::sides
[side
]);
3654 NS_ASSERTION(eCSSUnit_Percent
!= value
.GetUnit(),
3655 "Percentage borders not implemented yet "
3656 "If implementing, make sure to fix all consumers of "
3657 "nsStyleBorder, the IsPercentageAwareChild method, "
3658 "the nsAbsoluteContainingBlock::FrameDependsOnContainer "
3660 "nsLineLayout::IsPercentageAwareReplacedElement method "
3661 "and probably some other places");
3662 if (eCSSUnit_Enumerated
== value
.GetUnit()) {
3663 NS_ASSERTION(value
.GetIntValue() == NS_STYLE_BORDER_WIDTH_THIN
||
3664 value
.GetIntValue() == NS_STYLE_BORDER_WIDTH_MEDIUM
||
3665 value
.GetIntValue() == NS_STYLE_BORDER_WIDTH_THICK
,
3666 "Unexpected enum value");
3667 border
->SetBorderWidth(side
,
3668 (mPresContext
->GetBorderWidthTable())[value
.GetIntValue()]);
3670 // OK to pass bad aParentCoord since we're not passing SETCOORD_INHERIT
3671 else if (SetCoord(value
, coord
, nsStyleCoord(), SETCOORD_LENGTH
,
3672 aContext
, mPresContext
, inherited
)) {
3673 if (coord
.GetUnit() == eStyleUnit_Coord
) {
3674 border
->SetBorderWidth(side
, coord
.GetCoordValue());
3678 NS_ASSERTION(coord
.GetUnit() == eStyleUnit_Chars
, "unexpected unit");
3679 NS_WARNING("Border set in chars; we don't handle that");
3683 else if (eCSSUnit_Inherit
== value
.GetUnit()) {
3684 inherited
= PR_TRUE
;
3685 border
->SetBorderWidth(side
, parentBorder
->GetBorderWidth(side
));
3687 else if (eCSSUnit_Initial
== value
.GetUnit()) {
3688 border
->SetBorderWidth(side
,
3689 (mPresContext
->GetBorderWidthTable())[NS_STYLE_BORDER_WIDTH_MEDIUM
]);
3694 // border-style, border-*-style: enum, none, inherit
3695 nsCSSRect
ourStyle(marginData
.mBorderStyle
);
3696 AdjustLogicalBoxProp(aContext
,
3697 marginData
.mBorderLeftStyleLTRSource
,
3698 marginData
.mBorderLeftStyleRTLSource
,
3699 marginData
.mBorderStartStyle
, marginData
.mBorderEndStyle
,
3700 NS_SIDE_LEFT
, ourStyle
, inherited
);
3701 AdjustLogicalBoxProp(aContext
,
3702 marginData
.mBorderRightStyleLTRSource
,
3703 marginData
.mBorderRightStyleRTLSource
,
3704 marginData
.mBorderEndStyle
, marginData
.mBorderStartStyle
,
3705 NS_SIDE_RIGHT
, ourStyle
, inherited
);
3706 { // scope for compilers with broken |for| loop scoping
3707 NS_FOR_CSS_SIDES(side
) {
3708 const nsCSSValue
&value
= ourStyle
.*(nsCSSRect::sides
[side
]);
3709 nsCSSUnit unit
= value
.GetUnit();
3710 if (eCSSUnit_Enumerated
== unit
) {
3711 border
->SetBorderStyle(side
, value
.GetIntValue());
3713 else if (eCSSUnit_None
== unit
|| eCSSUnit_Initial
== unit
) {
3714 border
->SetBorderStyle(side
, NS_STYLE_BORDER_STYLE_NONE
);
3716 else if (eCSSUnit_Inherit
== unit
) {
3717 inherited
= PR_TRUE
;
3718 border
->SetBorderStyle(side
, parentBorder
->GetBorderStyle(side
));
3723 // -moz-border-*-colors: color, string, enum
3724 nscolor borderColor
;
3725 nscolor unused
= NS_RGB(0,0,0);
3727 { // scope for compilers with broken |for| loop scoping
3728 NS_FOR_CSS_SIDES(side
) {
3729 nsCSSValueList
* list
=
3730 marginData
.mBorderColors
.*(nsCSSValueListRect::sides
[side
]);
3731 // FIXME Bug 389404: Implement inherit and -moz-initial.
3733 // Some composite border color information has been specified for this
3735 border
->EnsureBorderColors();
3736 border
->ClearBorderColors(side
);
3738 if (SetColor(list
->mValue
, unused
, mPresContext
, aContext
, borderColor
, inherited
))
3739 border
->AppendBorderColor(side
, borderColor
, PR_FALSE
);
3740 else if (eCSSUnit_Enumerated
== list
->mValue
.GetUnit() &&
3741 NS_STYLE_COLOR_TRANSPARENT
== list
->mValue
.GetIntValue())
3742 border
->AppendBorderColor(side
, nsnull
, PR_TRUE
);
3749 // border-color, border-*-color: color, string, enum, inherit
3750 nsCSSRect
ourBorderColor(marginData
.mBorderColor
);
3753 AdjustLogicalBoxProp(aContext
,
3754 marginData
.mBorderLeftColorLTRSource
,
3755 marginData
.mBorderLeftColorRTLSource
,
3756 marginData
.mBorderStartColor
, marginData
.mBorderEndColor
,
3757 NS_SIDE_LEFT
, ourBorderColor
, inherited
);
3758 AdjustLogicalBoxProp(aContext
,
3759 marginData
.mBorderRightColorLTRSource
,
3760 marginData
.mBorderRightColorRTLSource
,
3761 marginData
.mBorderEndColor
, marginData
.mBorderStartColor
,
3762 NS_SIDE_RIGHT
, ourBorderColor
, inherited
);
3763 { // scope for compilers with broken |for| loop scoping
3764 NS_FOR_CSS_SIDES(side
) {
3765 const nsCSSValue
&value
= ourBorderColor
.*(nsCSSRect::sides
[side
]);
3766 if (eCSSUnit_Inherit
== value
.GetUnit()) {
3767 if (parentContext
) {
3768 inherited
= PR_TRUE
;
3769 parentBorder
->GetBorderColor(side
, borderColor
,
3770 transparent
, foreground
);
3772 border
->SetBorderTransparent(side
);
3773 else if (foreground
) {
3774 // We want to inherit the color from the parent, not use the
3775 // color on the element where this chunk of style data will be
3776 // used. We can ensure that the data for the parent are fully
3777 // computed (unlike for the element where this will be used, for
3778 // which the color could be specified on a more specific rule).
3779 border
->SetBorderColor(side
, parentContext
->GetStyleColor()->mColor
);
3781 border
->SetBorderColor(side
, borderColor
);
3784 border
->SetBorderToForeground(side
);
3787 else if (SetColor(value
, unused
, mPresContext
, aContext
, borderColor
, inherited
)) {
3788 border
->SetBorderColor(side
, borderColor
);
3790 else if (eCSSUnit_Enumerated
== value
.GetUnit()) {
3791 switch (value
.GetIntValue()) {
3792 case NS_STYLE_COLOR_TRANSPARENT
:
3793 border
->SetBorderTransparent(side
);
3795 case NS_STYLE_COLOR_MOZ_USE_TEXT_COLOR
:
3796 border
->SetBorderToForeground(side
);
3800 else if (eCSSUnit_Initial
== value
.GetUnit()) {
3801 border
->SetBorderToForeground(side
);
3806 // -moz-border-radius: length, percent, inherit
3807 { // scope for compilers with broken |for| loop scoping
3808 NS_FOR_CSS_SIDES(side
) {
3809 nsStyleCoord parentCoord
= parentBorder
->mBorderRadius
.Get(side
);
3810 if (SetCoord(marginData
.mBorderRadius
.*(nsCSSRect::sides
[side
]), coord
,
3811 parentCoord
, SETCOORD_LPH
| SETCOORD_INITIAL_ZERO
,
3812 aContext
, mPresContext
, inherited
))
3813 border
->mBorderRadius
.Set(side
, coord
);
3817 // float-edge: enum, inherit
3818 if (eCSSUnit_Enumerated
== marginData
.mFloatEdge
.GetUnit())
3819 border
->mFloatEdge
= marginData
.mFloatEdge
.GetIntValue();
3820 else if (eCSSUnit_Inherit
== marginData
.mFloatEdge
.GetUnit()) {
3821 inherited
= PR_TRUE
;
3822 border
->mFloatEdge
= parentBorder
->mFloatEdge
;
3824 else if (eCSSUnit_Initial
== marginData
.mFloatEdge
.GetUnit()) {
3825 border
->mFloatEdge
= NS_STYLE_FLOAT_EDGE_CONTENT
;
3828 COMPUTE_END_RESET(Border
, border
)
3832 nsRuleNode::ComputePaddingData(void* aStartStruct
,
3833 const nsRuleDataStruct
& aData
,
3834 nsStyleContext
* aContext
,
3835 nsRuleNode
* aHighestNode
,
3836 const RuleDetail aRuleDetail
, PRBool aInherited
)
3838 COMPUTE_START_RESET(Padding
, (), padding
, parentPadding
, Margin
, marginData
)
3840 // padding: length, percent, inherit
3842 nsCSSRect
ourPadding(marginData
.mPadding
);
3843 AdjustLogicalBoxProp(aContext
,
3844 marginData
.mPaddingLeftLTRSource
,
3845 marginData
.mPaddingLeftRTLSource
,
3846 marginData
.mPaddingStart
, marginData
.mPaddingEnd
,
3847 NS_SIDE_LEFT
, ourPadding
, inherited
);
3848 AdjustLogicalBoxProp(aContext
,
3849 marginData
.mPaddingRightLTRSource
,
3850 marginData
.mPaddingRightRTLSource
,
3851 marginData
.mPaddingEnd
, marginData
.mPaddingStart
,
3852 NS_SIDE_RIGHT
, ourPadding
, inherited
);
3853 NS_FOR_CSS_SIDES(side
) {
3854 nsStyleCoord parentCoord
= parentPadding
->mPadding
.Get(side
);
3855 if (SetCoord(ourPadding
.*(nsCSSRect::sides
[side
]),
3856 coord
, parentCoord
, SETCOORD_LPH
| SETCOORD_INITIAL_ZERO
,
3857 aContext
, mPresContext
, inherited
)) {
3858 padding
->mPadding
.Set(side
, coord
);
3862 padding
->RecalcData();
3863 COMPUTE_END_RESET(Padding
, padding
)
3867 nsRuleNode::ComputeOutlineData(void* aStartStruct
,
3868 const nsRuleDataStruct
& aData
,
3869 nsStyleContext
* aContext
,
3870 nsRuleNode
* aHighestNode
,
3871 const RuleDetail aRuleDetail
, PRBool aInherited
)
3873 COMPUTE_START_RESET(Outline
, (mPresContext
), outline
, parentOutline
,
3876 // outline-width: length, enum, inherit
3877 if (eCSSUnit_Initial
== marginData
.mOutlineWidth
.GetUnit()) {
3878 outline
->mOutlineWidth
=
3879 nsStyleCoord(NS_STYLE_BORDER_WIDTH_MEDIUM
, eStyleUnit_Enumerated
);
3882 SetCoord(marginData
.mOutlineWidth
, outline
->mOutlineWidth
,
3883 parentOutline
->mOutlineWidth
, SETCOORD_LEH
, aContext
,
3884 mPresContext
, inherited
);
3887 // outline-offset: length, inherit
3888 SetCoord(marginData
.mOutlineOffset
, outline
->mOutlineOffset
, parentOutline
->mOutlineOffset
,
3889 SETCOORD_LH
| SETCOORD_INITIAL_ZERO
, aContext
, mPresContext
,
3893 // outline-color: color, string, enum, inherit
3894 nscolor outlineColor
;
3895 nscolor unused
= NS_RGB(0,0,0);
3896 if (eCSSUnit_Inherit
== marginData
.mOutlineColor
.GetUnit()) {
3897 if (parentContext
) {
3898 inherited
= PR_TRUE
;
3899 if (parentOutline
->GetOutlineColor(outlineColor
))
3900 outline
->SetOutlineColor(outlineColor
);
3902 #ifdef GFX_HAS_INVERT
3903 outline
->SetOutlineInitialColor();
3905 // We want to inherit the color from the parent, not use the
3906 // color on the element where this chunk of style data will be
3907 // used. We can ensure that the data for the parent are fully
3908 // computed (unlike for the element where this will be used, for
3909 // which the color could be specified on a more specific rule).
3910 outline
->SetOutlineColor(parentContext
->GetStyleColor()->mColor
);
3914 outline
->SetOutlineInitialColor();
3917 else if (SetColor(marginData
.mOutlineColor
, unused
, mPresContext
, aContext
, outlineColor
, inherited
))
3918 outline
->SetOutlineColor(outlineColor
);
3919 else if (eCSSUnit_Enumerated
== marginData
.mOutlineColor
.GetUnit() ||
3920 eCSSUnit_Initial
== marginData
.mOutlineColor
.GetUnit()) {
3921 outline
->SetOutlineInitialColor();
3924 // -moz-outline-radius: length, percent, inherit
3926 { // scope for compilers with broken |for| loop scoping
3927 NS_FOR_CSS_SIDES(side
) {
3928 nsStyleCoord parentCoord
= parentOutline
->mOutlineRadius
.Get(side
);
3929 if (SetCoord(marginData
.mOutlineRadius
.*(nsCSSRect::sides
[side
]), coord
,
3930 parentCoord
, SETCOORD_LPH
| SETCOORD_INITIAL_ZERO
,
3931 aContext
, mPresContext
, inherited
))
3932 outline
->mOutlineRadius
.Set(side
, coord
);
3936 // outline-style: auto, enum, none, inherit
3937 if (eCSSUnit_Enumerated
== marginData
.mOutlineStyle
.GetUnit())
3938 outline
->SetOutlineStyle(marginData
.mOutlineStyle
.GetIntValue());
3939 else if (eCSSUnit_None
== marginData
.mOutlineStyle
.GetUnit() ||
3940 eCSSUnit_Initial
== marginData
.mOutlineStyle
.GetUnit())
3941 outline
->SetOutlineStyle(NS_STYLE_BORDER_STYLE_NONE
);
3942 else if (eCSSUnit_Auto
== marginData
.mOutlineStyle
.GetUnit()) {
3943 outline
->SetOutlineStyle(NS_STYLE_BORDER_STYLE_AUTO
);
3944 } else if (eCSSUnit_Inherit
== marginData
.mOutlineStyle
.GetUnit()) {
3945 inherited
= PR_TRUE
;
3946 outline
->SetOutlineStyle(parentOutline
->GetOutlineStyle());
3949 outline
->RecalcData(mPresContext
);
3950 COMPUTE_END_RESET(Outline
, outline
)
3954 nsRuleNode::ComputeListData(void* aStartStruct
,
3955 const nsRuleDataStruct
& aData
,
3956 nsStyleContext
* aContext
,
3957 nsRuleNode
* aHighestNode
,
3958 const RuleDetail aRuleDetail
, PRBool aInherited
)
3960 COMPUTE_START_INHERITED(List
, (), list
, parentList
, List
, listData
)
3962 // list-style-type: enum, none, inherit
3963 if (eCSSUnit_Enumerated
== listData
.mType
.GetUnit()) {
3964 list
->mListStyleType
= listData
.mType
.GetIntValue();
3966 else if (eCSSUnit_None
== listData
.mType
.GetUnit()) {
3967 list
->mListStyleType
= NS_STYLE_LIST_STYLE_NONE
;
3969 else if (eCSSUnit_Inherit
== listData
.mType
.GetUnit()) {
3970 inherited
= PR_TRUE
;
3971 list
->mListStyleType
= parentList
->mListStyleType
;
3973 else if (eCSSUnit_Initial
== listData
.mType
.GetUnit()) {
3974 list
->mListStyleType
= NS_STYLE_LIST_STYLE_DISC
;
3977 // list-style-image: url, none, inherit
3978 if (eCSSUnit_Image
== listData
.mImage
.GetUnit()) {
3979 list
->mListStyleImage
= listData
.mImage
.GetImageValue();
3981 else if (eCSSUnit_None
== listData
.mImage
.GetUnit() ||
3982 eCSSUnit_Initial
== listData
.mImage
.GetUnit()) {
3983 list
->mListStyleImage
= nsnull
;
3985 else if (eCSSUnit_Inherit
== listData
.mImage
.GetUnit()) {
3986 inherited
= PR_TRUE
;
3987 list
->mListStyleImage
= parentList
->mListStyleImage
;
3990 // list-style-position: enum, inherit
3991 if (eCSSUnit_Enumerated
== listData
.mPosition
.GetUnit()) {
3992 list
->mListStylePosition
= listData
.mPosition
.GetIntValue();
3994 else if (eCSSUnit_Inherit
== listData
.mPosition
.GetUnit()) {
3995 inherited
= PR_TRUE
;
3996 list
->mListStylePosition
= parentList
->mListStylePosition
;
3998 else if (eCSSUnit_Initial
== listData
.mPosition
.GetUnit()) {
3999 list
->mListStylePosition
= NS_STYLE_LIST_STYLE_POSITION_OUTSIDE
;
4002 // image region property: length, auto, inherit
4003 if (eCSSUnit_Inherit
== listData
.mImageRegion
.mTop
.GetUnit()) { // if one is inherit, they all are
4004 inherited
= PR_TRUE
;
4005 list
->mImageRegion
= parentList
->mImageRegion
;
4007 // if one is -moz-initial, they all are
4008 else if (eCSSUnit_Initial
== listData
.mImageRegion
.mTop
.GetUnit()) {
4009 list
->mImageRegion
.Empty();
4012 if (eCSSUnit_Auto
== listData
.mImageRegion
.mTop
.GetUnit())
4013 list
->mImageRegion
.y
= 0;
4014 else if (listData
.mImageRegion
.mTop
.IsLengthUnit())
4015 list
->mImageRegion
.y
= CalcLength(listData
.mImageRegion
.mTop
, aContext
, mPresContext
, inherited
);
4017 if (eCSSUnit_Auto
== listData
.mImageRegion
.mBottom
.GetUnit())
4018 list
->mImageRegion
.height
= 0;
4019 else if (listData
.mImageRegion
.mBottom
.IsLengthUnit())
4020 list
->mImageRegion
.height
= CalcLength(listData
.mImageRegion
.mBottom
, aContext
,
4021 mPresContext
, inherited
) - list
->mImageRegion
.y
;
4023 if (eCSSUnit_Auto
== listData
.mImageRegion
.mLeft
.GetUnit())
4024 list
->mImageRegion
.x
= 0;
4025 else if (listData
.mImageRegion
.mLeft
.IsLengthUnit())
4026 list
->mImageRegion
.x
= CalcLength(listData
.mImageRegion
.mLeft
, aContext
, mPresContext
, inherited
);
4028 if (eCSSUnit_Auto
== listData
.mImageRegion
.mRight
.GetUnit())
4029 list
->mImageRegion
.width
= 0;
4030 else if (listData
.mImageRegion
.mRight
.IsLengthUnit())
4031 list
->mImageRegion
.width
= CalcLength(listData
.mImageRegion
.mRight
, aContext
, mPresContext
, inherited
) -
4032 list
->mImageRegion
.x
;
4035 COMPUTE_END_INHERITED(List
, list
)
4039 nsRuleNode::ComputePositionData(void* aStartStruct
,
4040 const nsRuleDataStruct
& aData
,
4041 nsStyleContext
* aContext
,
4042 nsRuleNode
* aHighestNode
,
4043 const RuleDetail aRuleDetail
, PRBool aInherited
)
4045 COMPUTE_START_RESET(Position
, (), pos
, parentPos
, Position
, posData
)
4047 // box offsets: length, percent, auto, inherit
4049 NS_FOR_CSS_SIDES(side
) {
4050 nsStyleCoord parentCoord
= parentPos
->mOffset
.Get(side
);
4051 if (SetCoord(posData
.mOffset
.*(nsCSSRect::sides
[side
]),
4052 coord
, parentCoord
, SETCOORD_LPAH
| SETCOORD_INITIAL_AUTO
,
4053 aContext
, mPresContext
, inherited
)) {
4054 pos
->mOffset
.Set(side
, coord
);
4058 SetCoord(posData
.mWidth
, pos
->mWidth
, parentPos
->mWidth
,
4059 SETCOORD_LPAEH
| SETCOORD_INITIAL_AUTO
, aContext
,
4060 mPresContext
, inherited
);
4061 SetCoord(posData
.mMinWidth
, pos
->mMinWidth
, parentPos
->mMinWidth
,
4062 SETCOORD_LPEH
| SETCOORD_INITIAL_ZERO
, aContext
,
4063 mPresContext
, inherited
);
4064 SetCoord(posData
.mMaxWidth
, pos
->mMaxWidth
, parentPos
->mMaxWidth
,
4065 SETCOORD_LPOEH
| SETCOORD_INITIAL_NONE
, aContext
,
4066 mPresContext
, inherited
);
4068 SetCoord(posData
.mHeight
, pos
->mHeight
, parentPos
->mHeight
,
4069 SETCOORD_LPAH
| SETCOORD_INITIAL_AUTO
, aContext
,
4070 mPresContext
, inherited
);
4071 SetCoord(posData
.mMinHeight
, pos
->mMinHeight
, parentPos
->mMinHeight
,
4072 SETCOORD_LPH
| SETCOORD_INITIAL_ZERO
, aContext
,
4073 mPresContext
, inherited
);
4074 SetCoord(posData
.mMaxHeight
, pos
->mMaxHeight
, parentPos
->mMaxHeight
,
4075 SETCOORD_LPOH
| SETCOORD_INITIAL_NONE
, aContext
,
4076 mPresContext
, inherited
);
4078 // box-sizing: enum, inherit
4079 if (eCSSUnit_Enumerated
== posData
.mBoxSizing
.GetUnit()) {
4080 pos
->mBoxSizing
= posData
.mBoxSizing
.GetIntValue();
4082 else if (eCSSUnit_Inherit
== posData
.mBoxSizing
.GetUnit()) {
4083 inherited
= PR_TRUE
;
4084 pos
->mBoxSizing
= parentPos
->mBoxSizing
;
4086 else if (eCSSUnit_Initial
== posData
.mBoxSizing
.GetUnit()) {
4087 pos
->mBoxSizing
= NS_STYLE_BOX_SIZING_CONTENT
;
4091 if (! SetCoord(posData
.mZIndex
, pos
->mZIndex
, parentPos
->mZIndex
,
4092 SETCOORD_IA
| SETCOORD_INITIAL_AUTO
, aContext
,
4093 nsnull
, inherited
)) {
4094 if (eCSSUnit_Inherit
== posData
.mZIndex
.GetUnit()) {
4095 // handle inherit, because it's ok to inherit 'auto' here
4096 inherited
= PR_TRUE
;
4097 pos
->mZIndex
= parentPos
->mZIndex
;
4101 COMPUTE_END_RESET(Position
, pos
)
4105 nsRuleNode::ComputeTableData(void* aStartStruct
,
4106 const nsRuleDataStruct
& aData
,
4107 nsStyleContext
* aContext
,
4108 nsRuleNode
* aHighestNode
,
4109 const RuleDetail aRuleDetail
, PRBool aInherited
)
4111 COMPUTE_START_RESET(Table
, (), table
, parentTable
, Table
, tableData
)
4113 // table-layout: auto, enum, inherit
4114 if (eCSSUnit_Enumerated
== tableData
.mLayout
.GetUnit())
4115 table
->mLayoutStrategy
= tableData
.mLayout
.GetIntValue();
4116 else if (eCSSUnit_Auto
== tableData
.mLayout
.GetUnit() ||
4117 eCSSUnit_Initial
== tableData
.mLayout
.GetUnit())
4118 table
->mLayoutStrategy
= NS_STYLE_TABLE_LAYOUT_AUTO
;
4119 else if (eCSSUnit_Inherit
== tableData
.mLayout
.GetUnit()) {
4120 inherited
= PR_TRUE
;
4121 table
->mLayoutStrategy
= parentTable
->mLayoutStrategy
;
4124 // rules: enum (not a real CSS prop)
4125 if (eCSSUnit_Enumerated
== tableData
.mRules
.GetUnit())
4126 table
->mRules
= tableData
.mRules
.GetIntValue();
4128 // frame: enum (not a real CSS prop)
4129 if (eCSSUnit_Enumerated
== tableData
.mFrame
.GetUnit())
4130 table
->mFrame
= tableData
.mFrame
.GetIntValue();
4132 // cols: enum, int (not a real CSS prop)
4133 if (eCSSUnit_Enumerated
== tableData
.mCols
.GetUnit() ||
4134 eCSSUnit_Integer
== tableData
.mCols
.GetUnit())
4135 table
->mCols
= tableData
.mCols
.GetIntValue();
4137 // span: pixels (not a real CSS prop)
4138 if (eCSSUnit_Enumerated
== tableData
.mSpan
.GetUnit() ||
4139 eCSSUnit_Integer
== tableData
.mSpan
.GetUnit())
4140 table
->mSpan
= tableData
.mSpan
.GetIntValue();
4142 COMPUTE_END_RESET(Table
, table
)
4146 nsRuleNode::ComputeTableBorderData(void* aStartStruct
,
4147 const nsRuleDataStruct
& aData
,
4148 nsStyleContext
* aContext
,
4149 nsRuleNode
* aHighestNode
,
4150 const RuleDetail aRuleDetail
, PRBool aInherited
)
4152 COMPUTE_START_INHERITED(TableBorder
, (mPresContext
), table
, parentTable
,
4155 // border-collapse: enum, inherit
4156 if (eCSSUnit_Enumerated
== tableData
.mBorderCollapse
.GetUnit()) {
4157 table
->mBorderCollapse
= tableData
.mBorderCollapse
.GetIntValue();
4159 else if (eCSSUnit_Inherit
== tableData
.mBorderCollapse
.GetUnit()) {
4160 inherited
= PR_TRUE
;
4161 table
->mBorderCollapse
= parentTable
->mBorderCollapse
;
4163 else if (eCSSUnit_Initial
== tableData
.mBorderCollapse
.GetUnit()) {
4164 table
->mBorderCollapse
= NS_STYLE_BORDER_SEPARATE
;
4167 // border-spacing-x: length, inherit
4168 SetCoord(tableData
.mBorderSpacing
.mXValue
, table
->mBorderSpacingX
,
4169 parentTable
->mBorderSpacingX
, SETCOORD_LH
| SETCOORD_INITIAL_ZERO
,
4170 aContext
, mPresContext
, inherited
);
4171 // border-spacing-y: length, inherit
4172 SetCoord(tableData
.mBorderSpacing
.mYValue
, table
->mBorderSpacingY
,
4173 parentTable
->mBorderSpacingY
, SETCOORD_LH
| SETCOORD_INITIAL_ZERO
,
4174 aContext
, mPresContext
, inherited
);
4176 // caption-side: enum, inherit
4177 if (eCSSUnit_Enumerated
== tableData
.mCaptionSide
.GetUnit()) {
4178 table
->mCaptionSide
= tableData
.mCaptionSide
.GetIntValue();
4180 else if (eCSSUnit_Inherit
== tableData
.mCaptionSide
.GetUnit()) {
4181 inherited
= PR_TRUE
;
4182 table
->mCaptionSide
= parentTable
->mCaptionSide
;
4184 else if (eCSSUnit_Initial
== tableData
.mCaptionSide
.GetUnit()) {
4185 table
->mCaptionSide
= NS_STYLE_CAPTION_SIDE_TOP
;
4188 // empty-cells: enum, inherit
4189 if (eCSSUnit_Enumerated
== tableData
.mEmptyCells
.GetUnit()) {
4190 table
->mEmptyCells
= tableData
.mEmptyCells
.GetIntValue();
4192 else if (eCSSUnit_Inherit
== tableData
.mEmptyCells
.GetUnit()) {
4193 inherited
= PR_TRUE
;
4194 table
->mEmptyCells
= parentTable
->mEmptyCells
;
4196 else if (eCSSUnit_Initial
== tableData
.mEmptyCells
.GetUnit()) {
4197 table
->mEmptyCells
=
4198 (mPresContext
->CompatibilityMode() == eCompatibility_NavQuirks
)
4199 ? NS_STYLE_TABLE_EMPTY_CELLS_SHOW_BACKGROUND
4200 : NS_STYLE_TABLE_EMPTY_CELLS_SHOW
;
4204 COMPUTE_END_INHERITED(TableBorder
, table
)
4208 nsRuleNode::ComputeContentData(void* aStartStruct
,
4209 const nsRuleDataStruct
& aData
,
4210 nsStyleContext
* aContext
,
4211 nsRuleNode
* aHighestNode
,
4212 const RuleDetail aRuleDetail
, PRBool aInherited
)
4214 COMPUTE_START_RESET(Content
, (), content
, parentContent
,
4215 Content
, contentData
)
4217 // content: [string, url, counter, attr, enum]+, normal, none, inherit
4219 nsAutoString buffer
;
4220 nsCSSValueList
* contentValue
= contentData
.mContent
;
4222 if (eCSSUnit_Normal
== contentValue
->mValue
.GetUnit() ||
4223 eCSSUnit_None
== contentValue
->mValue
.GetUnit() ||
4224 eCSSUnit_Initial
== contentValue
->mValue
.GetUnit()) {
4225 // "normal", "none", and "initial" all mean no content
4226 content
->AllocateContents(0);
4228 else if (eCSSUnit_Inherit
== contentValue
->mValue
.GetUnit()) {
4229 inherited
= PR_TRUE
;
4230 count
= parentContent
->ContentCount();
4231 if (NS_SUCCEEDED(content
->AllocateContents(count
))) {
4232 while (0 < count
--) {
4233 content
->ContentAt(count
) = parentContent
->ContentAt(count
);
4239 while (contentValue
) {
4241 contentValue
= contentValue
->mNext
;
4243 if (NS_SUCCEEDED(content
->AllocateContents(count
))) {
4244 const nsAutoString nullStr
;
4246 contentValue
= contentData
.mContent
;
4247 while (contentValue
) {
4248 const nsCSSValue
& value
= contentValue
->mValue
;
4249 nsCSSUnit unit
= value
.GetUnit();
4250 nsStyleContentType type
;
4251 nsStyleContentData
&data
= content
->ContentAt(count
++);
4253 case eCSSUnit_String
: type
= eStyleContentType_String
; break;
4254 case eCSSUnit_Image
: type
= eStyleContentType_Image
; break;
4255 case eCSSUnit_Attr
: type
= eStyleContentType_Attr
; break;
4256 case eCSSUnit_Counter
: type
= eStyleContentType_Counter
; break;
4257 case eCSSUnit_Counters
: type
= eStyleContentType_Counters
; break;
4258 case eCSSUnit_Enumerated
:
4259 switch (value
.GetIntValue()) {
4260 case NS_STYLE_CONTENT_OPEN_QUOTE
:
4261 type
= eStyleContentType_OpenQuote
; break;
4262 case NS_STYLE_CONTENT_CLOSE_QUOTE
:
4263 type
= eStyleContentType_CloseQuote
; break;
4264 case NS_STYLE_CONTENT_NO_OPEN_QUOTE
:
4265 type
= eStyleContentType_NoOpenQuote
; break;
4266 case NS_STYLE_CONTENT_NO_CLOSE_QUOTE
:
4267 type
= eStyleContentType_NoCloseQuote
; break;
4268 case NS_STYLE_CONTENT_ALT_CONTENT
:
4269 type
= eStyleContentType_AltContent
; break;
4271 NS_ERROR("bad content value");
4275 NS_ERROR("bad content type");
4278 if (type
== eStyleContentType_Image
) {
4279 data
.mContent
.mImage
= value
.GetImageValue();
4280 NS_IF_ADDREF(data
.mContent
.mImage
);
4282 else if (type
<= eStyleContentType_Attr
) {
4283 value
.GetStringValue(buffer
);
4285 data
.mContent
.mString
= NS_strdup(buffer
.get());
4287 else if (type
<= eStyleContentType_Counters
) {
4288 data
.mContent
.mCounters
= value
.GetArrayValue();
4289 data
.mContent
.mCounters
->AddRef();
4292 data
.mContent
.mString
= nsnull
;
4294 contentValue
= contentValue
->mNext
;
4300 // counter-increment: [string [int]]+, none, inherit
4301 nsCSSCounterData
* ourIncrement
= contentData
.mCounterIncrement
;
4303 if (eCSSUnit_None
== ourIncrement
->mCounter
.GetUnit() ||
4304 eCSSUnit_Initial
== ourIncrement
->mCounter
.GetUnit()) {
4305 content
->AllocateCounterIncrements(0);
4307 else if (eCSSUnit_Inherit
== ourIncrement
->mCounter
.GetUnit()) {
4308 inherited
= PR_TRUE
;
4309 count
= parentContent
->CounterIncrementCount();
4310 if (NS_SUCCEEDED(content
->AllocateCounterIncrements(count
))) {
4311 while (0 < count
--) {
4312 const nsStyleCounterData
*data
=
4313 parentContent
->GetCounterIncrementAt(count
);
4314 content
->SetCounterIncrementAt(count
, data
->mCounter
, data
->mValue
);
4318 else if (eCSSUnit_String
== ourIncrement
->mCounter
.GetUnit()) {
4320 while (ourIncrement
) {
4322 ourIncrement
= ourIncrement
->mNext
;
4324 if (NS_SUCCEEDED(content
->AllocateCounterIncrements(count
))) {
4326 ourIncrement
= contentData
.mCounterIncrement
;
4327 while (ourIncrement
) {
4329 if (eCSSUnit_Integer
== ourIncrement
->mValue
.GetUnit()) {
4330 increment
= ourIncrement
->mValue
.GetIntValue();
4335 ourIncrement
->mCounter
.GetStringValue(buffer
);
4336 content
->SetCounterIncrementAt(count
++, buffer
, increment
);
4337 ourIncrement
= ourIncrement
->mNext
;
4343 // counter-reset: [string [int]]+, none, inherit
4344 nsCSSCounterData
* ourReset
= contentData
.mCounterReset
;
4346 if (eCSSUnit_None
== ourReset
->mCounter
.GetUnit() ||
4347 eCSSUnit_Initial
== ourReset
->mCounter
.GetUnit()) {
4348 content
->AllocateCounterResets(0);
4350 else if (eCSSUnit_Inherit
== ourReset
->mCounter
.GetUnit()) {
4351 inherited
= PR_TRUE
;
4352 count
= parentContent
->CounterResetCount();
4353 if (NS_SUCCEEDED(content
->AllocateCounterResets(count
))) {
4354 while (0 < count
--) {
4355 const nsStyleCounterData
*data
=
4356 parentContent
->GetCounterResetAt(count
);
4357 content
->SetCounterResetAt(count
, data
->mCounter
, data
->mValue
);
4361 else if (eCSSUnit_String
== ourReset
->mCounter
.GetUnit()) {
4365 ourReset
= ourReset
->mNext
;
4367 if (NS_SUCCEEDED(content
->AllocateCounterResets(count
))) {
4369 ourReset
= contentData
.mCounterReset
;
4372 if (eCSSUnit_Integer
== ourReset
->mValue
.GetUnit()) {
4373 reset
= ourReset
->mValue
.GetIntValue();
4378 ourReset
->mCounter
.GetStringValue(buffer
);
4379 content
->SetCounterResetAt(count
++, buffer
, reset
);
4380 ourReset
= ourReset
->mNext
;
4386 // marker-offset: length, auto, inherit
4387 SetCoord(contentData
.mMarkerOffset
, content
->mMarkerOffset
, parentContent
->mMarkerOffset
,
4388 SETCOORD_LH
| SETCOORD_AUTO
| SETCOORD_INITIAL_AUTO
, aContext
,
4389 mPresContext
, inherited
);
4391 COMPUTE_END_RESET(Content
, content
)
4395 nsRuleNode::ComputeQuotesData(void* aStartStruct
,
4396 const nsRuleDataStruct
& aData
,
4397 nsStyleContext
* aContext
,
4398 nsRuleNode
* aHighestNode
,
4399 const RuleDetail aRuleDetail
, PRBool aInherited
)
4401 COMPUTE_START_INHERITED(Quotes
, (), quotes
, parentQuotes
,
4402 Content
, contentData
)
4404 // quotes: [string string]+, none, inherit
4406 nsAutoString buffer
;
4407 nsCSSQuotes
* ourQuotes
= contentData
.mQuotes
;
4409 nsAutoString closeBuffer
;
4410 // FIXME Bug 389406: Implement eCSSUnit_Initial (correctly, unlike
4411 // style structs), and remove the "initial" value from ua.css.
4412 if (eCSSUnit_Inherit
== ourQuotes
->mOpen
.GetUnit()) {
4413 inherited
= PR_TRUE
;
4414 count
= parentQuotes
->QuotesCount();
4415 if (NS_SUCCEEDED(quotes
->AllocateQuotes(count
))) {
4416 while (0 < count
--) {
4417 parentQuotes
->GetQuotesAt(count
, buffer
, closeBuffer
);
4418 quotes
->SetQuotesAt(count
, buffer
, closeBuffer
);
4422 else if (eCSSUnit_None
== ourQuotes
->mOpen
.GetUnit()) {
4423 quotes
->AllocateQuotes(0);
4425 else if (eCSSUnit_String
== ourQuotes
->mOpen
.GetUnit()) {
4429 ourQuotes
= ourQuotes
->mNext
;
4431 if (NS_SUCCEEDED(quotes
->AllocateQuotes(count
))) {
4433 ourQuotes
= contentData
.mQuotes
;
4435 ourQuotes
->mOpen
.GetStringValue(buffer
);
4436 ourQuotes
->mClose
.GetStringValue(closeBuffer
);
4438 Unquote(closeBuffer
);
4439 quotes
->SetQuotesAt(count
++, buffer
, closeBuffer
);
4440 ourQuotes
= ourQuotes
->mNext
;
4446 COMPUTE_END_INHERITED(Quotes
, quotes
)
4450 nsRuleNode::ComputeXULData(void* aStartStruct
,
4451 const nsRuleDataStruct
& aData
,
4452 nsStyleContext
* aContext
,
4453 nsRuleNode
* aHighestNode
,
4454 const RuleDetail aRuleDetail
, PRBool aInherited
)
4456 COMPUTE_START_RESET(XUL
, (), xul
, parentXUL
, XUL
, xulData
)
4458 // box-align: enum, inherit
4459 if (eCSSUnit_Enumerated
== xulData
.mBoxAlign
.GetUnit()) {
4460 xul
->mBoxAlign
= xulData
.mBoxAlign
.GetIntValue();
4462 else if (eCSSUnit_Inherit
== xulData
.mBoxAlign
.GetUnit()) {
4463 inherited
= PR_TRUE
;
4464 xul
->mBoxAlign
= parentXUL
->mBoxAlign
;
4466 else if (eCSSUnit_Initial
== xulData
.mBoxAlign
.GetUnit()) {
4467 xul
->mBoxAlign
= NS_STYLE_BOX_ALIGN_STRETCH
;
4470 // box-direction: enum, inherit
4471 if (eCSSUnit_Enumerated
== xulData
.mBoxDirection
.GetUnit()) {
4472 xul
->mBoxDirection
= xulData
.mBoxDirection
.GetIntValue();
4474 else if (eCSSUnit_Inherit
== xulData
.mBoxDirection
.GetUnit()) {
4475 inherited
= PR_TRUE
;
4476 xul
->mBoxDirection
= parentXUL
->mBoxDirection
;
4478 else if (eCSSUnit_Initial
== xulData
.mBoxDirection
.GetUnit()) {
4479 xul
->mBoxDirection
= NS_STYLE_BOX_DIRECTION_NORMAL
;
4482 // box-flex: factor, inherit
4483 if (eCSSUnit_Number
== xulData
.mBoxFlex
.GetUnit()) {
4484 xul
->mBoxFlex
= xulData
.mBoxFlex
.GetFloatValue();
4486 else if (eCSSUnit_Inherit
== xulData
.mBoxFlex
.GetUnit()) {
4487 inherited
= PR_TRUE
;
4488 xul
->mBoxFlex
= parentXUL
->mBoxFlex
;
4490 else if (eCSSUnit_Initial
== xulData
.mBoxFlex
.GetUnit()) {
4491 xul
->mBoxFlex
= 0.0f
;
4494 // box-orient: enum, inherit
4495 if (eCSSUnit_Enumerated
== xulData
.mBoxOrient
.GetUnit()) {
4496 xul
->mBoxOrient
= xulData
.mBoxOrient
.GetIntValue();
4498 else if (eCSSUnit_Inherit
== xulData
.mBoxOrient
.GetUnit()) {
4499 inherited
= PR_TRUE
;
4500 xul
->mBoxOrient
= parentXUL
->mBoxOrient
;
4502 else if (eCSSUnit_Initial
== xulData
.mBoxOrient
.GetUnit()) {
4503 xul
->mBoxOrient
= NS_STYLE_BOX_ORIENT_HORIZONTAL
;
4506 // box-pack: enum, inherit
4507 if (eCSSUnit_Enumerated
== xulData
.mBoxPack
.GetUnit()) {
4508 xul
->mBoxPack
= xulData
.mBoxPack
.GetIntValue();
4510 else if (eCSSUnit_Inherit
== xulData
.mBoxPack
.GetUnit()) {
4511 inherited
= PR_TRUE
;
4512 xul
->mBoxPack
= parentXUL
->mBoxPack
;
4514 else if (eCSSUnit_Initial
== xulData
.mBoxPack
.GetUnit()) {
4515 xul
->mBoxPack
= NS_STYLE_BOX_PACK_START
;
4518 // box-ordinal-group: integer
4519 if (eCSSUnit_Integer
== xulData
.mBoxOrdinal
.GetUnit()) {
4520 xul
->mBoxOrdinal
= xulData
.mBoxOrdinal
.GetIntValue();
4521 } else if (eCSSUnit_Inherit
== xulData
.mBoxOrdinal
.GetUnit()) {
4522 inherited
= PR_TRUE
;
4523 xul
->mBoxOrdinal
= parentXUL
->mBoxOrdinal
;
4524 } else if (eCSSUnit_Initial
== xulData
.mBoxOrdinal
.GetUnit()) {
4525 xul
->mBoxOrdinal
= 1;
4528 COMPUTE_END_RESET(XUL
, xul
)
4532 nsRuleNode::ComputeColumnData(void* aStartStruct
,
4533 const nsRuleDataStruct
& aData
,
4534 nsStyleContext
* aContext
,
4535 nsRuleNode
* aHighestNode
,
4536 const RuleDetail aRuleDetail
, PRBool aInherited
)
4538 COMPUTE_START_RESET(Column
, (), column
, parent
, Column
, columnData
)
4540 // column-width: length, auto, inherit
4541 SetCoord(columnData
.mColumnWidth
,
4542 column
->mColumnWidth
, parent
->mColumnWidth
,
4543 SETCOORD_LAH
| SETCOORD_INITIAL_AUTO
,
4544 aContext
, mPresContext
, inherited
);
4546 // column-gap: length, percentage, inherit, normal
4547 SetCoord(columnData
.mColumnGap
,
4548 column
->mColumnGap
, parent
->mColumnGap
,
4549 SETCOORD_LPH
| SETCOORD_NORMAL
| SETCOORD_INITIAL_NORMAL
,
4550 aContext
, mPresContext
, inherited
);
4552 // column-count: auto, integer, inherit
4553 if (eCSSUnit_Auto
== columnData
.mColumnCount
.GetUnit() ||
4554 eCSSUnit_Initial
== columnData
.mColumnCount
.GetUnit()) {
4555 column
->mColumnCount
= NS_STYLE_COLUMN_COUNT_AUTO
;
4556 } else if (eCSSUnit_Integer
== columnData
.mColumnCount
.GetUnit()) {
4557 column
->mColumnCount
= columnData
.mColumnCount
.GetIntValue();
4558 // Max 1000 columns - wallpaper for bug 345583.
4559 column
->mColumnCount
= PR_MIN(column
->mColumnCount
, 1000);
4560 } else if (eCSSUnit_Inherit
== columnData
.mColumnCount
.GetUnit()) {
4561 inherited
= PR_TRUE
;
4562 column
->mColumnCount
= parent
->mColumnCount
;
4565 COMPUTE_END_RESET(Column
, column
)
4570 SetSVGPaint(const nsCSSValuePair
& aValue
, const nsStyleSVGPaint
& parentPaint
,
4571 nsPresContext
* aPresContext
, nsStyleContext
*aContext
,
4572 nsStyleSVGPaint
& aResult
, nsStyleSVGPaintType aInitialPaintType
,
4577 if (aValue
.mXValue
.GetUnit() == eCSSUnit_Inherit
) {
4578 aResult
= parentPaint
;
4579 aInherited
= PR_TRUE
;
4580 } else if (aValue
.mXValue
.GetUnit() == eCSSUnit_None
) {
4581 aResult
.SetType(eStyleSVGPaintType_None
);
4582 } else if (aValue
.mXValue
.GetUnit() == eCSSUnit_Initial
) {
4583 aResult
.SetType(aInitialPaintType
);
4584 aResult
.mPaint
.mColor
= NS_RGB(0, 0, 0);
4585 aResult
.mFallbackColor
= NS_RGB(0, 0, 0);
4586 } else if (aValue
.mXValue
.GetUnit() == eCSSUnit_URL
) {
4587 aResult
.SetType(eStyleSVGPaintType_Server
);
4588 aResult
.mPaint
.mPaintServer
= aValue
.mXValue
.GetURLValue();
4589 NS_IF_ADDREF(aResult
.mPaint
.mPaintServer
);
4590 if (aValue
.mYValue
.GetUnit() == eCSSUnit_None
) {
4591 aResult
.mFallbackColor
= NS_RGBA(0, 0, 0, 0);
4593 NS_ASSERTION(aValue
.mYValue
.GetUnit() != eCSSUnit_Inherit
, "cannot inherit fallback colour");
4594 SetColor(aValue
.mYValue
, NS_RGB(0, 0, 0), aPresContext
, aContext
, aResult
.mFallbackColor
, aInherited
);
4596 } else if (SetColor(aValue
.mXValue
, parentPaint
.mPaint
.mColor
, aPresContext
, aContext
, color
, aInherited
)) {
4597 aResult
.SetType(eStyleSVGPaintType_Color
);
4598 aResult
.mPaint
.mColor
= color
;
4603 SetSVGOpacity(const nsCSSValue
& aValue
, float parentOpacity
, float& opacity
, PRBool
& aInherited
)
4605 if (aValue
.GetUnit() == eCSSUnit_Inherit
) {
4606 opacity
= parentOpacity
;
4607 aInherited
= PR_TRUE
;
4609 else if (aValue
.GetUnit() == eCSSUnit_Number
) {
4610 opacity
= aValue
.GetFloatValue();
4611 opacity
= PR_MAX(opacity
, 0.0f
);
4612 opacity
= PR_MIN(opacity
, 1.0f
);
4614 else if (aValue
.GetUnit() == eCSSUnit_Initial
) {
4620 nsRuleNode::ComputeSVGData(void* aStartStruct
,
4621 const nsRuleDataStruct
& aData
,
4622 nsStyleContext
* aContext
,
4623 nsRuleNode
* aHighestNode
,
4624 const RuleDetail aRuleDetail
, PRBool aInherited
)
4626 COMPUTE_START_INHERITED(SVG
, (), svg
, parentSVG
, SVG
, SVGData
)
4628 // clip-rule: enum, inherit
4629 if (eCSSUnit_Enumerated
== SVGData
.mClipRule
.GetUnit()) {
4630 svg
->mClipRule
= SVGData
.mClipRule
.GetIntValue();
4632 else if (eCSSUnit_Inherit
== SVGData
.mClipRule
.GetUnit()) {
4633 inherited
= PR_TRUE
;
4634 svg
->mClipRule
= parentSVG
->mClipRule
;
4636 else if (eCSSUnit_Initial
== SVGData
.mClipRule
.GetUnit()) {
4637 svg
->mClipRule
= NS_STYLE_FILL_RULE_NONZERO
;
4640 // color-interpolation: auto, sRGB, linearRGB, inherit
4641 if (eCSSUnit_Enumerated
== SVGData
.mColorInterpolation
.GetUnit()) {
4642 svg
->mColorInterpolation
= SVGData
.mColorInterpolation
.GetIntValue();
4644 else if (eCSSUnit_Auto
== SVGData
.mColorInterpolation
.GetUnit()) {
4645 svg
->mColorInterpolation
= NS_STYLE_COLOR_INTERPOLATION_AUTO
;
4647 else if (eCSSUnit_Inherit
== SVGData
.mColorInterpolation
.GetUnit()) {
4648 inherited
= PR_TRUE
;
4649 svg
->mColorInterpolation
= parentSVG
->mColorInterpolation
;
4651 else if (eCSSUnit_Initial
== SVGData
.mColorInterpolation
.GetUnit()) {
4652 svg
->mColorInterpolation
= NS_STYLE_COLOR_INTERPOLATION_SRGB
;
4655 // color-interpolation-filters: auto, sRGB, linearRGB, inherit
4656 if (eCSSUnit_Enumerated
== SVGData
.mColorInterpolationFilters
.GetUnit()) {
4657 svg
->mColorInterpolationFilters
= SVGData
.mColorInterpolationFilters
.GetIntValue();
4659 else if (eCSSUnit_Auto
== SVGData
.mColorInterpolationFilters
.GetUnit()) {
4660 svg
->mColorInterpolationFilters
= NS_STYLE_COLOR_INTERPOLATION_AUTO
;
4662 else if (eCSSUnit_Inherit
== SVGData
.mColorInterpolationFilters
.GetUnit()) {
4663 inherited
= PR_TRUE
;
4664 svg
->mColorInterpolationFilters
= parentSVG
->mColorInterpolationFilters
;
4666 else if (eCSSUnit_Initial
== SVGData
.mColorInterpolationFilters
.GetUnit()) {
4667 svg
->mColorInterpolationFilters
= NS_STYLE_COLOR_INTERPOLATION_LINEARRGB
;
4671 SetSVGPaint(SVGData
.mFill
, parentSVG
->mFill
, mPresContext
, aContext
,
4672 svg
->mFill
, eStyleSVGPaintType_Color
, inherited
);
4675 SetSVGOpacity(SVGData
.mFillOpacity
, parentSVG
->mFillOpacity
,
4676 svg
->mFillOpacity
, inherited
);
4678 // fill-rule: enum, inherit
4679 if (eCSSUnit_Enumerated
== SVGData
.mFillRule
.GetUnit()) {
4680 svg
->mFillRule
= SVGData
.mFillRule
.GetIntValue();
4682 else if (eCSSUnit_Inherit
== SVGData
.mFillRule
.GetUnit()) {
4683 inherited
= PR_TRUE
;
4684 svg
->mFillRule
= parentSVG
->mFillRule
;
4686 else if (eCSSUnit_Initial
== SVGData
.mFillRule
.GetUnit()) {
4687 svg
->mFillRule
= NS_STYLE_FILL_RULE_NONZERO
;
4690 // marker-end: url, none, inherit
4691 if (eCSSUnit_URL
== SVGData
.mMarkerEnd
.GetUnit()) {
4692 svg
->mMarkerEnd
= SVGData
.mMarkerEnd
.GetURLValue();
4693 } else if (eCSSUnit_None
== SVGData
.mMarkerEnd
.GetUnit() ||
4694 eCSSUnit_Initial
== SVGData
.mMarkerEnd
.GetUnit()) {
4695 svg
->mMarkerEnd
= nsnull
;
4696 } else if (eCSSUnit_Inherit
== SVGData
.mMarkerEnd
.GetUnit()) {
4697 inherited
= PR_TRUE
;
4698 svg
->mMarkerEnd
= parentSVG
->mMarkerEnd
;
4701 // marker-mid: url, none, inherit
4702 if (eCSSUnit_URL
== SVGData
.mMarkerMid
.GetUnit()) {
4703 svg
->mMarkerMid
= SVGData
.mMarkerMid
.GetURLValue();
4704 } else if (eCSSUnit_None
== SVGData
.mMarkerMid
.GetUnit() ||
4705 eCSSUnit_Initial
== SVGData
.mMarkerMid
.GetUnit()) {
4706 svg
->mMarkerMid
= nsnull
;
4707 } else if (eCSSUnit_Inherit
== SVGData
.mMarkerMid
.GetUnit()) {
4708 inherited
= PR_TRUE
;
4709 svg
->mMarkerMid
= parentSVG
->mMarkerMid
;
4712 // marker-start: url, none, inherit
4713 if (eCSSUnit_URL
== SVGData
.mMarkerStart
.GetUnit()) {
4714 svg
->mMarkerStart
= SVGData
.mMarkerStart
.GetURLValue();
4715 } else if (eCSSUnit_None
== SVGData
.mMarkerStart
.GetUnit() ||
4716 eCSSUnit_Initial
== SVGData
.mMarkerStart
.GetUnit()) {
4717 svg
->mMarkerStart
= nsnull
;
4718 } else if (eCSSUnit_Inherit
== SVGData
.mMarkerStart
.GetUnit()) {
4719 inherited
= PR_TRUE
;
4720 svg
->mMarkerStart
= parentSVG
->mMarkerStart
;
4723 // pointer-events: enum, inherit
4724 if (eCSSUnit_Enumerated
== SVGData
.mPointerEvents
.GetUnit()) {
4725 svg
->mPointerEvents
= SVGData
.mPointerEvents
.GetIntValue();
4726 } else if (eCSSUnit_None
== SVGData
.mPointerEvents
.GetUnit()) {
4727 svg
->mPointerEvents
= NS_STYLE_POINTER_EVENTS_NONE
;
4728 } else if (eCSSUnit_Inherit
== SVGData
.mPointerEvents
.GetUnit()) {
4729 inherited
= PR_TRUE
;
4730 svg
->mPointerEvents
= parentSVG
->mPointerEvents
;
4731 } else if (eCSSUnit_Initial
== SVGData
.mPointerEvents
.GetUnit()) {
4732 svg
->mPointerEvents
= NS_STYLE_POINTER_EVENTS_VISIBLEPAINTED
;
4735 // shape-rendering: enum, auto, inherit
4736 if (eCSSUnit_Enumerated
== SVGData
.mShapeRendering
.GetUnit()) {
4737 svg
->mShapeRendering
= SVGData
.mShapeRendering
.GetIntValue();
4739 else if (eCSSUnit_Auto
== SVGData
.mShapeRendering
.GetUnit() ||
4740 eCSSUnit_Initial
== SVGData
.mShapeRendering
.GetUnit()) {
4741 svg
->mShapeRendering
= NS_STYLE_SHAPE_RENDERING_AUTO
;
4743 else if (eCSSUnit_Inherit
== SVGData
.mShapeRendering
.GetUnit()) {
4744 inherited
= PR_TRUE
;
4745 svg
->mShapeRendering
= parentSVG
->mShapeRendering
;
4749 SetSVGPaint(SVGData
.mStroke
, parentSVG
->mStroke
, mPresContext
, aContext
,
4750 svg
->mStroke
, eStyleSVGPaintType_None
, inherited
);
4752 // stroke-dasharray: <dasharray>, none, inherit
4753 nsCSSValueList
*list
= SVGData
.mStrokeDasharray
;
4755 if (eCSSUnit_Inherit
== list
->mValue
.GetUnit()) {
4756 // only do the copy if weren't already set up by the copy constructor
4757 // FIXME Bug 389408: This is broken when aStartStruct is non-null!
4758 if (!svg
->mStrokeDasharray
) {
4759 inherited
= PR_TRUE
;
4760 svg
->mStrokeDasharrayLength
= parentSVG
->mStrokeDasharrayLength
;
4761 if (svg
->mStrokeDasharrayLength
) {
4762 svg
->mStrokeDasharray
= new nsStyleCoord
[svg
->mStrokeDasharrayLength
];
4763 if (svg
->mStrokeDasharray
)
4764 memcpy(svg
->mStrokeDasharray
,
4765 parentSVG
->mStrokeDasharray
,
4766 svg
->mStrokeDasharrayLength
* sizeof(nsStyleCoord
));
4768 svg
->mStrokeDasharrayLength
= 0;
4772 delete [] svg
->mStrokeDasharray
;
4773 svg
->mStrokeDasharray
= nsnull
;
4774 svg
->mStrokeDasharrayLength
= 0;
4776 if (eCSSUnit_Initial
!= list
->mValue
.GetUnit() &&
4777 eCSSUnit_None
!= list
->mValue
.GetUnit()) {
4778 // count number of values
4779 nsCSSValueList
*value
= SVGData
.mStrokeDasharray
;
4780 while (nsnull
!= value
) {
4781 ++svg
->mStrokeDasharrayLength
;
4782 value
= value
->mNext
;
4785 NS_ASSERTION(svg
->mStrokeDasharrayLength
!= 0, "no dasharray items");
4787 svg
->mStrokeDasharray
= new nsStyleCoord
[svg
->mStrokeDasharrayLength
];
4789 if (svg
->mStrokeDasharray
) {
4790 value
= SVGData
.mStrokeDasharray
;
4792 while (nsnull
!= value
) {
4793 SetCoord(value
->mValue
,
4794 svg
->mStrokeDasharray
[i
++], nsnull
,
4795 SETCOORD_LP
| SETCOORD_FACTOR
,
4796 aContext
, mPresContext
, inherited
);
4797 value
= value
->mNext
;
4800 svg
->mStrokeDasharrayLength
= 0;
4805 // stroke-dashoffset: <dashoffset>, inherit
4806 SetCoord(SVGData
.mStrokeDashoffset
,
4807 svg
->mStrokeDashoffset
, parentSVG
->mStrokeDashoffset
,
4808 SETCOORD_LPH
| SETCOORD_FACTOR
| SETCOORD_INITIAL_ZERO
,
4809 aContext
, mPresContext
, inherited
);
4811 // stroke-linecap: enum, inherit
4812 if (eCSSUnit_Enumerated
== SVGData
.mStrokeLinecap
.GetUnit()) {
4813 svg
->mStrokeLinecap
= SVGData
.mStrokeLinecap
.GetIntValue();
4815 else if (eCSSUnit_Inherit
== SVGData
.mStrokeLinecap
.GetUnit()) {
4816 inherited
= PR_TRUE
;
4817 svg
->mStrokeLinecap
= parentSVG
->mStrokeLinecap
;
4819 else if (eCSSUnit_Initial
== SVGData
.mStrokeLinecap
.GetUnit()) {
4820 svg
->mStrokeLinecap
= NS_STYLE_STROKE_LINECAP_BUTT
;
4823 // stroke-linejoin: enum, inherit
4824 if (eCSSUnit_Enumerated
== SVGData
.mStrokeLinejoin
.GetUnit()) {
4825 svg
->mStrokeLinejoin
= SVGData
.mStrokeLinejoin
.GetIntValue();
4827 else if (eCSSUnit_Inherit
== SVGData
.mStrokeLinejoin
.GetUnit()) {
4828 inherited
= PR_TRUE
;
4829 svg
->mStrokeLinejoin
= parentSVG
->mStrokeLinejoin
;
4831 else if (eCSSUnit_Initial
== SVGData
.mStrokeLinejoin
.GetUnit()) {
4832 svg
->mStrokeLinejoin
= NS_STYLE_STROKE_LINEJOIN_MITER
;
4835 // stroke-miterlimit: <miterlimit>, inherit
4836 if (eCSSUnit_Number
== SVGData
.mStrokeMiterlimit
.GetUnit()) {
4837 svg
->mStrokeMiterlimit
= SVGData
.mStrokeMiterlimit
.GetFloatValue();
4839 else if (eCSSUnit_Inherit
== SVGData
.mStrokeMiterlimit
.GetUnit()) {
4840 svg
->mStrokeMiterlimit
= parentSVG
->mStrokeMiterlimit
;
4841 inherited
= PR_TRUE
;
4843 else if (eCSSUnit_Initial
== SVGData
.mStrokeMiterlimit
.GetUnit()) {
4844 svg
->mStrokeMiterlimit
= 4.0f
;
4848 SetSVGOpacity(SVGData
.mStrokeOpacity
, parentSVG
->mStrokeOpacity
,
4849 svg
->mStrokeOpacity
, inherited
);
4852 if (eCSSUnit_Initial
== SVGData
.mStrokeWidth
.GetUnit()) {
4853 svg
->mStrokeWidth
.SetCoordValue(nsPresContext::CSSPixelsToAppUnits(1));
4855 SetCoord(SVGData
.mStrokeWidth
,
4856 svg
->mStrokeWidth
, parentSVG
->mStrokeWidth
,
4857 SETCOORD_LPH
| SETCOORD_FACTOR
,
4858 aContext
, mPresContext
, inherited
);
4861 // text-anchor: enum, inherit
4862 if (eCSSUnit_Enumerated
== SVGData
.mTextAnchor
.GetUnit()) {
4863 svg
->mTextAnchor
= SVGData
.mTextAnchor
.GetIntValue();
4865 else if (eCSSUnit_Inherit
== SVGData
.mTextAnchor
.GetUnit()) {
4866 inherited
= PR_TRUE
;
4867 svg
->mTextAnchor
= parentSVG
->mTextAnchor
;
4869 else if (eCSSUnit_Initial
== SVGData
.mTextAnchor
.GetUnit()) {
4870 svg
->mTextAnchor
= NS_STYLE_TEXT_ANCHOR_START
;
4873 // text-rendering: enum, auto, inherit
4874 if (eCSSUnit_Enumerated
== SVGData
.mTextRendering
.GetUnit()) {
4875 svg
->mTextRendering
= SVGData
.mTextRendering
.GetIntValue();
4877 else if (eCSSUnit_Auto
== SVGData
.mTextRendering
.GetUnit() ||
4878 eCSSUnit_Initial
== SVGData
.mTextRendering
.GetUnit()) {
4879 svg
->mTextRendering
= NS_STYLE_TEXT_RENDERING_AUTO
;
4881 else if (eCSSUnit_Inherit
== SVGData
.mTextRendering
.GetUnit()) {
4882 inherited
= PR_TRUE
;
4883 svg
->mTextRendering
= parentSVG
->mTextRendering
;
4886 COMPUTE_END_INHERITED(SVG
, svg
)
4890 nsRuleNode::ComputeSVGResetData(void* aStartStruct
,
4891 const nsRuleDataStruct
& aData
,
4892 nsStyleContext
* aContext
,
4893 nsRuleNode
* aHighestNode
,
4894 const RuleDetail aRuleDetail
, PRBool aInherited
)
4896 COMPUTE_START_RESET(SVGReset
, (), svgReset
, parentSVGReset
, SVG
, SVGData
)
4899 if (eCSSUnit_Initial
== SVGData
.mStopColor
.GetUnit()) {
4900 svgReset
->mStopColor
= NS_RGB(0, 0, 0);
4902 SetColor(SVGData
.mStopColor
, parentSVGReset
->mStopColor
,
4903 mPresContext
, aContext
, svgReset
->mStopColor
, inherited
);
4907 if (eCSSUnit_Initial
== SVGData
.mFloodColor
.GetUnit()) {
4908 svgReset
->mFloodColor
= NS_RGB(0, 0, 0);
4910 SetColor(SVGData
.mFloodColor
, parentSVGReset
->mFloodColor
,
4911 mPresContext
, aContext
, svgReset
->mFloodColor
, inherited
);
4915 if (eCSSUnit_Initial
== SVGData
.mLightingColor
.GetUnit()) {
4916 svgReset
->mLightingColor
= NS_RGB(255, 255, 255);
4918 SetColor(SVGData
.mLightingColor
, parentSVGReset
->mLightingColor
,
4919 mPresContext
, aContext
, svgReset
->mLightingColor
, inherited
);
4922 // clip-path: url, none, inherit
4923 if (eCSSUnit_URL
== SVGData
.mClipPath
.GetUnit()) {
4924 svgReset
->mClipPath
= SVGData
.mClipPath
.GetURLValue();
4925 } else if (eCSSUnit_None
== SVGData
.mClipPath
.GetUnit() ||
4926 eCSSUnit_Initial
== SVGData
.mClipPath
.GetUnit()) {
4927 svgReset
->mClipPath
= nsnull
;
4928 } else if (eCSSUnit_Inherit
== SVGData
.mClipPath
.GetUnit()) {
4929 inherited
= PR_TRUE
;
4930 svgReset
->mClipPath
= parentSVGReset
->mClipPath
;
4934 SetSVGOpacity(SVGData
.mStopOpacity
, parentSVGReset
->mStopOpacity
,
4935 svgReset
->mStopOpacity
, inherited
);
4938 SetSVGOpacity(SVGData
.mFloodOpacity
, parentSVGReset
->mFloodOpacity
,
4939 svgReset
->mFloodOpacity
, inherited
);
4941 // dominant-baseline: enum, auto, inherit
4942 if (eCSSUnit_Enumerated
== SVGData
.mDominantBaseline
.GetUnit()) {
4943 svgReset
->mDominantBaseline
= SVGData
.mDominantBaseline
.GetIntValue();
4945 else if (eCSSUnit_Auto
== SVGData
.mDominantBaseline
.GetUnit() ||
4946 eCSSUnit_Initial
== SVGData
.mDominantBaseline
.GetUnit()) {
4947 svgReset
->mDominantBaseline
= NS_STYLE_DOMINANT_BASELINE_AUTO
;
4949 else if (eCSSUnit_Inherit
== SVGData
.mDominantBaseline
.GetUnit()) {
4950 inherited
= PR_TRUE
;
4951 svgReset
->mDominantBaseline
= parentSVGReset
->mDominantBaseline
;
4954 // filter: url, none, inherit
4955 if (eCSSUnit_URL
== SVGData
.mFilter
.GetUnit()) {
4956 svgReset
->mFilter
= SVGData
.mFilter
.GetURLValue();
4957 } else if (eCSSUnit_None
== SVGData
.mFilter
.GetUnit() ||
4958 eCSSUnit_Initial
== SVGData
.mFilter
.GetUnit()) {
4959 svgReset
->mFilter
= nsnull
;
4960 } else if (eCSSUnit_Inherit
== SVGData
.mFilter
.GetUnit()) {
4961 inherited
= PR_TRUE
;
4962 svgReset
->mFilter
= parentSVGReset
->mFilter
;
4965 // mask: url, none, inherit
4966 if (eCSSUnit_URL
== SVGData
.mMask
.GetUnit()) {
4967 svgReset
->mMask
= SVGData
.mMask
.GetURLValue();
4968 } else if (eCSSUnit_None
== SVGData
.mMask
.GetUnit() ||
4969 eCSSUnit_Initial
== SVGData
.mMask
.GetUnit()) {
4970 svgReset
->mMask
= nsnull
;
4971 } else if (eCSSUnit_Inherit
== SVGData
.mMask
.GetUnit()) {
4972 inherited
= PR_TRUE
;
4973 svgReset
->mMask
= parentSVGReset
->mMask
;
4976 COMPUTE_END_RESET(SVGReset
, svgReset
)
4981 nsRuleNode::GetParentData(const nsStyleStructID aSID
)
4983 NS_PRECONDITION(mDependentBits
& nsCachedStyleData::GetBitForSID(aSID
),
4984 "should be called when node depends on parent data");
4985 NS_ASSERTION(mStyleData
.GetStyleData(aSID
) == nsnull
,
4986 "both struct and dependent bits present");
4987 // Walk up the rule tree from this rule node (towards less specific
4989 PRUint32 bit
= nsCachedStyleData::GetBitForSID(aSID
);
4990 nsRuleNode
*ruleNode
= mParent
;
4991 while (ruleNode
->mDependentBits
& bit
) {
4992 NS_ASSERTION(ruleNode
->mStyleData
.GetStyleData(aSID
) == nsnull
,
4993 "both struct and dependent bits present");
4994 ruleNode
= ruleNode
->mParent
;
4997 return ruleNode
->mStyleData
.GetStyleData(aSID
);
5000 #define STYLE_STRUCT(name_, checkdata_cb_, ctor_args_) \
5001 inline const nsStyle##name_ * \
5002 nsRuleNode::GetParent##name_() \
5004 NS_PRECONDITION(mDependentBits & \
5005 nsCachedStyleData::GetBitForSID(eStyleStruct_##name_), \
5006 "should be called when node depends on parent data"); \
5007 NS_ASSERTION(mStyleData.GetStyle##name_() == nsnull, \
5008 "both struct and dependent bits present"); \
5009 /* Walk up the rule tree from this rule node (towards less specific */ \
5011 PRUint32 bit = nsCachedStyleData::GetBitForSID(eStyleStruct_##name_); \
5012 nsRuleNode *ruleNode = mParent; \
5013 while (ruleNode->mDependentBits & bit) { \
5014 NS_ASSERTION(ruleNode->mStyleData.GetStyle##name_() == nsnull, \
5015 "both struct and dependent bits present"); \
5016 ruleNode = ruleNode->mParent; \
5019 return ruleNode->mStyleData.GetStyle##name_(); \
5021 #include "nsStyleStructList.h"
5025 nsRuleNode::GetStyleData(nsStyleStructID aSID
,
5026 nsStyleContext
* aContext
,
5027 PRBool aComputeData
)
5030 if (mDependentBits
& nsCachedStyleData::GetBitForSID(aSID
)) {
5031 // We depend on an ancestor for this struct since the cached struct
5032 // it has is also appropriate for this rule node. Just go up the
5033 // rule tree and return the first cached struct we find.
5034 data
= GetParentData(aSID
);
5035 NS_ASSERTION(data
, "dependent bits set but no cached struct present");
5039 data
= mStyleData
.GetStyleData(aSID
);
5040 if (NS_LIKELY(data
!= nsnull
))
5041 return data
; // We have a fully specified struct. Just return it.
5043 if (NS_UNLIKELY(!aComputeData
))
5046 // Nothing is cached. We'll have to delve further and examine our rules.
5047 #define STYLE_STRUCT_TEST aSID
5048 #define STYLE_STRUCT(name, checkdata_cb, ctor_args) \
5049 data = Get##name##Data(aContext);
5050 #include "nsStyleStructList.h"
5052 #undef STYLE_STRUCT_TEST
5054 if (NS_LIKELY(data
!= nsnull
))
5057 NS_NOTREACHED("could not create style struct");
5058 // To ensure that |GetStyleData| never returns null (even when we're
5059 // out of memory), we'll get the style set and get a copy of the
5060 // default values for the given style struct from the set. Note that
5061 // this works fine even if |this| is a rule node that has been
5062 // destroyed (leftover from a previous rule tree) but is somehow still
5064 return mPresContext
->PresShell()->StyleSet()->
5065 DefaultStyleData()->GetStyleData(aSID
);
5068 // See comments above in GetStyleData for an explanation of what the
5070 #define STYLE_STRUCT(name_, checkdata_cb_, ctor_args_) \
5071 const nsStyle##name_* \
5072 nsRuleNode::GetStyle##name_(nsStyleContext* aContext, PRBool aComputeData) \
5074 const nsStyle##name_ *data; \
5075 if (mDependentBits & \
5076 nsCachedStyleData::GetBitForSID(eStyleStruct_##name_)) { \
5077 data = GetParent##name_(); \
5078 NS_ASSERTION(data, "dependent bits set but no cached struct present"); \
5082 data = mStyleData.GetStyle##name_(); \
5083 if (NS_LIKELY(data != nsnull)) \
5086 if (NS_UNLIKELY(!aComputeData)) \
5090 static_cast<const nsStyle##name_ *>(Get##name_##Data(aContext)); \
5092 if (NS_LIKELY(data != nsnull)) \
5095 NS_NOTREACHED("could not create style struct"); \
5097 static_cast<const nsStyle##name_ *>( \
5098 mPresContext->PresShell()->StyleSet()-> \
5099 DefaultStyleData()->GetStyleData(eStyleStruct_##name_)); \
5101 #include "nsStyleStructList.h"
5107 for (nsRuleNode
*node
= this;
5108 node
&& !(node
->mDependentBits
& NS_RULE_NODE_GC_MARK
);
5109 node
= node
->mParent
)
5110 node
->mDependentBits
|= NS_RULE_NODE_GC_MARK
;
5113 PR_STATIC_CALLBACK(PLDHashOperator
)
5114 SweepRuleNodeChildren(PLDHashTable
*table
, PLDHashEntryHdr
*hdr
,
5115 PRUint32 number
, void *arg
)
5117 ChildrenHashEntry
*entry
= static_cast<ChildrenHashEntry
*>(hdr
);
5118 if (entry
->mRuleNode
->Sweep())
5119 return PL_DHASH_REMOVE
; // implies NEXT, unless |ed with STOP
5120 return PL_DHASH_NEXT
;
5126 // If we're not marked, then we have to delete ourself.
5127 // However, we never allow the root node to GC itself, because nsStyleSet
5128 // wants to hold onto the root node and not worry about re-creating a
5129 // rule walker if the root node is deleted.
5130 if (!(mDependentBits
& NS_RULE_NODE_GC_MARK
) && !IsRoot()) {
5135 // Clear our mark, for the next time around.
5136 mDependentBits
&= ~NS_RULE_NODE_GC_MARK
;
5138 // Call sweep on the children, since some may not be marked, and
5139 // remove any deleted children from the child lists.
5140 if (HaveChildren()) {
5141 if (ChildrenAreHashed()) {
5142 PLDHashTable
*children
= ChildrenHash();
5143 PL_DHashTableEnumerate(children
, SweepRuleNodeChildren
, nsnull
);
5145 for (nsRuleList
**children
= ChildrenListPtr(); *children
; ) {
5146 if ((*children
)->mRuleNode
->Sweep()) {
5147 // This rule node was destroyed, so remove this entry, and
5148 // implicitly advance by making *children point to the next
5150 *children
= (*children
)->DestroySelf(mPresContext
);
5153 children
= &(*children
)->mNext
;
5162 nsRuleNode::HasAuthorSpecifiedRules(nsStyleContext
* aStyleContext
,
5163 PRUint32 ruleTypeMask
)
5165 nsRuleDataColor colorData
;
5166 nsRuleDataMargin marginData
;
5167 PRUint32 nValues
= 0;
5169 PRUint32 inheritBits
= 0;
5170 if (ruleTypeMask
& NS_AUTHOR_SPECIFIED_BACKGROUND
)
5171 inheritBits
|= NS_STYLE_INHERIT_BIT(Background
);
5173 if (ruleTypeMask
& NS_AUTHOR_SPECIFIED_BORDER
)
5174 inheritBits
|= NS_STYLE_INHERIT_BIT(Border
);
5176 if (ruleTypeMask
& NS_AUTHOR_SPECIFIED_PADDING
)
5177 inheritBits
|= NS_STYLE_INHERIT_BIT(Padding
);
5179 /* We're relying on the use of |aStyleContext| not mutating it! */
5180 nsRuleData
ruleData(inheritBits
,
5181 aStyleContext
->PresContext(), aStyleContext
);
5182 ruleData
.mColorData
= &colorData
;
5183 ruleData
.mMarginData
= &marginData
;
5185 nsCSSValue
* backgroundValues
[] = {
5186 &colorData
.mBackColor
,
5187 &colorData
.mBackImage
5190 nsCSSValue
* borderValues
[] = {
5191 &marginData
.mBorderColor
.mTop
,
5192 &marginData
.mBorderStyle
.mTop
,
5193 &marginData
.mBorderWidth
.mTop
,
5194 &marginData
.mBorderColor
.mRight
,
5195 &marginData
.mBorderStyle
.mRight
,
5196 &marginData
.mBorderWidth
.mRight
,
5197 &marginData
.mBorderColor
.mBottom
,
5198 &marginData
.mBorderStyle
.mBottom
,
5199 &marginData
.mBorderWidth
.mBottom
,
5200 &marginData
.mBorderColor
.mLeft
,
5201 &marginData
.mBorderStyle
.mLeft
,
5202 &marginData
.mBorderWidth
.mLeft
5203 // XXX add &marginData.mBorder{Start,End}{Width,Color,Style}
5206 nsCSSValue
* paddingValues
[] = {
5207 &marginData
.mPadding
.mTop
,
5208 &marginData
.mPadding
.mRight
,
5209 &marginData
.mPadding
.mBottom
,
5210 &marginData
.mPadding
.mLeft
,
5211 &marginData
.mPaddingStart
,
5212 &marginData
.mPaddingEnd
5215 nsCSSValue
* values
[NS_ARRAY_LENGTH(backgroundValues
) +
5216 NS_ARRAY_LENGTH(borderValues
) +
5217 NS_ARRAY_LENGTH(paddingValues
)];
5219 if (ruleTypeMask
& NS_AUTHOR_SPECIFIED_BACKGROUND
) {
5220 memcpy(&values
[nValues
], backgroundValues
, NS_ARRAY_LENGTH(backgroundValues
) * sizeof(nsCSSValue
*));
5221 nValues
+= NS_ARRAY_LENGTH(backgroundValues
);
5224 if (ruleTypeMask
& NS_AUTHOR_SPECIFIED_BORDER
) {
5225 memcpy(&values
[nValues
], borderValues
, NS_ARRAY_LENGTH(borderValues
) * sizeof(nsCSSValue
*));
5226 nValues
+= NS_ARRAY_LENGTH(borderValues
);
5229 if (ruleTypeMask
& NS_AUTHOR_SPECIFIED_PADDING
) {
5230 memcpy(&values
[nValues
], paddingValues
, NS_ARRAY_LENGTH(paddingValues
) * sizeof(nsCSSValue
*));
5231 nValues
+= NS_ARRAY_LENGTH(paddingValues
);
5234 // We need to be careful not to count styles covered up by
5235 // user-important or UA-important declarations.
5236 for (nsRuleNode
* ruleNode
= aStyleContext
->GetRuleNode(); ruleNode
;
5237 ruleNode
= ruleNode
->GetParent()) {
5238 nsIStyleRule
*rule
= ruleNode
->GetRule();
5240 ruleData
.mLevel
= ruleNode
->GetLevel();
5241 ruleData
.mIsImportantRule
= ruleNode
->IsImportantRule();
5242 rule
->MapRuleInfoInto(&ruleData
);
5243 if (ruleData
.mLevel
== nsStyleSet::eAgentSheet
||
5244 ruleData
.mLevel
== nsStyleSet::eUserSheet
) {
5245 // This is a rule whose effect we want to ignore, so if any of
5246 // the properties we care about were set, set them to the dummy
5247 // value that they'll never otherwise get.
5248 for (PRUint32 i
= 0; i
< nValues
; ++i
)
5249 if (values
[i
]->GetUnit() != eCSSUnit_Null
)
5250 values
[i
]->SetDummyValue();
5252 // If any of the values we care about was set by the above rule,
5253 // we have author style.
5254 for (PRUint32 i
= 0; i
< nValues
; ++i
)
5255 if (values
[i
]->GetUnit() != eCSSUnit_Null
&&
5256 values
[i
]->GetUnit() != eCSSUnit_Dummy
) // see above