1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is Mozilla Communicator client code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1998
20 * the Initial Developer. All Rights Reserved.
23 * Original Author: David W. Hyatt (hyatt@netscape.com)
24 * Daniel Glazman <glazman@netscape.com>
25 * Roger B. Sidje <rbs@maths.uq.edu.au>
26 * Mats Palmgren <mats.palmgren@bredband.net>
27 * L. David Baron <dbaron@dbaron.org>
28 * Christian Biesinger <cbiesinger@web.de>
29 * Michael Ventnor <m.ventnor@gmail.com>
31 * Alternatively, the contents of this file may be used under the terms of
32 * either of the GNU General Public License Version 2 or later (the "GPL"),
33 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
34 * in which case the provisions of the GPL or the LGPL are applicable instead
35 * of those above. If you wish to allow use of your version of this file only
36 * under the terms of either the GPL or the LGPL, and not to allow others to
37 * use your version of this file under the terms of the MPL, indicate your
38 * decision by deleting the provisions above and replace them with the notice
39 * and other provisions required by the GPL or the LGPL. If you do not delete
40 * the provisions above, a recipient may use your version of this file under
41 * the terms of any one of the MPL, the GPL or the LGPL.
43 * ***** END LICENSE BLOCK ***** */
46 * a node in the lexicographic tree of rules that match an element,
47 * responsible for converting the rules' information into computed style
50 #include "nsRuleNode.h"
52 #include "nsIServiceManager.h"
53 #include "nsIDeviceContext.h"
54 #include "nsILookAndFeel.h"
55 #include "nsIPresShell.h"
56 #include "nsIThebesFontMetrics.h"
58 #include "nsStyleUtil.h"
59 #include "nsCSSPseudoElements.h"
60 #include "nsThemeConstants.h"
63 #include "nsStyleContext.h"
64 #include "nsStyleSet.h"
66 #include "imgIRequest.h"
67 #include "nsRuleData.h"
68 #include "nsILanguageAtomService.h"
69 #include "nsIStyleRule.h"
70 #include "nsBidiUtils.h"
71 #include "nsStyleStructInlines.h"
72 #include "nsStyleTransformMatrix.h"
73 #include "nsCSSKeywords.h"
76 * For storage of an |nsRuleNode|'s children in a PLDHashTable.
79 struct ChildrenHashEntry
: public PLDHashEntryHdr
{
80 // key is |mRuleNode->GetKey()|
81 nsRuleNode
*mRuleNode
;
84 /* static */ PR_CALLBACK PLDHashNumber
85 nsRuleNode::ChildrenHashHashKey(PLDHashTable
*aTable
, const void *aKey
)
87 const nsRuleNode::Key
*key
=
88 static_cast<const nsRuleNode::Key
*>(aKey
);
89 // Disagreement on importance and level for the same rule is extremely
90 // rare, so hash just on the rule.
91 return PL_DHashVoidPtrKeyStub(aTable
, key
->mRule
);
94 /* static */ PR_CALLBACK PRBool
95 nsRuleNode::ChildrenHashMatchEntry(PLDHashTable
*aTable
,
96 const PLDHashEntryHdr
*aHdr
,
99 const ChildrenHashEntry
*entry
=
100 static_cast<const ChildrenHashEntry
*>(aHdr
);
101 const nsRuleNode::Key
*key
=
102 static_cast<const nsRuleNode::Key
*>(aKey
);
103 return entry
->mRuleNode
->GetKey() == *key
;
106 /* static */ PLDHashTableOps
107 nsRuleNode::ChildrenHashOps
= {
108 // It's probably better to allocate the table itself using malloc and
109 // free rather than the pres shell's arena because the table doesn't
110 // grow very often and the pres shell's arena doesn't recycle very
111 // large size allocations.
115 ChildrenHashMatchEntry
,
116 PL_DHashMoveEntryStub
,
117 PL_DHashClearEntryStub
,
118 PL_DHashFinalizeStub
,
123 // EnsureBlockDisplay:
124 // - if the display value (argument) is not a block-type
125 // then we set it to a valid block display value
126 // - For enforcing the floated/positioned element CSS2 rules
127 static void EnsureBlockDisplay(PRUint8
& display
)
129 // see if the display value is already a block
131 case NS_STYLE_DISPLAY_NONE
:
132 // never change display:none *ever*
133 case NS_STYLE_DISPLAY_TABLE
:
134 case NS_STYLE_DISPLAY_BLOCK
:
135 case NS_STYLE_DISPLAY_LIST_ITEM
:
136 // do not muck with these at all - already blocks
137 // This is equivalent to nsStyleDisplay::IsBlockOutside. (XXX Maybe we
138 // should just call that?)
141 case NS_STYLE_DISPLAY_INLINE_TABLE
:
142 // make inline tables into tables
143 display
= NS_STYLE_DISPLAY_TABLE
;
148 display
= NS_STYLE_DISPLAY_BLOCK
;
152 // XXX This should really be done in the CSS parser.
153 static nsString
& Unquote(nsString
& aString
)
155 PRUnichar start
= aString
.First();
156 PRUnichar end
= aString
.Last();
158 if ((start
== end
) &&
159 ((start
== PRUnichar('\"')) ||
160 (start
== PRUnichar('\'')))) {
161 PRInt32 length
= aString
.Length();
162 aString
.Truncate(length
- 1);
168 static nscoord
CalcLengthWith(const nsCSSValue
& aValue
,
170 const nsStyleFont
* aStyleFont
,
171 nsStyleContext
* aStyleContext
,
172 nsPresContext
* aPresContext
,
175 NS_ASSERTION(aValue
.IsLengthUnit(), "not a length unit");
176 NS_ASSERTION(aStyleFont
|| aStyleContext
, "Must have style data");
177 NS_ASSERTION(aPresContext
, "Must have prescontext");
179 if (aValue
.IsFixedLengthUnit()) {
180 return aPresContext
->TwipsToAppUnits(aValue
.GetLengthTwips());
182 nsCSSUnit unit
= aValue
.GetUnit();
183 if (unit
== eCSSUnit_Pixel
) {
184 return nsPresContext::CSSPixelsToAppUnits(aValue
.GetFloatValue());
186 // Common code for all units other than pixels:
187 aInherited
= PR_TRUE
;
189 aStyleFont
= aStyleContext
->GetStyleFont();
191 if (aFontSize
== -1) {
192 // XXX Should this be aStyleFont->mSize instead to avoid taking minfontsize
193 // prefs into account?
194 aFontSize
= aStyleFont
->mFont
.size
;
198 return NSToCoordRound(aValue
.GetFloatValue() * float(aFontSize
));
199 // XXX scale against font metrics height instead?
202 return NSToCoordRound((aValue
.GetFloatValue() * float(aFontSize
)) / 2.0f
);
204 case eCSSUnit_XHeight
: {
205 nsFont font
= aStyleFont
->mFont
;
206 font
.size
= aFontSize
;
207 nsCOMPtr
<nsIFontMetrics
> fm
= aPresContext
->GetMetricsFor(font
);
209 fm
->GetXHeight(xHeight
);
210 return NSToCoordRound(aValue
.GetFloatValue() * float(xHeight
));
212 case eCSSUnit_CapHeight
: {
213 NS_NOTYETIMPLEMENTED("cap height unit");
214 nscoord capHeight
= ((aFontSize
/ 3) * 2); // XXX HACK!
215 return NSToCoordRound(aValue
.GetFloatValue() * float(capHeight
));
217 case eCSSUnit_Char
: {
218 nsFont font
= aStyleFont
->mFont
;
219 font
.size
= aFontSize
;
220 nsCOMPtr
<nsIFontMetrics
> fm
= aPresContext
->GetMetricsFor(font
);
221 nsCOMPtr
<nsIThebesFontMetrics
> tfm(do_QueryInterface(fm
));
222 gfxFloat zeroWidth
= (tfm
->GetThebesFontGroup()->GetFontAt(0)
223 ->GetMetrics().zeroOrAveCharWidth
);
225 return NSToCoordRound(aValue
.GetFloatValue() *
226 NS_ceil(aPresContext
->AppUnitsPerDevPixel() *
230 NS_NOTREACHED("unexpected unit");
237 nsRuleNode::CalcLength(const nsCSSValue
& aValue
,
238 nsStyleContext
* aStyleContext
,
239 nsPresContext
* aPresContext
,
242 NS_ASSERTION(aStyleContext
, "Must have style data");
244 return CalcLengthWith(aValue
, -1, nsnull
, aStyleContext
, aPresContext
, aInherited
);
247 /* Inline helper function to redirect requests to CalcLength. */
248 static inline nscoord
CalcLength(const nsCSSValue
& aValue
,
249 nsStyleContext
* aStyleContext
,
250 nsPresContext
* aPresContext
,
253 return nsRuleNode::CalcLength(aValue
, aStyleContext
,
254 aPresContext
, aInherited
);
258 nsRuleNode::CalcLengthWithInitialFont(nsPresContext
* aPresContext
,
259 const nsCSSValue
& aValue
)
261 nsStyleFont
defaultFont(aPresContext
);
263 return CalcLengthWith(aValue
, -1, &defaultFont
, nsnull
, aPresContext
,
267 #define SETCOORD_NORMAL 0x01 // N
268 #define SETCOORD_AUTO 0x02 // A
269 #define SETCOORD_INHERIT 0x04 // H
270 #define SETCOORD_PERCENT 0x08 // P
271 #define SETCOORD_FACTOR 0x10 // F
272 #define SETCOORD_LENGTH 0x20 // L
273 #define SETCOORD_INTEGER 0x40 // I
274 #define SETCOORD_ENUMERATED 0x80 // E
275 #define SETCOORD_NONE 0x100 // O
276 #define SETCOORD_INITIAL_ZERO 0x200
277 #define SETCOORD_INITIAL_AUTO 0x400
278 #define SETCOORD_INITIAL_NONE 0x800
279 #define SETCOORD_INITIAL_NORMAL 0x1000
280 #define SETCOORD_INITIAL_HALF 0x2000
282 #define SETCOORD_LP (SETCOORD_LENGTH | SETCOORD_PERCENT)
283 #define SETCOORD_LH (SETCOORD_LENGTH | SETCOORD_INHERIT)
284 #define SETCOORD_AH (SETCOORD_AUTO | SETCOORD_INHERIT)
285 #define SETCOORD_LAH (SETCOORD_AUTO | SETCOORD_LENGTH | SETCOORD_INHERIT)
286 #define SETCOORD_LPH (SETCOORD_LP | SETCOORD_INHERIT)
287 #define SETCOORD_LPAH (SETCOORD_LP | SETCOORD_AH)
288 #define SETCOORD_LPEH (SETCOORD_LP | SETCOORD_ENUMERATED | SETCOORD_INHERIT)
289 #define SETCOORD_LPAEH (SETCOORD_LPAH | SETCOORD_ENUMERATED)
290 #define SETCOORD_LPOH (SETCOORD_LPH | SETCOORD_NONE)
291 #define SETCOORD_LPOEH (SETCOORD_LPOH | SETCOORD_ENUMERATED)
292 #define SETCOORD_LE (SETCOORD_LENGTH | SETCOORD_ENUMERATED)
293 #define SETCOORD_LEH (SETCOORD_LE | SETCOORD_INHERIT)
294 #define SETCOORD_IA (SETCOORD_INTEGER | SETCOORD_AUTO)
295 #define SETCOORD_LAE (SETCOORD_LENGTH | SETCOORD_AUTO | SETCOORD_ENUMERATED)
297 // changes aCoord iff it returns PR_TRUE
298 static PRBool
SetCoord(const nsCSSValue
& aValue
, nsStyleCoord
& aCoord
,
299 const nsStyleCoord
& aParentCoord
,
300 PRInt32 aMask
, nsStyleContext
* aStyleContext
,
301 nsPresContext
* aPresContext
, PRBool
& aInherited
)
303 PRBool result
= PR_TRUE
;
304 if (aValue
.GetUnit() == eCSSUnit_Null
) {
307 else if (((aMask
& SETCOORD_LENGTH
) != 0) &&
308 aValue
.IsLengthUnit()) {
309 aCoord
.SetCoordValue(CalcLength(aValue
, aStyleContext
, aPresContext
, aInherited
));
311 else if (((aMask
& SETCOORD_PERCENT
) != 0) &&
312 (aValue
.GetUnit() == eCSSUnit_Percent
)) {
313 aCoord
.SetPercentValue(aValue
.GetPercentValue());
315 else if (((aMask
& SETCOORD_INTEGER
) != 0) &&
316 (aValue
.GetUnit() == eCSSUnit_Integer
)) {
317 aCoord
.SetIntValue(aValue
.GetIntValue(), eStyleUnit_Integer
);
319 else if (((aMask
& SETCOORD_ENUMERATED
) != 0) &&
320 (aValue
.GetUnit() == eCSSUnit_Enumerated
)) {
321 aCoord
.SetIntValue(aValue
.GetIntValue(), eStyleUnit_Enumerated
);
323 else if (((aMask
& SETCOORD_AUTO
) != 0) &&
324 (aValue
.GetUnit() == eCSSUnit_Auto
)) {
325 aCoord
.SetAutoValue();
327 else if (((aMask
& SETCOORD_INHERIT
) != 0) &&
328 (aValue
.GetUnit() == eCSSUnit_Inherit
)) {
329 aCoord
= aParentCoord
; // just inherit value from parent
330 aInherited
= PR_TRUE
;
332 else if (((aMask
& SETCOORD_NORMAL
) != 0) &&
333 (aValue
.GetUnit() == eCSSUnit_Normal
)) {
334 aCoord
.SetNormalValue();
336 else if (((aMask
& SETCOORD_NONE
) != 0) &&
337 (aValue
.GetUnit() == eCSSUnit_None
)) {
338 aCoord
.SetNoneValue();
340 else if (((aMask
& SETCOORD_FACTOR
) != 0) &&
341 (aValue
.GetUnit() == eCSSUnit_Number
)) {
342 aCoord
.SetFactorValue(aValue
.GetFloatValue());
344 else if (((aMask
& SETCOORD_INITIAL_AUTO
) != 0) &&
345 (aValue
.GetUnit() == eCSSUnit_Initial
)) {
346 aCoord
.SetAutoValue();
348 else if (((aMask
& SETCOORD_INITIAL_ZERO
) != 0) &&
349 (aValue
.GetUnit() == eCSSUnit_Initial
)) {
350 aCoord
.SetCoordValue(0);
352 else if (((aMask
& SETCOORD_INITIAL_NONE
) != 0) &&
353 (aValue
.GetUnit() == eCSSUnit_Initial
)) {
354 aCoord
.SetNoneValue();
356 else if (((aMask
& SETCOORD_INITIAL_NORMAL
) != 0) &&
357 (aValue
.GetUnit() == eCSSUnit_Initial
)) {
358 aCoord
.SetNormalValue();
360 else if (((aMask
& SETCOORD_INITIAL_HALF
) != 0) &&
361 (aValue
.GetUnit() == eCSSUnit_Initial
)) {
362 aCoord
.SetPercentValue(0.5f
);
365 result
= PR_FALSE
; // didn't set anything
370 /* Given an enumerated value that represents a box position, converts it to
371 * a float representing the percentage of the box it corresponds to. For
372 * example, "center" becomes 0.5f.
374 * @param aEnumValue The enumerated value.
375 * @return The float percent it corresponds to.
377 static float GetFloatFromBoxPosition(PRInt32 aEnumValue
)
379 switch (aEnumValue
) {
380 case NS_STYLE_BG_POSITION_LEFT
:
381 case NS_STYLE_BG_POSITION_TOP
:
383 case NS_STYLE_BG_POSITION_RIGHT
:
384 case NS_STYLE_BG_POSITION_BOTTOM
:
387 NS_NOTREACHED("unexpected value");
389 case NS_STYLE_BG_POSITION_CENTER
:
394 static PRBool
SetColor(const nsCSSValue
& aValue
, const nscolor aParentColor
,
395 nsPresContext
* aPresContext
, nsStyleContext
*aContext
,
396 nscolor
& aResult
, PRBool
& aInherited
)
398 PRBool result
= PR_FALSE
;
399 nsCSSUnit unit
= aValue
.GetUnit();
401 if (eCSSUnit_Color
== unit
) {
402 aResult
= aValue
.GetColorValue();
405 else if (eCSSUnit_String
== unit
) {
407 aValue
.GetStringValue(value
);
409 if (NS_ColorNameToRGB(value
, &rgba
)) {
414 else if (eCSSUnit_EnumColor
== unit
) {
415 PRInt32 intValue
= aValue
.GetIntValue();
417 nsILookAndFeel
* look
= aPresContext
->LookAndFeel();
418 nsILookAndFeel::nsColorID colorID
= (nsILookAndFeel::nsColorID
) intValue
;
419 if (NS_SUCCEEDED(look
->GetColor(colorID
, aResult
))) {
425 case NS_COLOR_MOZ_HYPERLINKTEXT
:
426 aResult
= aPresContext
->DefaultLinkColor();
428 case NS_COLOR_MOZ_VISITEDHYPERLINKTEXT
:
429 aResult
= aPresContext
->DefaultVisitedLinkColor();
431 case NS_COLOR_MOZ_ACTIVEHYPERLINKTEXT
:
432 aResult
= aPresContext
->DefaultActiveLinkColor();
434 case NS_COLOR_CURRENTCOLOR
:
435 // The data computed from this can't be shared in the rule tree
436 // because they could be used on a node with a different color
437 aInherited
= PR_TRUE
;
438 aResult
= aContext
->GetStyleColor()->mColor
;
441 NS_NOTREACHED("Should never have an unknown negative colorID.");
447 else if (eCSSUnit_Inherit
== unit
) {
448 aResult
= aParentColor
;
450 aInherited
= PR_TRUE
;
455 // flags for SetDiscrete - align values with SETCOORD_* constants
458 #define SETDSC_NORMAL 0x01 // N
459 #define SETDSC_AUTO 0x02 // A
460 #define SETDSC_INTEGER 0x40 // I
461 #define SETDSC_ENUMERATED 0x80 // E
462 #define SETDSC_NONE 0x100 // O
463 #define SETDSC_SYSTEM_FONT 0x2000
465 // no caller cares whether aField was changed or not
466 template <typename FieldT
,
467 typename T1
, typename T2
, typename T3
, typename T4
, typename T5
>
469 SetDiscrete(const nsCSSValue
& aValue
, FieldT
& aField
,
470 PRBool
& aInherited
, PRUint32 aMask
,
478 switch (aValue
.GetUnit()) {
482 // every caller of SetDiscrete provides inherit and initial
483 // alternatives, so we don't require them to say so in the mask
484 case eCSSUnit_Inherit
:
485 aInherited
= PR_TRUE
;
486 aField
= aParentValue
;
489 case eCSSUnit_Initial
:
490 aField
= aInitialValue
;
493 // every caller provides one or other of these alternatives,
494 // but they have to say which
495 case eCSSUnit_Enumerated
:
496 if (aMask
& SETDSC_ENUMERATED
) {
497 aField
= aValue
.GetIntValue();
502 case eCSSUnit_Integer
:
503 if (aMask
& SETDSC_INTEGER
) {
504 aField
= aValue
.GetIntValue();
509 // remaining possibilities in descending order of frequency of use
511 if (aMask
& SETDSC_AUTO
) {
518 if (aMask
& SETDSC_NONE
) {
524 case eCSSUnit_Normal
:
525 if (aMask
& SETDSC_NORMAL
) {
526 aField
= aNormalValue
;
531 case eCSSUnit_System_Font
:
532 if (aMask
& SETDSC_SYSTEM_FONT
) {
533 aField
= aSystemFontValue
;
542 NS_NOTREACHED("SetDiscrete: inappropriate unit");
545 // flags for SetFactor
546 #define SETFCT_POSITIVE 0x01 // assert value is >= 0.0f
547 #define SETFCT_OPACITY 0x02 // clamp value to [0.0f .. 1.0f]
548 #define SETFCT_NONE 0x04 // allow _None (uses aInitialValue).
551 SetFactor(const nsCSSValue
& aValue
, float& aField
, PRBool
& aInherited
,
552 float aParentValue
, float aInitialValue
, PRUint32 aFlags
= 0)
554 switch (aValue
.GetUnit()) {
558 case eCSSUnit_Number
:
559 aField
= aValue
.GetFloatValue();
560 if (aFlags
& SETFCT_POSITIVE
) {
561 NS_ASSERTION(aField
>= 0.0f
, "negative value for positive-only property");
565 if (aFlags
& SETFCT_OPACITY
) {
573 case eCSSUnit_Inherit
:
574 aInherited
= PR_TRUE
;
575 aField
= aParentValue
;
578 case eCSSUnit_Initial
:
579 aField
= aInitialValue
;
583 if (aFlags
& SETFCT_NONE
) {
584 aField
= aInitialValue
;
593 NS_NOTREACHED("SetFactor: inappropriate unit");
596 // Overloaded new operator. Initializes the memory to 0 and relies on an arena
597 // (which comes from the presShell) to perform the allocation.
599 nsRuleNode::operator new(size_t sz
, nsPresContext
* aPresContext
) CPP_THROW_NEW
601 // Check the recycle list first.
602 return aPresContext
->AllocateFromShell(sz
);
605 /* static */ PR_CALLBACK PLDHashOperator
606 nsRuleNode::EnqueueRuleNodeChildren(PLDHashTable
*table
, PLDHashEntryHdr
*hdr
,
607 PRUint32 number
, void *arg
)
609 ChildrenHashEntry
*entry
= static_cast<ChildrenHashEntry
*>(hdr
);
610 nsRuleNode
***destroyQueueTail
= static_cast<nsRuleNode
***>(arg
);
611 **destroyQueueTail
= entry
->mRuleNode
;
612 *destroyQueueTail
= &entry
->mRuleNode
->mNextSibling
;
613 return PL_DHASH_NEXT
;
616 // Overridden to prevent the global delete from being called, since the memory
617 // came out of an nsIArena instead of the global delete operator's heap.
619 nsRuleNode::DestroyInternal(nsRuleNode
***aDestroyQueueTail
)
621 nsRuleNode
*destroyQueue
, **destroyQueueTail
;
622 if (aDestroyQueueTail
) {
623 destroyQueueTail
= *aDestroyQueueTail
;
625 destroyQueue
= nsnull
;
626 destroyQueueTail
= &destroyQueue
;
629 if (ChildrenAreHashed()) {
630 PLDHashTable
*children
= ChildrenHash();
631 PL_DHashTableEnumerate(children
, EnqueueRuleNodeChildren
,
633 *destroyQueueTail
= nsnull
; // ensure null-termination
634 PL_DHashTableDestroy(children
);
635 } else if (HaveChildren()) {
636 *destroyQueueTail
= ChildrenList();
638 destroyQueueTail
= &(*destroyQueueTail
)->mNextSibling
;
639 } while (*destroyQueueTail
);
641 mChildrenTaggedPtr
= nsnull
;
643 if (aDestroyQueueTail
) {
644 // Our caller destroys the queue.
645 *aDestroyQueueTail
= destroyQueueTail
;
647 // We have to do destroy the queue. When we destroy each node, it
648 // will add its children to the queue.
649 while (destroyQueue
) {
650 nsRuleNode
*cur
= destroyQueue
;
651 destroyQueue
= destroyQueue
->mNextSibling
;
653 NS_ASSERTION(destroyQueueTail
== &cur
->mNextSibling
, "mangled list");
654 destroyQueueTail
= &destroyQueue
;
656 cur
->DestroyInternal(&destroyQueueTail
);
660 // Destroy ourselves.
663 // Don't let the memory be freed, since it will be recycled
664 // instead. Don't call the global operator delete.
665 mPresContext
->FreeToShell(sizeof(nsRuleNode
), this);
668 nsRuleNode
* nsRuleNode::CreateRootNode(nsPresContext
* aPresContext
)
670 return new (aPresContext
)
671 nsRuleNode(aPresContext
, nsnull
, nsnull
, 0xff, PR_FALSE
);
674 nsILanguageAtomService
* nsRuleNode::gLangService
= nsnull
;
676 nsRuleNode::nsRuleNode(nsPresContext
* aContext
, nsRuleNode
* aParent
,
677 nsIStyleRule
* aRule
, PRUint8 aLevel
,
679 : mPresContext(aContext
),
682 mChildrenTaggedPtr(nsnull
),
683 mDependentBits((PRUint32(aLevel
) << NS_RULE_NODE_LEVEL_SHIFT
) |
684 (aIsImportant
? NS_RULE_NODE_IS_IMPORTANT
: 0)),
687 MOZ_COUNT_CTOR(nsRuleNode
);
690 NS_ASSERTION(IsRoot() || GetLevel() == aLevel
, "not enough bits");
691 NS_ASSERTION(IsRoot() || IsImportantRule() == aIsImportant
, "yikes");
694 nsRuleNode::~nsRuleNode()
696 MOZ_COUNT_DTOR(nsRuleNode
);
697 if (mStyleData
.mResetData
|| mStyleData
.mInheritedData
)
698 mStyleData
.Destroy(0, mPresContext
);
699 NS_IF_RELEASE(mRule
);
703 nsRuleNode::Transition(nsIStyleRule
* aRule
, PRUint8 aLevel
,
704 PRPackedBool aIsImportantRule
)
706 nsRuleNode
* next
= nsnull
;
707 nsRuleNode::Key
key(aRule
, aLevel
, aIsImportantRule
);
709 if (HaveChildren() && !ChildrenAreHashed()) {
711 nsRuleNode
* curr
= ChildrenList();
712 while (curr
&& curr
->GetKey() != key
) {
713 curr
= curr
->mNextSibling
;
718 else if (numKids
>= kMaxChildrenInList
)
719 ConvertChildrenToHash();
722 if (ChildrenAreHashed()) {
723 ChildrenHashEntry
*entry
= static_cast<ChildrenHashEntry
*>
724 (PL_DHashTableOperate(ChildrenHash(), &key
, PL_DHASH_ADD
));
728 if (entry
->mRuleNode
)
729 next
= entry
->mRuleNode
;
731 next
= entry
->mRuleNode
= new (mPresContext
)
732 nsRuleNode(mPresContext
, this, aRule
, aLevel
, aIsImportantRule
);
734 PL_DHashTableRawRemove(ChildrenHash(), entry
);
739 // Create the new entry in our list.
740 next
= new (mPresContext
)
741 nsRuleNode(mPresContext
, this, aRule
, aLevel
, aIsImportantRule
);
745 next
->mNextSibling
= ChildrenList();
746 SetChildrenList(next
);
753 nsRuleNode::ConvertChildrenToHash()
755 NS_ASSERTION(!ChildrenAreHashed() && HaveChildren(),
756 "must have a non-empty list of children");
757 PLDHashTable
*hash
= PL_NewDHashTable(&ChildrenHashOps
, nsnull
,
758 sizeof(ChildrenHashEntry
),
759 kMaxChildrenInList
* 4);
762 for (nsRuleNode
* curr
= ChildrenList(); curr
; curr
= curr
->mNextSibling
) {
763 // This will never fail because of the initial size we gave the table.
764 ChildrenHashEntry
*entry
= static_cast<ChildrenHashEntry
*>(
765 PL_DHashTableOperate(hash
, curr
->mRule
, PL_DHASH_ADD
));
766 NS_ASSERTION(!entry
->mRuleNode
, "duplicate entries in list");
767 entry
->mRuleNode
= curr
;
769 SetChildrenHash(hash
);
773 nsRuleNode::PropagateNoneBit(PRUint32 aBit
, nsRuleNode
* aHighestNode
)
775 nsRuleNode
* curr
= this;
777 NS_ASSERTION(!(curr
->mNoneBits
& aBit
), "propagating too far");
778 curr
->mNoneBits
|= aBit
;
779 if (curr
== aHighestNode
)
781 curr
= curr
->mParent
;
786 nsRuleNode::PropagateDependentBit(PRUint32 aBit
, nsRuleNode
* aHighestNode
)
788 for (nsRuleNode
* curr
= this; curr
!= aHighestNode
; curr
= curr
->mParent
) {
789 if (curr
->mDependentBits
& aBit
) {
791 while (curr
!= aHighestNode
) {
792 NS_ASSERTION(curr
->mDependentBits
& aBit
, "bit not set");
793 curr
= curr
->mParent
;
799 curr
->mDependentBits
|= aBit
;
804 * The following "Check" functions are used for determining what type of
805 * sharing can be used for the data on this rule node. MORE HERE...
808 /* the information for a property (or in some cases, a rect group of
811 struct PropertyCheckData
{
817 * a callback function that that can revise the result of
818 * CheckSpecifiedProperties before finishing; aResult is the current
819 * result, and it returns the revised one.
821 typedef nsRuleNode::RuleDetail
822 (* PR_CALLBACK CheckCallbackFn
)(const nsRuleDataStruct
& aData
,
823 nsRuleNode::RuleDetail aResult
);
825 /* the information for all the properties in a style struct */
826 struct StructCheckData
{
827 const PropertyCheckData
* props
;
829 CheckCallbackFn callback
;
834 * @param aValue the value being examined
835 * @param aSpecifiedCount to be incremented by one if the value is specified
836 * @param aInherited to be incremented by one if the value is set to inherit
839 ExamineCSSValue(const nsCSSValue
& aValue
,
840 PRUint32
& aSpecifiedCount
, PRUint32
& aInheritedCount
)
842 if (aValue
.GetUnit() != eCSSUnit_Null
) {
844 if (aValue
.GetUnit() == eCSSUnit_Inherit
) {
851 ExamineCSSValuePair(const nsCSSValuePair
* aValuePair
,
852 PRUint32
& aSpecifiedCount
, PRUint32
& aInheritedCount
)
854 NS_PRECONDITION(aValuePair
, "Must have a value pair");
856 ExamineCSSValue(aValuePair
->mXValue
, aSpecifiedCount
, aInheritedCount
);
857 ExamineCSSValue(aValuePair
->mYValue
, aSpecifiedCount
, aInheritedCount
);
861 ExamineCSSRect(const nsCSSRect
* aRect
,
862 PRUint32
& aSpecifiedCount
, PRUint32
& aInheritedCount
)
864 NS_PRECONDITION(aRect
, "Must have a rect");
866 NS_FOR_CSS_SIDES(side
) {
867 ExamineCSSValue(aRect
->*(nsCSSRect::sides
[side
]),
868 aSpecifiedCount
, aInheritedCount
);
872 PR_STATIC_CALLBACK(nsRuleNode::RuleDetail
)
873 CheckFontCallback(const nsRuleDataStruct
& aData
,
874 nsRuleNode::RuleDetail aResult
)
876 const nsRuleDataFont
& fontData
=
877 static_cast<const nsRuleDataFont
&>(aData
);
879 // em, ex, percent, 'larger', and 'smaller' values on font-size depend
880 // on the parent context's font-size
881 // Likewise, 'lighter' and 'bolder' values of 'font-weight' depend on
883 const nsCSSValue
& size
= fontData
.mSize
;
884 const nsCSSValue
& weight
= fontData
.mWeight
;
885 if ((size
.IsRelativeLengthUnit() && size
.GetUnit() != eCSSUnit_Pixel
) ||
886 size
.GetUnit() == eCSSUnit_Percent
||
887 (size
.GetUnit() == eCSSUnit_Enumerated
&&
888 (size
.GetIntValue() == NS_STYLE_FONT_SIZE_SMALLER
||
889 size
.GetIntValue() == NS_STYLE_FONT_SIZE_LARGER
)) ||
891 fontData
.mScriptLevel
.GetUnit() == eCSSUnit_Integer
||
893 (weight
.GetUnit() == eCSSUnit_Enumerated
&&
894 (weight
.GetIntValue() == NS_STYLE_FONT_WEIGHT_BOLDER
||
895 weight
.GetIntValue() == NS_STYLE_FONT_WEIGHT_LIGHTER
))) {
896 NS_ASSERTION(aResult
== nsRuleNode::eRulePartialReset
||
897 aResult
== nsRuleNode::eRuleFullReset
||
898 aResult
== nsRuleNode::eRulePartialMixed
||
899 aResult
== nsRuleNode::eRuleFullMixed
,
900 "we know we already have a reset-counted property");
901 // Promote reset to mixed since we have something that depends on
902 // the parent. But never promote to inherited since that could
903 // cause inheritance of the exact value.
904 if (aResult
== nsRuleNode::eRulePartialReset
)
905 aResult
= nsRuleNode::eRulePartialMixed
;
906 else if (aResult
== nsRuleNode::eRuleFullReset
)
907 aResult
= nsRuleNode::eRuleFullMixed
;
913 PR_STATIC_CALLBACK(nsRuleNode::RuleDetail
)
914 CheckColorCallback(const nsRuleDataStruct
& aData
,
915 nsRuleNode::RuleDetail aResult
)
917 const nsRuleDataColor
& colorData
=
918 static_cast<const nsRuleDataColor
&>(aData
);
920 // currentColor values for color require inheritance
921 if (colorData
.mColor
.GetUnit() == eCSSUnit_EnumColor
&&
922 colorData
.mColor
.GetIntValue() == NS_COLOR_CURRENTCOLOR
) {
923 NS_ASSERTION(aResult
== nsRuleNode::eRuleFullReset
,
924 "we should already be counted as full-reset");
925 aResult
= nsRuleNode::eRuleFullInherited
;
932 // for nsCSSPropList.h, so we get information on things in the style
933 // structs but not nsCSS*
934 #define CSS_PROP_INCLUDE_NOT_CSS
936 static const PropertyCheckData FontCheckProperties
[] = {
937 #define CSS_PROP_FONT(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
938 { offsetof(nsRuleData##datastruct_, member_), type_ },
939 #include "nsCSSPropList.h"
943 static const PropertyCheckData DisplayCheckProperties
[] = {
944 #define CSS_PROP_DISPLAY(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
945 { offsetof(nsRuleData##datastruct_, member_), type_ },
946 #include "nsCSSPropList.h"
947 #undef CSS_PROP_DISPLAY
950 static const PropertyCheckData VisibilityCheckProperties
[] = {
951 #define CSS_PROP_VISIBILITY(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
952 { offsetof(nsRuleData##datastruct_, member_), type_ },
953 #include "nsCSSPropList.h"
954 #undef CSS_PROP_VISIBILITY
957 static const PropertyCheckData MarginCheckProperties
[] = {
958 #define CSS_PROP_MARGIN(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
959 { offsetof(nsRuleData##datastruct_, member_), type_ },
960 #include "nsCSSPropList.h"
961 #undef CSS_PROP_MARGIN
964 static const PropertyCheckData BorderCheckProperties
[] = {
965 #define CSS_PROP_BORDER(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
966 { offsetof(nsRuleData##datastruct_, member_), type_ },
967 #include "nsCSSPropList.h"
968 #undef CSS_PROP_BORDER
971 static const PropertyCheckData PaddingCheckProperties
[] = {
972 #define CSS_PROP_PADDING(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
973 { offsetof(nsRuleData##datastruct_, member_), type_ },
974 #include "nsCSSPropList.h"
975 #undef CSS_PROP_PADDING
978 static const PropertyCheckData OutlineCheckProperties
[] = {
979 #define CSS_PROP_OUTLINE(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
980 { offsetof(nsRuleData##datastruct_, member_), type_ },
981 #include "nsCSSPropList.h"
982 #undef CSS_PROP_OUTLINE
985 static const PropertyCheckData ListCheckProperties
[] = {
986 #define CSS_PROP_LIST(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
987 { offsetof(nsRuleData##datastruct_, member_), type_ },
988 #include "nsCSSPropList.h"
992 static const PropertyCheckData ColorCheckProperties
[] = {
993 #define CSS_PROP_COLOR(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
994 { offsetof(nsRuleData##datastruct_, member_), type_ },
995 #include "nsCSSPropList.h"
996 #undef CSS_PROP_COLOR
999 static const PropertyCheckData BackgroundCheckProperties
[] = {
1000 #define CSS_PROP_BACKGROUND(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
1001 { offsetof(nsRuleData##datastruct_, member_), type_ },
1002 #include "nsCSSPropList.h"
1003 #undef CSS_PROP_BACKGROUND
1006 static const PropertyCheckData PositionCheckProperties
[] = {
1007 #define CSS_PROP_POSITION(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
1008 { offsetof(nsRuleData##datastruct_, member_), type_ },
1009 #include "nsCSSPropList.h"
1010 #undef CSS_PROP_POSITION
1013 static const PropertyCheckData TableCheckProperties
[] = {
1014 #define CSS_PROP_TABLE(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
1015 { offsetof(nsRuleData##datastruct_, member_), type_ },
1016 #include "nsCSSPropList.h"
1017 #undef CSS_PROP_TABLE
1020 static const PropertyCheckData TableBorderCheckProperties
[] = {
1021 #define CSS_PROP_TABLEBORDER(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
1022 { offsetof(nsRuleData##datastruct_, member_), type_ },
1023 #include "nsCSSPropList.h"
1024 #undef CSS_PROP_TABLEBORDER
1027 static const PropertyCheckData ContentCheckProperties
[] = {
1028 #define CSS_PROP_CONTENT(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
1029 { offsetof(nsRuleData##datastruct_, member_), type_ },
1030 #include "nsCSSPropList.h"
1031 #undef CSS_PROP_CONTENT
1034 static const PropertyCheckData QuotesCheckProperties
[] = {
1035 #define CSS_PROP_QUOTES(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
1036 { offsetof(nsRuleData##datastruct_, member_), type_ },
1037 #include "nsCSSPropList.h"
1038 #undef CSS_PROP_QUOTES
1041 static const PropertyCheckData TextCheckProperties
[] = {
1042 #define CSS_PROP_TEXT(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
1043 { offsetof(nsRuleData##datastruct_, member_), type_ },
1044 #include "nsCSSPropList.h"
1045 #undef CSS_PROP_TEXT
1048 static const PropertyCheckData TextResetCheckProperties
[] = {
1049 #define CSS_PROP_TEXTRESET(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
1050 { offsetof(nsRuleData##datastruct_, member_), type_ },
1051 #include "nsCSSPropList.h"
1052 #undef CSS_PROP_TEXTRESET
1055 static const PropertyCheckData UserInterfaceCheckProperties
[] = {
1056 #define CSS_PROP_USERINTERFACE(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
1057 { offsetof(nsRuleData##datastruct_, member_), type_ },
1058 #include "nsCSSPropList.h"
1059 #undef CSS_PROP_USERINTERFACE
1062 static const PropertyCheckData UIResetCheckProperties
[] = {
1063 #define CSS_PROP_UIRESET(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
1064 { offsetof(nsRuleData##datastruct_, member_), type_ },
1065 #include "nsCSSPropList.h"
1066 #undef CSS_PROP_UIRESET
1069 static const PropertyCheckData XULCheckProperties
[] = {
1070 #define CSS_PROP_XUL(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
1071 { offsetof(nsRuleData##datastruct_, member_), type_ },
1072 #include "nsCSSPropList.h"
1077 static const PropertyCheckData SVGCheckProperties
[] = {
1078 #define CSS_PROP_SVG(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
1079 { offsetof(nsRuleData##datastruct_, member_), type_ },
1080 #include "nsCSSPropList.h"
1084 static const PropertyCheckData SVGResetCheckProperties
[] = {
1085 #define CSS_PROP_SVGRESET(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
1086 { offsetof(nsRuleData##datastruct_, member_), type_ },
1087 #include "nsCSSPropList.h"
1088 #undef CSS_PROP_SVGRESET
1092 static const PropertyCheckData ColumnCheckProperties
[] = {
1093 #define CSS_PROP_COLUMN(name_, id_, method_, datastruct_, member_, type_, kwtable_) \
1094 { offsetof(nsRuleData##datastruct_, member_), type_ },
1095 #include "nsCSSPropList.h"
1096 #undef CSS_PROP_COLUMN
1099 #undef CSS_PROP_INCLUDE_NOT_CSS
1101 static const StructCheckData gCheckProperties
[] = {
1103 #define STYLE_STRUCT(name, checkdata_cb, ctor_args) \
1104 {name##CheckProperties, \
1105 sizeof(name##CheckProperties)/sizeof(PropertyCheckData), \
1107 #include "nsStyleStructList.h"
1115 // XXXldb Taking the address of a reference is evil.
1117 inline const nsCSSValue
&
1118 ValueAtOffset(const nsRuleDataStruct
& aRuleDataStruct
, size_t aOffset
)
1120 return * reinterpret_cast<const nsCSSValue
*>
1121 (reinterpret_cast<const char*>(&aRuleDataStruct
) + aOffset
);
1124 inline const nsCSSRect
*
1125 RectAtOffset(const nsRuleDataStruct
& aRuleDataStruct
, size_t aOffset
)
1127 return reinterpret_cast<const nsCSSRect
*>
1128 (reinterpret_cast<const char*>(&aRuleDataStruct
) + aOffset
);
1131 inline const nsCSSValuePair
*
1132 ValuePairAtOffset(const nsRuleDataStruct
& aRuleDataStruct
, size_t aOffset
)
1134 return reinterpret_cast<const nsCSSValuePair
*>
1135 (reinterpret_cast<const char*>(&aRuleDataStruct
) + aOffset
);
1138 inline const nsCSSValueList
*
1139 ValueListAtOffset(const nsRuleDataStruct
& aRuleDataStruct
, size_t aOffset
)
1141 return * reinterpret_cast<const nsCSSValueList
*const*>
1142 (reinterpret_cast<const char*>(&aRuleDataStruct
) + aOffset
);
1145 inline const nsCSSValueList
**
1146 ValueListArrayAtOffset(const nsRuleDataStruct
& aRuleDataStruct
, size_t aOffset
)
1148 return * reinterpret_cast<const nsCSSValueList
**const*>
1149 (reinterpret_cast<const char*>(&aRuleDataStruct
) + aOffset
);
1152 inline const nsCSSValuePairList
*
1153 ValuePairListAtOffset(const nsRuleDataStruct
& aRuleDataStruct
, size_t aOffset
)
1155 return * reinterpret_cast<const nsCSSValuePairList
*const*>
1156 (reinterpret_cast<const char*>(&aRuleDataStruct
) + aOffset
);
1159 #if defined(MOZ_MATHML) && defined(DEBUG)
1161 AreAllMathMLPropertiesUndefined(const nsCSSFont
& aRuleData
)
1163 return aRuleData
.mScriptLevel
.GetUnit() == eCSSUnit_Null
&&
1164 aRuleData
.mScriptSizeMultiplier
.GetUnit() == eCSSUnit_Null
&&
1165 aRuleData
.mScriptMinSize
.GetUnit() == eCSSUnit_Null
;
1169 inline nsRuleNode::RuleDetail
1170 nsRuleNode::CheckSpecifiedProperties(const nsStyleStructID aSID
,
1171 const nsRuleDataStruct
& aRuleDataStruct
)
1173 const StructCheckData
*structData
= gCheckProperties
+ aSID
;
1175 // Build a count of the:
1176 PRUint32 total
= 0, // total number of props in the struct
1177 specified
= 0, // number that were specified for this node
1178 inherited
= 0; // number that were 'inherit' (and not
1179 // eCSSUnit_Inherit) for this node
1181 for (const PropertyCheckData
*prop
= structData
->props
,
1182 *prop_end
= prop
+ structData
->nprops
;
1185 switch (prop
->type
) {
1187 case eCSSType_Value
:
1189 ExamineCSSValue(ValueAtOffset(aRuleDataStruct
, prop
->offset
),
1190 specified
, inherited
);
1195 ExamineCSSRect(RectAtOffset(aRuleDataStruct
, prop
->offset
),
1196 specified
, inherited
);
1199 case eCSSType_ValuePair
:
1201 ExamineCSSValuePair(ValuePairAtOffset(aRuleDataStruct
, prop
->offset
),
1202 specified
, inherited
);
1205 case eCSSType_ValueList
:
1208 const nsCSSValueList
* valueList
=
1209 ValueListAtOffset(aRuleDataStruct
, prop
->offset
);
1212 if (eCSSUnit_Inherit
== valueList
->mValue
.GetUnit()) {
1219 case eCSSType_ValuePairList
:
1222 const nsCSSValuePairList
* quotes
=
1223 ValuePairListAtOffset(aRuleDataStruct
, prop
->offset
);
1226 if (eCSSUnit_Inherit
== quotes
->mXValue
.GetUnit()) {
1234 NS_NOTREACHED("unknown type");
1240 printf("CheckSpecifiedProperties: SID=%d total=%d spec=%d inh=%d.\n",
1241 aSID
, total
, specified
, inherited
);
1245 NS_ASSERTION(aSID
!= eStyleStruct_Font
||
1246 mPresContext
->Document()->GetMathMLEnabled() ||
1247 AreAllMathMLPropertiesUndefined(static_cast<const nsCSSFont
&>(aRuleDataStruct
)),
1248 "MathML style property was defined even though MathML is disabled");
1252 * Return the most specific information we can: prefer None or Full
1253 * over Partial, and Reset or Inherited over Mixed, since we can
1254 * optimize based on the edge cases and not the in-between cases.
1256 nsRuleNode::RuleDetail result
;
1257 if (inherited
== total
)
1258 result
= eRuleFullInherited
;
1259 else if (specified
== total
1261 // MathML defines 3 properties in Font that will never be set when
1262 // MathML is not in use. Therefore if all but three
1263 // properties have been set, and MathML is not enabled, we can treat
1264 // this as fully specified. Code in nsMathMLElementFactory will
1265 // rebuild the rule tree and style data when MathML is first enabled
1266 // (see nsMathMLElement::BindToTree).
1267 || (aSID
== eStyleStruct_Font
&& specified
+ 3 == total
&&
1268 !mPresContext
->Document()->GetMathMLEnabled())
1272 result
= eRuleFullReset
;
1274 result
= eRuleFullMixed
;
1275 } else if (specified
== 0)
1277 else if (specified
== inherited
)
1278 result
= eRulePartialInherited
;
1279 else if (inherited
== 0)
1280 result
= eRulePartialReset
;
1282 result
= eRulePartialMixed
;
1284 if (structData
->callback
) {
1285 result
= (*structData
->callback
)(aRuleDataStruct
, result
);
1292 nsRuleNode::GetDisplayData(nsStyleContext
* aContext
)
1294 nsRuleDataDisplay displayData
; // Declare a struct with null CSS values.
1295 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Display
), mPresContext
, aContext
);
1296 ruleData
.mDisplayData
= &displayData
;
1298 return WalkRuleTree(eStyleStruct_Display
, aContext
, &ruleData
, &displayData
);
1302 nsRuleNode::GetVisibilityData(nsStyleContext
* aContext
)
1304 nsRuleDataDisplay displayData
; // Declare a struct with null CSS values.
1305 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Visibility
), mPresContext
, aContext
);
1306 ruleData
.mDisplayData
= &displayData
;
1308 return WalkRuleTree(eStyleStruct_Visibility
, aContext
, &ruleData
, &displayData
);
1312 nsRuleNode::GetTextData(nsStyleContext
* aContext
)
1314 nsRuleDataText textData
; // Declare a struct with null CSS values.
1315 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Text
), mPresContext
, aContext
);
1316 ruleData
.mTextData
= &textData
;
1318 const void* res
= WalkRuleTree(eStyleStruct_Text
, aContext
, &ruleData
, &textData
);
1319 textData
.mTextShadow
= nsnull
; // We are sharing with some style rule. It really owns the data.
1324 nsRuleNode::GetTextResetData(nsStyleContext
* aContext
)
1326 nsRuleDataText textData
; // Declare a struct with null CSS values.
1327 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(TextReset
), mPresContext
, aContext
);
1328 ruleData
.mTextData
= &textData
;
1330 return WalkRuleTree(eStyleStruct_TextReset
, aContext
, &ruleData
, &textData
);
1334 nsRuleNode::GetUserInterfaceData(nsStyleContext
* aContext
)
1336 nsRuleDataUserInterface uiData
; // Declare a struct with null CSS values.
1337 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(UserInterface
), mPresContext
, aContext
);
1338 ruleData
.mUserInterfaceData
= &uiData
;
1340 const void* res
= WalkRuleTree(eStyleStruct_UserInterface
, aContext
, &ruleData
, &uiData
);
1341 uiData
.mCursor
= nsnull
; // We are sharing with some style rule. It really owns the data.
1346 nsRuleNode::GetUIResetData(nsStyleContext
* aContext
)
1348 nsRuleDataUserInterface uiData
; // Declare a struct with null CSS values.
1349 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(UIReset
), mPresContext
, aContext
);
1350 ruleData
.mUserInterfaceData
= &uiData
;
1352 const void* res
= WalkRuleTree(eStyleStruct_UIReset
, aContext
, &ruleData
, &uiData
);
1357 nsRuleNode::GetFontData(nsStyleContext
* aContext
)
1359 nsRuleDataFont fontData
; // Declare a struct with null CSS values.
1360 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Font
), mPresContext
, aContext
);
1361 ruleData
.mFontData
= &fontData
;
1363 return WalkRuleTree(eStyleStruct_Font
, aContext
, &ruleData
, &fontData
);
1367 nsRuleNode::GetColorData(nsStyleContext
* aContext
)
1369 nsRuleDataColor colorData
; // Declare a struct with null CSS values.
1370 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Color
), mPresContext
, aContext
);
1371 ruleData
.mColorData
= &colorData
;
1373 return WalkRuleTree(eStyleStruct_Color
, aContext
, &ruleData
, &colorData
);
1377 nsRuleNode::GetBackgroundData(nsStyleContext
* aContext
)
1379 nsRuleDataColor colorData
; // Declare a struct with null CSS values.
1380 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Background
), mPresContext
, aContext
);
1381 ruleData
.mColorData
= &colorData
;
1383 // If any members need to be set to null here, they must also be set to
1384 // null in HasAuthorSpecifiedRules (look at mBoxShadow in GetBorderData
1385 // and HasAuthorSpecifiedRules).
1387 return WalkRuleTree(eStyleStruct_Background
, aContext
, &ruleData
, &colorData
);
1391 nsRuleNode::GetMarginData(nsStyleContext
* aContext
)
1393 nsRuleDataMargin marginData
; // Declare a struct with null CSS values.
1394 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Margin
), mPresContext
, aContext
);
1395 ruleData
.mMarginData
= &marginData
;
1397 return WalkRuleTree(eStyleStruct_Margin
, aContext
, &ruleData
, &marginData
);
1401 nsRuleNode::GetBorderData(nsStyleContext
* aContext
)
1403 nsRuleDataMargin marginData
; // Declare a struct with null CSS values.
1404 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Border
), mPresContext
, aContext
);
1405 ruleData
.mMarginData
= &marginData
;
1407 const void* res
= WalkRuleTree(eStyleStruct_Border
, aContext
, &ruleData
, &marginData
);
1408 // We are sharing with some style rule. It really owns the data.
1409 // This nulling must also happen in HasAuthorSpecifiedRules.
1410 marginData
.mBoxShadow
= nsnull
;
1415 nsRuleNode::GetPaddingData(nsStyleContext
* aContext
)
1417 nsRuleDataMargin marginData
; // Declare a struct with null CSS values.
1418 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Padding
), mPresContext
, aContext
);
1419 ruleData
.mMarginData
= &marginData
;
1421 // If any members need to be set to null here, they must also be set to
1422 // null in HasAuthorSpecifiedRules (look at mBoxShadow in GetBorderData
1423 // and HasAuthorSpecifiedRules).
1425 return WalkRuleTree(eStyleStruct_Padding
, aContext
, &ruleData
, &marginData
);
1429 nsRuleNode::GetOutlineData(nsStyleContext
* aContext
)
1431 nsRuleDataMargin marginData
; // Declare a struct with null CSS values.
1432 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Outline
), mPresContext
, aContext
);
1433 ruleData
.mMarginData
= &marginData
;
1435 return WalkRuleTree(eStyleStruct_Outline
, aContext
, &ruleData
, &marginData
);
1439 nsRuleNode::GetListData(nsStyleContext
* aContext
)
1441 nsRuleDataList listData
; // Declare a struct with null CSS values.
1442 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(List
), mPresContext
, aContext
);
1443 ruleData
.mListData
= &listData
;
1445 return WalkRuleTree(eStyleStruct_List
, aContext
, &ruleData
, &listData
);
1449 nsRuleNode::GetPositionData(nsStyleContext
* aContext
)
1451 nsRuleDataPosition posData
; // Declare a struct with null CSS values.
1452 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Position
), mPresContext
, aContext
);
1453 ruleData
.mPositionData
= &posData
;
1455 return WalkRuleTree(eStyleStruct_Position
, aContext
, &ruleData
, &posData
);
1459 nsRuleNode::GetTableData(nsStyleContext
* aContext
)
1461 nsRuleDataTable tableData
; // Declare a struct with null CSS values.
1462 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Table
), mPresContext
, aContext
);
1463 ruleData
.mTableData
= &tableData
;
1465 return WalkRuleTree(eStyleStruct_Table
, aContext
, &ruleData
, &tableData
);
1469 nsRuleNode::GetTableBorderData(nsStyleContext
* aContext
)
1471 nsRuleDataTable tableData
; // Declare a struct with null CSS values.
1472 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(TableBorder
), mPresContext
, aContext
);
1473 ruleData
.mTableData
= &tableData
;
1475 return WalkRuleTree(eStyleStruct_TableBorder
, aContext
, &ruleData
, &tableData
);
1479 nsRuleNode::GetContentData(nsStyleContext
* aContext
)
1481 nsRuleDataContent contentData
; // Declare a struct with null CSS values.
1482 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Content
), mPresContext
, aContext
);
1483 ruleData
.mContentData
= &contentData
;
1485 const void* res
= WalkRuleTree(eStyleStruct_Content
, aContext
, &ruleData
, &contentData
);
1486 contentData
.mCounterIncrement
= contentData
.mCounterReset
= nsnull
;
1487 contentData
.mContent
= nsnull
; // We are sharing with some style rule. It really owns the data.
1492 nsRuleNode::GetQuotesData(nsStyleContext
* aContext
)
1494 nsRuleDataContent contentData
; // Declare a struct with null CSS values.
1495 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Quotes
), mPresContext
, aContext
);
1496 ruleData
.mContentData
= &contentData
;
1498 const void* res
= WalkRuleTree(eStyleStruct_Quotes
, aContext
, &ruleData
, &contentData
);
1499 contentData
.mQuotes
= nsnull
; // We are sharing with some style rule. It really owns the data.
1504 nsRuleNode::GetXULData(nsStyleContext
* aContext
)
1506 nsRuleDataXUL xulData
; // Declare a struct with null CSS values.
1507 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(XUL
), mPresContext
, aContext
);
1508 ruleData
.mXULData
= &xulData
;
1510 return WalkRuleTree(eStyleStruct_XUL
, aContext
, &ruleData
, &xulData
);
1514 nsRuleNode::GetColumnData(nsStyleContext
* aContext
)
1516 nsRuleDataColumn columnData
; // Declare a struct with null CSS values.
1517 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Column
), mPresContext
, aContext
);
1518 ruleData
.mColumnData
= &columnData
;
1520 return WalkRuleTree(eStyleStruct_Column
, aContext
, &ruleData
, &columnData
);
1525 nsRuleNode::GetSVGData(nsStyleContext
* aContext
)
1527 nsRuleDataSVG svgData
; // Declare a struct with null CSS values.
1528 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(SVG
), mPresContext
, aContext
);
1529 ruleData
.mSVGData
= &svgData
;
1531 const void *res
= WalkRuleTree(eStyleStruct_SVG
, aContext
, &ruleData
, &svgData
);
1532 svgData
.mStrokeDasharray
= nsnull
; // We are sharing with some style rule. It really owns the data.
1537 nsRuleNode::GetSVGResetData(nsStyleContext
* aContext
)
1539 nsRuleDataSVG svgData
; // Declare a struct with null CSS values.
1540 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(SVGReset
), mPresContext
, aContext
);
1541 ruleData
.mSVGData
= &svgData
;
1543 return WalkRuleTree(eStyleStruct_SVGReset
, aContext
, &ruleData
, &svgData
);
1548 nsRuleNode::WalkRuleTree(const nsStyleStructID aSID
,
1549 nsStyleContext
* aContext
,
1550 nsRuleData
* aRuleData
,
1551 nsRuleDataStruct
* aSpecificData
)
1553 // We start at the most specific rule in the tree.
1554 void* startStruct
= nsnull
;
1556 nsRuleNode
* ruleNode
= this;
1557 nsRuleNode
* highestNode
= nsnull
; // The highest node in the rule tree
1558 // that has the same properties
1559 // specified for struct |aSID| as
1561 nsRuleNode
* rootNode
= this; // After the loop below, this will be the
1562 // highest node that we've walked without
1563 // finding cached data on the rule tree.
1564 // If we don't find any cached data, it
1565 // will be the root. (XXX misnamed)
1566 RuleDetail detail
= eRuleNone
;
1567 PRUint32 bit
= nsCachedStyleData::GetBitForSID(aSID
);
1570 // See if this rule node has cached the fact that the remaining
1571 // nodes along this path specify no data whatsoever.
1572 if (ruleNode
->mNoneBits
& bit
)
1575 // If the dependent bit is set on a rule node for this struct, that
1576 // means its rule won't have any information to add, so skip it.
1577 // XXXldb I don't understand why we need to check |detail| here, but
1579 if (detail
== eRuleNone
)
1580 while (ruleNode
->mDependentBits
& bit
) {
1581 NS_ASSERTION(ruleNode
->mStyleData
.GetStyleData(aSID
) == nsnull
,
1582 "dependent bit with cached data makes no sense");
1583 // Climb up to the next rule in the tree (a less specific rule).
1584 rootNode
= ruleNode
;
1585 ruleNode
= ruleNode
->mParent
;
1586 NS_ASSERTION(!(ruleNode
->mNoneBits
& bit
), "can't have both bits set");
1589 // Check for cached data after the inner loop above -- otherwise
1591 startStruct
= ruleNode
->mStyleData
.GetStyleData(aSID
);
1593 break; // We found a rule with fully specified data. We don't
1594 // need to go up the tree any further, since the remainder
1595 // of this branch has already been computed.
1597 // Ask the rule to fill in the properties that it specifies.
1598 nsIStyleRule
*rule
= ruleNode
->mRule
;
1600 aRuleData
->mLevel
= ruleNode
->GetLevel();
1601 aRuleData
->mIsImportantRule
= ruleNode
->IsImportantRule();
1602 rule
->MapRuleInfoInto(aRuleData
);
1605 // Now we check to see how many properties have been specified by
1606 // the rules we've examined so far.
1607 RuleDetail oldDetail
= detail
;
1608 detail
= CheckSpecifiedProperties(aSID
, *aSpecificData
);
1610 if (oldDetail
== eRuleNone
&& detail
!= eRuleNone
)
1611 highestNode
= ruleNode
;
1613 if (detail
== eRuleFullReset
||
1614 detail
== eRuleFullMixed
||
1615 detail
== eRuleFullInherited
)
1616 break; // We don't need to examine any more rules. All properties
1617 // have been fully specified.
1619 // Climb up to the next rule in the tree (a less specific rule).
1620 rootNode
= ruleNode
;
1621 ruleNode
= ruleNode
->mParent
;
1624 NS_ASSERTION(!startStruct
|| (detail
!= eRuleFullReset
&&
1625 detail
!= eRuleFullMixed
&&
1626 detail
!= eRuleFullInherited
),
1627 "can't have start struct and be fully specified");
1629 PRBool isReset
= nsCachedStyleData::IsReset(aSID
);
1631 highestNode
= rootNode
;
1633 if (!aRuleData
->mCanStoreInRuleTree
)
1634 detail
= eRulePartialMixed
; // Treat as though some data is specified to avoid
1635 // the optimizations and force data computation.
1637 if (detail
== eRuleNone
&& startStruct
&& !aRuleData
->mPostResolveCallback
) {
1638 // We specified absolutely no rule information, but a parent rule in the tree
1639 // specified all the rule information. We set a bit along the branch from our
1640 // node in the tree to the node that specified the data that tells nodes on that
1641 // branch that they never need to examine their rules for this particular struct type
1643 PropagateDependentBit(bit
, ruleNode
);
1646 // FIXME Do we need to check for mPostResolveCallback?
1647 if ((!startStruct
&& !isReset
&&
1648 (detail
== eRuleNone
|| detail
== eRulePartialInherited
)) ||
1649 detail
== eRuleFullInherited
) {
1650 // We specified no non-inherited information and neither did any of
1651 // our parent rules.
1653 // We set a bit along the branch from the highest node (ruleNode)
1654 // down to our node (this) indicating that no non-inherited data was
1655 // specified. This bit is guaranteed to be set already on the path
1656 // from the highest node to the root node in the case where
1657 // (detail == eRuleNone), which is the most common case here.
1658 // We must check |!isReset| because the Compute*Data functions for
1659 // reset structs wouldn't handle none bits correctly.
1660 if (highestNode
!= this && !isReset
)
1661 PropagateNoneBit(bit
, highestNode
);
1663 // All information must necessarily be inherited from our parent style context.
1664 // In the absence of any computed data in the rule tree and with
1665 // no rules specified that didn't have values of 'inherit', we should check our parent.
1666 nsStyleContext
* parentContext
= aContext
->GetParent();
1667 if (parentContext
) {
1668 // We have a parent, and so we should just inherit from the parent.
1669 // Set the inherit bits on our context. These bits tell the style context that
1670 // it never has to go back to the rule tree for data. Instead the style context tree
1671 // should be walked to find the data.
1672 const void* parentStruct
= parentContext
->GetStyleData(aSID
);
1673 aContext
->AddStyleBit(bit
); // makes const_cast OK.
1674 aContext
->SetStyle(aSID
, const_cast<void*>(parentStruct
));
1675 return parentStruct
;
1678 // We are the root. In the case of fonts, the default values just
1679 // come from the pres context.
1680 return SetDefaultOnRoot(aSID
, aContext
);
1683 // We need to compute the data from the information that the rules specified.
1685 #define STYLE_STRUCT_TEST aSID
1686 #define STYLE_STRUCT(name, checkdata_cb, ctor_args) \
1687 res = Compute##name##Data(startStruct, *aSpecificData, aContext, \
1688 highestNode, detail, !aRuleData->mCanStoreInRuleTree);
1689 #include "nsStyleStructList.h"
1691 #undef STYLE_STRUCT_TEST
1693 // If we have a post-resolve callback, handle that now.
1694 if (aRuleData
->mPostResolveCallback
&& (NS_LIKELY(res
!= nsnull
)))
1695 (*aRuleData
->mPostResolveCallback
)(const_cast<void*>(res
), aRuleData
);
1697 // Now return the result.
1702 nsRuleNode::SetDefaultOnRoot(const nsStyleStructID aSID
, nsStyleContext
* aContext
)
1705 case eStyleStruct_Font
:
1707 nsStyleFont
* fontData
= new (mPresContext
) nsStyleFont(mPresContext
);
1708 if (NS_LIKELY(fontData
!= nsnull
)) {
1709 nscoord minimumFontSize
=
1710 mPresContext
->GetCachedIntPref(kPresContext_MinimumFontSize
);
1712 if (minimumFontSize
> 0 && !mPresContext
->IsChrome()) {
1713 fontData
->mFont
.size
= PR_MAX(fontData
->mSize
, minimumFontSize
);
1716 fontData
->mFont
.size
= fontData
->mSize
;
1718 aContext
->SetStyle(eStyleStruct_Font
, fontData
);
1722 case eStyleStruct_Display
:
1724 nsStyleDisplay
* disp
= new (mPresContext
) nsStyleDisplay();
1725 if (NS_LIKELY(disp
!= nsnull
)) {
1726 aContext
->SetStyle(eStyleStruct_Display
, disp
);
1730 case eStyleStruct_Visibility
:
1732 nsStyleVisibility
* vis
= new (mPresContext
) nsStyleVisibility(mPresContext
);
1733 if (NS_LIKELY(vis
!= nsnull
)) {
1734 aContext
->SetStyle(eStyleStruct_Visibility
, vis
);
1738 case eStyleStruct_Text
:
1740 nsStyleText
* text
= new (mPresContext
) nsStyleText();
1741 if (NS_LIKELY(text
!= nsnull
)) {
1742 aContext
->SetStyle(eStyleStruct_Text
, text
);
1746 case eStyleStruct_TextReset
:
1748 nsStyleTextReset
* text
= new (mPresContext
) nsStyleTextReset();
1749 if (NS_LIKELY(text
!= nsnull
)) {
1750 aContext
->SetStyle(eStyleStruct_TextReset
, text
);
1754 case eStyleStruct_Color
:
1756 nsStyleColor
* color
= new (mPresContext
) nsStyleColor(mPresContext
);
1757 if (NS_LIKELY(color
!= nsnull
)) {
1758 aContext
->SetStyle(eStyleStruct_Color
, color
);
1762 case eStyleStruct_Background
:
1764 nsStyleBackground
* bg
= new (mPresContext
) nsStyleBackground();
1765 if (NS_LIKELY(bg
!= nsnull
)) {
1766 aContext
->SetStyle(eStyleStruct_Background
, bg
);
1770 case eStyleStruct_Margin
:
1772 nsStyleMargin
* margin
= new (mPresContext
) nsStyleMargin();
1773 if (NS_LIKELY(margin
!= nsnull
)) {
1774 aContext
->SetStyle(eStyleStruct_Margin
, margin
);
1778 case eStyleStruct_Border
:
1780 nsStyleBorder
* border
= new (mPresContext
) nsStyleBorder(mPresContext
);
1781 if (NS_LIKELY(border
!= nsnull
)) {
1782 aContext
->SetStyle(eStyleStruct_Border
, border
);
1786 case eStyleStruct_Padding
:
1788 nsStylePadding
* padding
= new (mPresContext
) nsStylePadding();
1789 if (NS_LIKELY(padding
!= nsnull
)) {
1790 aContext
->SetStyle(eStyleStruct_Padding
, padding
);
1794 case eStyleStruct_Outline
:
1796 nsStyleOutline
* outline
= new (mPresContext
) nsStyleOutline(mPresContext
);
1797 if (NS_LIKELY(outline
!= nsnull
)) {
1798 aContext
->SetStyle(eStyleStruct_Outline
, outline
);
1802 case eStyleStruct_List
:
1804 nsStyleList
* list
= new (mPresContext
) nsStyleList();
1805 if (NS_LIKELY(list
!= nsnull
)) {
1806 aContext
->SetStyle(eStyleStruct_List
, list
);
1810 case eStyleStruct_Position
:
1812 nsStylePosition
* pos
= new (mPresContext
) nsStylePosition();
1813 if (NS_LIKELY(pos
!= nsnull
)) {
1814 aContext
->SetStyle(eStyleStruct_Position
, pos
);
1818 case eStyleStruct_Table
:
1820 nsStyleTable
* table
= new (mPresContext
) nsStyleTable();
1821 if (NS_LIKELY(table
!= nsnull
)) {
1822 aContext
->SetStyle(eStyleStruct_Table
, table
);
1826 case eStyleStruct_TableBorder
:
1828 nsStyleTableBorder
* table
= new (mPresContext
) nsStyleTableBorder(mPresContext
);
1829 if (NS_LIKELY(table
!= nsnull
)) {
1830 aContext
->SetStyle(eStyleStruct_TableBorder
, table
);
1834 case eStyleStruct_Content
:
1836 nsStyleContent
* content
= new (mPresContext
) nsStyleContent();
1837 if (NS_LIKELY(content
!= nsnull
)) {
1838 aContext
->SetStyle(eStyleStruct_Content
, content
);
1842 case eStyleStruct_Quotes
:
1844 nsStyleQuotes
* quotes
= new (mPresContext
) nsStyleQuotes();
1845 if (NS_LIKELY(quotes
!= nsnull
)) {
1846 aContext
->SetStyle(eStyleStruct_Quotes
, quotes
);
1850 case eStyleStruct_UserInterface
:
1852 nsStyleUserInterface
* ui
= new (mPresContext
) nsStyleUserInterface();
1853 if (NS_LIKELY(ui
!= nsnull
)) {
1854 aContext
->SetStyle(eStyleStruct_UserInterface
, ui
);
1858 case eStyleStruct_UIReset
:
1860 nsStyleUIReset
* ui
= new (mPresContext
) nsStyleUIReset();
1861 if (NS_LIKELY(ui
!= nsnull
)) {
1862 aContext
->SetStyle(eStyleStruct_UIReset
, ui
);
1867 case eStyleStruct_XUL
:
1869 nsStyleXUL
* xul
= new (mPresContext
) nsStyleXUL();
1870 if (NS_LIKELY(xul
!= nsnull
)) {
1871 aContext
->SetStyle(eStyleStruct_XUL
, xul
);
1876 case eStyleStruct_Column
:
1878 nsStyleColumn
* column
= new (mPresContext
) nsStyleColumn(mPresContext
);
1879 if (NS_LIKELY(column
!= nsnull
)) {
1880 aContext
->SetStyle(eStyleStruct_Column
, column
);
1886 case eStyleStruct_SVG
:
1888 nsStyleSVG
* svg
= new (mPresContext
) nsStyleSVG();
1889 if (NS_LIKELY(svg
!= nsnull
)) {
1890 aContext
->SetStyle(eStyleStruct_SVG
, svg
);
1895 case eStyleStruct_SVGReset
:
1897 nsStyleSVGReset
* svgReset
= new (mPresContext
) nsStyleSVGReset();
1898 if (NS_LIKELY(svgReset
!= nsnull
)) {
1899 aContext
->SetStyle(eStyleStruct_SVGReset
, svgReset
);
1906 * unhandled case: nsStyleStructID_Length.
1907 * last item of nsStyleStructID, to know its length.
1915 * This function handles cascading of *-left or *-right box properties
1916 * against *-start (which is L for LTR and R for RTL) or *-end (which is
1917 * R for LTR and L for RTL).
1919 * Cascading these properties correctly is hard because we need to
1920 * cascade two properties as one, but which two properties depends on a
1921 * third property ('direction'). We solve this by treating each of
1922 * these properties (say, 'margin-start') as a shorthand that sets a
1923 * property containing the value of the property specified
1924 * ('margin-start-value') and sets a pair of properties
1925 * ('margin-left-ltr-source' and 'margin-right-rtl-source') saying which
1926 * of the properties we use. Thus, when we want to compute the value of
1927 * 'margin-left' when 'direction' is 'ltr', we look at the value of
1928 * 'margin-left-ltr-source', which tells us whether to use the highest
1929 * 'margin-left' in the cascade or the highest 'margin-start'.
1931 * Finally, since we can compute the normal (*-left and *-right)
1932 * properties in a loop, this function works by modifying the data we
1933 * will use in that loop (which the caller must copy from the const
1937 nsRuleNode::AdjustLogicalBoxProp(nsStyleContext
* aContext
,
1938 const nsCSSValue
& aLTRSource
,
1939 const nsCSSValue
& aRTLSource
,
1940 const nsCSSValue
& aLTRLogicalValue
,
1941 const nsCSSValue
& aRTLLogicalValue
,
1943 nsCSSRect
& aValueRect
,
1946 PRBool LTRlogical
= aLTRSource
.GetUnit() == eCSSUnit_Enumerated
&&
1947 aLTRSource
.GetIntValue() == NS_BOXPROP_SOURCE_LOGICAL
;
1948 PRBool RTLlogical
= aRTLSource
.GetUnit() == eCSSUnit_Enumerated
&&
1949 aRTLSource
.GetIntValue() == NS_BOXPROP_SOURCE_LOGICAL
;
1950 if (LTRlogical
|| RTLlogical
) {
1951 // We can't cache anything on the rule tree if we use any data from
1952 // the style context, since data cached in the rule tree could be
1953 // used with a style context with a different value.
1954 aInherited
= PR_TRUE
;
1955 PRUint8 dir
= aContext
->GetStyleVisibility()->mDirection
;
1957 if (dir
== NS_STYLE_DIRECTION_LTR
) {
1959 aValueRect
.*(nsCSSRect::sides
[aSide
]) = aLTRLogicalValue
;
1962 aValueRect
.*(nsCSSRect::sides
[aSide
]) = aRTLLogicalValue
;
1968 * Begin an nsRuleNode::Compute*Data function for an inherited struct.
1970 * @param type_ The nsStyle* type this function computes.
1971 * @param ctorargs_ The arguments used for the default nsStyle* constructor.
1972 * @param data_ Variable (declared here) holding the result of this
1974 * @param parentdata_ Variable (declared here) holding the parent style
1975 * context's data for this struct.
1976 * @param rdtype_ The nsCSS* struct type used to compute this struct's data.
1977 * @param rdata_ Variable (declared here) holding the nsCSS* used here.
1979 #define COMPUTE_START_INHERITED(type_, ctorargs_, data_, parentdata_, rdtype_, rdata_) \
1980 NS_ASSERTION(aRuleDetail != eRuleFullInherited, \
1981 "should not have bothered calling Compute*Data"); \
1983 nsStyleContext* parentContext = aContext->GetParent(); \
1985 const nsRuleData##rdtype_& rdata_ = \
1986 static_cast<const nsRuleData##rdtype_&>(aData); \
1987 nsStyle##type_* data_ = nsnull; \
1988 const nsStyle##type_* parentdata_ = nsnull; \
1989 PRBool inherited = aInherited; \
1991 /* If |inherited| might be false by the time we're done, we can't call */ \
1992 /* parentContext->GetStyle##type_() since it could recur into setting */ \
1993 /* the same struct on the same rule node, causing a leak. */ \
1994 if (parentContext && aRuleDetail != eRuleFullReset && \
1995 (!aStartStruct || (aRuleDetail != eRulePartialReset && \
1996 aRuleDetail != eRuleNone))) \
1997 parentdata_ = parentContext->GetStyle##type_(); \
1999 /* We only need to compute the delta between this computed data and */ \
2000 /* our computed data. */ \
2001 data_ = new (mPresContext) \
2002 nsStyle##type_(*static_cast<nsStyle##type_*>(aStartStruct)); \
2004 if (aRuleDetail != eRuleFullMixed && aRuleDetail != eRuleFullReset) { \
2005 /* No question. We will have to inherit. Go ahead and init */ \
2006 /* with inherited vals from parent. */ \
2007 inherited = PR_TRUE; \
2009 data_ = new (mPresContext) nsStyle##type_(*parentdata_); \
2011 data_ = new (mPresContext) nsStyle##type_ ctorargs_; \
2014 data_ = new (mPresContext) nsStyle##type_ ctorargs_; \
2017 if (NS_UNLIKELY(!data_)) \
2018 return nsnull; /* Out Of Memory */ \
2020 parentdata_ = data_;
2023 * Begin an nsRuleNode::Compute*Data function for a reset struct.
2025 * @param type_ The nsStyle* type this function computes.
2026 * @param ctorargs_ The arguments used for the default nsStyle* constructor.
2027 * @param data_ Variable (declared here) holding the result of this
2029 * @param parentdata_ Variable (declared here) holding the parent style
2030 * context's data for this struct.
2031 * @param rdtype_ The nsCSS* struct type used to compute this struct's data.
2032 * @param rdata_ Variable (declared here) holding the nsCSS* used here.
2034 #define COMPUTE_START_RESET(type_, ctorargs_, data_, parentdata_, rdtype_, rdata_) \
2035 NS_ASSERTION(aRuleDetail != eRuleFullInherited, \
2036 "should not have bothered calling Compute*Data"); \
2038 nsStyleContext* parentContext = aContext->GetParent(); \
2039 if (parentContext && \
2040 parentContext->GetPseudoType() == nsCSSPseudoElements::firstLine) { \
2041 /* Reset structs don't inherit from first-line */ \
2042 parentContext = parentContext->GetParent(); \
2045 const nsRuleData##rdtype_& rdata_ = \
2046 static_cast<const nsRuleData##rdtype_&>(aData); \
2047 nsStyle##type_* data_; \
2049 /* We only need to compute the delta between this computed data and */ \
2050 /* our computed data. */ \
2051 data_ = new (mPresContext) \
2052 nsStyle##type_(*static_cast<nsStyle##type_*>(aStartStruct)); \
2054 data_ = new (mPresContext) nsStyle##type_ ctorargs_; \
2056 if (NS_UNLIKELY(!data_)) \
2057 return nsnull; /* Out Of Memory */ \
2059 /* If |inherited| might be false by the time we're done, we can't call */ \
2060 /* parentContext->GetStyle##type_() since it could recur into setting */ \
2061 /* the same struct on the same rule node, causing a leak. */ \
2062 const nsStyle##type_* parentdata_ = data_; \
2063 if (parentContext && \
2064 aRuleDetail != eRuleFullReset && \
2065 aRuleDetail != eRulePartialReset && \
2066 aRuleDetail != eRuleNone) \
2067 parentdata_ = parentContext->GetStyle##type_(); \
2068 PRBool inherited = aInherited;
2071 * Begin an nsRuleNode::Compute*Data function for an inherited struct.
2073 * @param type_ The nsStyle* type this function computes.
2074 * @param data_ Variable holding the result of this function.
2076 #define COMPUTE_END_INHERITED(type_, data_) \
2078 /* We inherited, and therefore can't be cached in the rule node. We */ \
2079 /* have to be put right on the style context. */ \
2080 aContext->SetStyle(eStyleStruct_##type_, data_); \
2082 /* We were fully specified and can therefore be cached right on the */ \
2084 if (!aHighestNode->mStyleData.mInheritedData) { \
2085 aHighestNode->mStyleData.mInheritedData = \
2086 new (mPresContext) nsInheritedStyleData; \
2087 if (NS_UNLIKELY(!aHighestNode->mStyleData.mInheritedData)) { \
2088 data_->Destroy(mPresContext); \
2092 aHighestNode->mStyleData.mInheritedData->m##type_##Data = data_; \
2093 /* Propagate the bit down. */ \
2094 PropagateDependentBit(NS_STYLE_INHERIT_BIT(type_), aHighestNode); \
2100 * Begin an nsRuleNode::Compute*Data function for a reset struct.
2102 * @param type_ The nsStyle* type this function computes.
2103 * @param data_ Variable holding the result of this function.
2105 #define COMPUTE_END_RESET(type_, data_) \
2107 /* We inherited, and therefore can't be cached in the rule node. We */ \
2108 /* have to be put right on the style context. */ \
2109 aContext->SetStyle(eStyleStruct_##type_, data_); \
2111 /* We were fully specified and can therefore be cached right on the */ \
2113 if (!aHighestNode->mStyleData.mResetData) { \
2114 aHighestNode->mStyleData.mResetData = \
2115 new (mPresContext) nsResetStyleData; \
2116 if (NS_UNLIKELY(!aHighestNode->mStyleData.mResetData)) { \
2117 data_->Destroy(mPresContext); \
2121 aHighestNode->mStyleData.mResetData->m##type_##Data = data_; \
2122 /* Propagate the bit down. */ \
2123 PropagateDependentBit(NS_STYLE_INHERIT_BIT(type_), aHighestNode); \
2129 // This function figures out how much scaling should be suppressed to
2130 // satisfy scriptminsize. This is our attempt to implement
2131 // http://www.w3.org/TR/MathML2/chapter3.html#id.3.3.4.2.2
2132 // This is called after mScriptLevel, mScriptMinSize and mScriptSizeMultiplier
2133 // have been set in aFont.
2135 // Here are the invariants we enforce:
2136 // 1) A decrease in size must not reduce the size below minscriptsize.
2137 // 2) An increase in size must not increase the size above the size we would
2138 // have if minscriptsize had not been applied anywhere.
2139 // 3) The scriptlevel-induced size change must between 1.0 and the parent's
2140 // scriptsizemultiplier^(new script level - old script level), as close to the
2141 // latter as possible subject to constraints 1 and 2.
2143 ComputeScriptLevelSize(const nsStyleFont
* aFont
, const nsStyleFont
* aParentFont
,
2144 nsPresContext
* aPresContext
, nscoord
* aUnconstrainedSize
)
2146 PRInt32 scriptLevelChange
=
2147 aFont
->mScriptLevel
- aParentFont
->mScriptLevel
;
2148 if (scriptLevelChange
== 0) {
2149 *aUnconstrainedSize
= aParentFont
->mScriptUnconstrainedSize
;
2150 // Constraint #3 says that we cannot change size, and #1 and #2 are always
2151 // satisfied with no change. It's important this be fast because it covers
2152 // all non-MathML content.
2153 return aParentFont
->mSize
;
2156 // Compute actual value of minScriptSize
2157 nscoord minScriptSize
=
2158 nsStyleFont::ZoomText(aPresContext
, aParentFont
->mScriptMinSize
);
2160 double scriptLevelScale
=
2161 pow(aParentFont
->mScriptSizeMultiplier
, scriptLevelChange
);
2162 // Compute the size we would have had if minscriptsize had never been
2163 // applied, also prevent overflow (bug 413274)
2164 *aUnconstrainedSize
=
2165 NSToCoordRound(PR_MIN(aParentFont
->mScriptUnconstrainedSize
*scriptLevelScale
,
2167 // Compute the size we could get via scriptlevel change
2168 nscoord scriptLevelSize
=
2169 NSToCoordRound(PR_MIN(aParentFont
->mSize
*scriptLevelScale
,
2171 if (scriptLevelScale
<= 1.0) {
2172 if (aParentFont
->mSize
<= minScriptSize
) {
2173 // We can't decrease the font size at all, so just stick to no change
2174 // (authors are allowed to explicitly set the font size smaller than
2176 return aParentFont
->mSize
;
2178 // We can decrease, so apply constraint #1
2179 return PR_MAX(minScriptSize
, scriptLevelSize
);
2181 // scriptminsize can only make sizes larger than the unconstrained size
2182 NS_ASSERTION(*aUnconstrainedSize
<= scriptLevelSize
, "How can this ever happen?");
2183 // Apply constraint #2
2184 return PR_MIN(scriptLevelSize
, PR_MAX(*aUnconstrainedSize
, minScriptSize
));
2190 nsRuleNode::SetFontSize(nsPresContext
* aPresContext
,
2191 const nsRuleDataFont
& aFontData
,
2192 const nsStyleFont
* aFont
,
2193 const nsStyleFont
* aParentFont
,
2195 const nsFont
& aSystemFont
,
2196 nscoord aParentSize
,
2197 nscoord aScriptLevelAdjustedParentSize
,
2198 PRBool aUsedStartStruct
,
2201 PRBool zoom
= PR_FALSE
;
2202 PRInt32 baseSize
= (PRInt32
) aPresContext
->
2203 GetDefaultFont(aFont
->mFlags
& NS_STYLE_FONT_FACE_MASK
)->size
;
2204 if (eCSSUnit_Enumerated
== aFontData
.mSize
.GetUnit()) {
2205 PRInt32 value
= aFontData
.mSize
.GetIntValue();
2206 PRInt32 scaler
= aPresContext
->FontScaler();
2207 float scaleFactor
= nsStyleUtil::GetScalingFactor(scaler
);
2210 if ((NS_STYLE_FONT_SIZE_XXSMALL
<= value
) &&
2211 (value
<= NS_STYLE_FONT_SIZE_XXLARGE
)) {
2212 *aSize
= nsStyleUtil::CalcFontPointSize(value
, baseSize
,
2213 scaleFactor
, aPresContext
, eFontSize_CSS
);
2215 else if (NS_STYLE_FONT_SIZE_XXXLARGE
== value
) {
2216 // <font size="7"> is not specified in CSS, so we don't use eFontSize_CSS.
2217 *aSize
= nsStyleUtil::CalcFontPointSize(value
, baseSize
,
2218 scaleFactor
, aPresContext
);
2220 else if (NS_STYLE_FONT_SIZE_LARGER
== value
||
2221 NS_STYLE_FONT_SIZE_SMALLER
== value
) {
2222 aInherited
= PR_TRUE
;
2224 // Un-zoom so we use the tables correctly. We'll then rezoom due
2225 // to the |zoom = PR_TRUE| above.
2226 // Note that relative units here use the parent's size unadjusted
2227 // for scriptlevel changes. A scriptlevel change between us and the parent
2228 // is simply ignored.
2229 nscoord parentSize
=
2230 nsStyleFont::UnZoomText(aPresContext
, aParentSize
);
2232 if (NS_STYLE_FONT_SIZE_LARGER
== value
) {
2233 *aSize
= nsStyleUtil::FindNextLargerFontSize(parentSize
,
2234 baseSize
, scaleFactor
, aPresContext
, eFontSize_CSS
);
2235 NS_ASSERTION(*aSize
> parentSize
,
2236 "FindNextLargerFontSize failed");
2239 *aSize
= nsStyleUtil::FindNextSmallerFontSize(parentSize
,
2240 baseSize
, scaleFactor
, aPresContext
, eFontSize_CSS
);
2241 NS_ASSERTION(*aSize
< parentSize
||
2242 parentSize
<= nsPresContext::CSSPixelsToAppUnits(1),
2243 "FindNextSmallerFontSize failed");
2246 NS_NOTREACHED("unexpected value");
2249 else if (aFontData
.mSize
.IsLengthUnit()) {
2250 // Note that font-based length units use the parent's size unadjusted
2251 // for scriptlevel changes. A scriptlevel change between us and the parent
2252 // is simply ignored.
2253 *aSize
= CalcLengthWith(aFontData
.mSize
, aParentSize
, aParentFont
, nsnull
,
2254 aPresContext
, aInherited
);
2255 zoom
= aFontData
.mSize
.IsFixedLengthUnit() ||
2256 aFontData
.mSize
.GetUnit() == eCSSUnit_Pixel
;
2258 else if (eCSSUnit_Percent
== aFontData
.mSize
.GetUnit()) {
2259 aInherited
= PR_TRUE
;
2260 // Note that % units use the parent's size unadjusted for scriptlevel
2261 // changes. A scriptlevel change between us and the parent is simply
2263 *aSize
= NSToCoordRound(aParentSize
*
2264 aFontData
.mSize
.GetPercentValue());
2267 else if (eCSSUnit_System_Font
== aFontData
.mSize
.GetUnit()) {
2268 // this becomes our cascading size
2269 *aSize
= aSystemFont
.size
;
2272 else if (eCSSUnit_Inherit
== aFontData
.mSize
.GetUnit()) {
2273 aInherited
= PR_TRUE
;
2274 // We apply scriptlevel change for this case, because the default is
2275 // to inherit and we don't want explicit "inherit" to differ from the
2277 *aSize
= aScriptLevelAdjustedParentSize
;
2280 else if (eCSSUnit_Initial
== aFontData
.mSize
.GetUnit()) {
2281 // The initial value is 'medium', which has magical sizing based on
2282 // the generic font family, so do that here too.
2286 NS_ASSERTION(eCSSUnit_Null
== aFontData
.mSize
.GetUnit(),
2287 "What kind of font-size value is this?");
2289 // if aUsedStartStruct is true, then every single property in the
2290 // font struct is being set all at once. This means scriptlevel is not
2291 // going to have any influence on the font size; there is no need to
2292 // do anything here.
2293 if (!aUsedStartStruct
&& aParentSize
!= aScriptLevelAdjustedParentSize
) {
2294 // There was no rule affecting the size but the size has been
2295 // affected by the parent's size via scriptlevel change. So treat
2296 // this as inherited.
2297 aInherited
= PR_TRUE
;
2298 *aSize
= aScriptLevelAdjustedParentSize
;
2303 // We want to zoom the cascaded size so that em-based measurements,
2304 // line-heights, etc., work.
2306 *aSize
= nsStyleFont::ZoomText(aPresContext
, *aSize
);
2310 static PRInt8
ClampTo8Bit(PRInt32 aValue
) {
2315 return PRInt8(aValue
);
2319 nsRuleNode::SetFont(nsPresContext
* aPresContext
, nsStyleContext
* aContext
,
2320 nscoord aMinFontSize
,
2321 PRUint8 aGenericFontID
, const nsRuleDataFont
& aFontData
,
2322 const nsStyleFont
* aParentFont
,
2323 nsStyleFont
* aFont
, PRBool aUsedStartStruct
,
2326 const nsFont
* defaultVariableFont
=
2327 aPresContext
->GetDefaultFont(kPresContext_DefaultVariableFont_ID
);
2329 // -moz-system-font: enum (never inherit!)
2331 if (eCSSUnit_Enumerated
== aFontData
.mSystemFont
.GetUnit()) {
2332 nsSystemFontID sysID
;
2333 switch (aFontData
.mSystemFont
.GetIntValue()) {
2334 case NS_STYLE_FONT_CAPTION
: sysID
= eSystemFont_Caption
; break; // css2
2335 case NS_STYLE_FONT_ICON
: sysID
= eSystemFont_Icon
; break;
2336 case NS_STYLE_FONT_MENU
: sysID
= eSystemFont_Menu
; break;
2337 case NS_STYLE_FONT_MESSAGE_BOX
: sysID
= eSystemFont_MessageBox
; break;
2338 case NS_STYLE_FONT_SMALL_CAPTION
: sysID
= eSystemFont_SmallCaption
; break;
2339 case NS_STYLE_FONT_STATUS_BAR
: sysID
= eSystemFont_StatusBar
; break;
2340 case NS_STYLE_FONT_WINDOW
: sysID
= eSystemFont_Window
; break; // css3
2341 case NS_STYLE_FONT_DOCUMENT
: sysID
= eSystemFont_Document
; break;
2342 case NS_STYLE_FONT_WORKSPACE
: sysID
= eSystemFont_Workspace
; break;
2343 case NS_STYLE_FONT_DESKTOP
: sysID
= eSystemFont_Desktop
; break;
2344 case NS_STYLE_FONT_INFO
: sysID
= eSystemFont_Info
; break;
2345 case NS_STYLE_FONT_DIALOG
: sysID
= eSystemFont_Dialog
; break;
2346 case NS_STYLE_FONT_BUTTON
: sysID
= eSystemFont_Button
; break;
2347 case NS_STYLE_FONT_PULL_DOWN_MENU
:sysID
= eSystemFont_PullDownMenu
; break;
2348 case NS_STYLE_FONT_LIST
: sysID
= eSystemFont_List
; break;
2349 case NS_STYLE_FONT_FIELD
: sysID
= eSystemFont_Field
; break;
2352 // GetSystemFont sets the font face but not necessarily the size
2353 // XXX Or at least it used to -- no longer true for thebes. Maybe
2354 // it should be again, though.
2355 systemFont
.size
= defaultVariableFont
->size
;
2357 if (NS_FAILED(aPresContext
->DeviceContext()->GetSystemFont(sysID
,
2359 systemFont
.name
= defaultVariableFont
->name
;
2362 // XXXldb All of this platform-specific stuff should be in the
2363 // nsIDeviceContext implementations, not here.
2367 // As far as I can tell the system default fonts and sizes for
2368 // on MS-Windows for Buttons, Listboxes/Comboxes and Text Fields are
2369 // all pre-determined and cannot be changed by either the control panel
2370 // or programmtically.
2373 // Fields (text fields)
2374 // Button and Selects (listboxes/comboboxes)
2375 // We use whatever font is defined by the system. Which it appears
2376 // (and the assumption is) it is always a proportional font. Then we
2377 // always use 2 points smaller than what the browser has defined as
2378 // the default proportional font.
2379 case eSystemFont_Field
:
2380 case eSystemFont_Button
:
2381 case eSystemFont_List
:
2382 // Assumption: system defined font is proportional
2384 PR_MAX(defaultVariableFont
->size
- aPresContext
->PointsToAppUnits(2), 0);
2389 // In case somebody explicitly used -moz-use-system-font.
2390 systemFont
= *defaultVariableFont
;
2394 // font-family: string list, enum, inherit
2395 NS_ASSERTION(eCSSUnit_Enumerated
!= aFontData
.mFamily
.GetUnit(),
2396 "system fonts should not be in mFamily anymore");
2397 if (eCSSUnit_String
== aFontData
.mFamily
.GetUnit()) {
2398 // set the correct font if we are using DocumentFonts OR we are overriding for XUL
2400 if (aGenericFontID
== kGenericFont_NONE
) {
2401 // only bother appending fallback fonts if this isn't a fallback generic font itself
2402 if (!aFont
->mFont
.name
.IsEmpty())
2403 aFont
->mFont
.name
.Append((PRUnichar
)',');
2404 // defaultVariableFont.name should always be "serif" or "sans-serif".
2405 aFont
->mFont
.name
.Append(defaultVariableFont
->name
);
2407 aFont
->mFont
.familyNameQuirks
=
2408 (aPresContext
->CompatibilityMode() == eCompatibility_NavQuirks
&&
2409 aFontData
.mFamilyFromHTML
);
2410 aFont
->mFont
.systemFont
= PR_FALSE
;
2411 aFont
->mFlags
&= ~NS_STYLE_FONT_FACE_MASK
;
2412 // Technically this is redundant with the code below, but it's good
2413 // to have since we'll still want it once we get rid of
2414 // SetGenericFont (bug 380915).
2415 aFont
->mFlags
|= aGenericFontID
;
2417 else if (eCSSUnit_System_Font
== aFontData
.mFamily
.GetUnit()) {
2418 aFont
->mFont
.name
= systemFont
.name
;
2419 aFont
->mFont
.familyNameQuirks
= PR_FALSE
;
2420 aFont
->mFont
.systemFont
= PR_TRUE
;
2421 aFont
->mFlags
&= ~NS_STYLE_FONT_FACE_MASK
;
2423 else if (eCSSUnit_Inherit
== aFontData
.mFamily
.GetUnit()) {
2424 aInherited
= PR_TRUE
;
2425 aFont
->mFont
.name
= aParentFont
->mFont
.name
;
2426 aFont
->mFont
.familyNameQuirks
= aParentFont
->mFont
.familyNameQuirks
;
2427 aFont
->mFont
.systemFont
= aParentFont
->mFont
.systemFont
;
2428 aFont
->mFlags
&= ~NS_STYLE_FONT_FACE_MASK
;
2429 aFont
->mFlags
|= (aParentFont
->mFlags
& NS_STYLE_FONT_FACE_MASK
);
2431 else if (eCSSUnit_Initial
== aFontData
.mFamily
.GetUnit()) {
2432 aFont
->mFont
.name
= defaultVariableFont
->name
;
2433 aFont
->mFont
.familyNameQuirks
= PR_FALSE
;
2434 aFont
->mFont
.systemFont
= defaultVariableFont
->systemFont
;
2435 aFont
->mFlags
&= ~NS_STYLE_FONT_FACE_MASK
;
2438 // When we're in the loop in SetGenericFont, we must ensure that we
2439 // always keep aFont->mFlags set to the correct generic. But we have
2440 // to be careful not to touch it when we're called directly from
2441 // ComputeFontData, because we could have a start struct.
2442 if (aGenericFontID
!= kGenericFont_NONE
) {
2443 aFont
->mFlags
&= ~NS_STYLE_FONT_FACE_MASK
;
2444 aFont
->mFlags
|= aGenericFontID
;
2447 // font-style: enum, normal, inherit, initial, -moz-system-font
2448 SetDiscrete(aFontData
.mStyle
, aFont
->mFont
.style
, aInherited
,
2449 SETDSC_ENUMERATED
| SETDSC_NORMAL
| SETDSC_SYSTEM_FONT
,
2450 aParentFont
->mFont
.style
,
2451 defaultVariableFont
->style
,
2453 NS_STYLE_FONT_STYLE_NORMAL
,
2456 // font-variant: enum, normal, inherit, initial, -moz-system-font
2457 SetDiscrete(aFontData
.mVariant
, aFont
->mFont
.variant
, aInherited
,
2458 SETDSC_ENUMERATED
| SETDSC_NORMAL
| SETDSC_SYSTEM_FONT
,
2459 aParentFont
->mFont
.variant
,
2460 defaultVariableFont
->variant
,
2462 NS_STYLE_FONT_VARIANT_NORMAL
,
2463 systemFont
.variant
);
2465 // font-weight: int, enum, normal, inherit, initial, -moz-system-font
2466 // special handling for enum
2467 if (eCSSUnit_Enumerated
== aFontData
.mWeight
.GetUnit()) {
2468 PRInt32 value
= aFontData
.mWeight
.GetIntValue();
2470 case NS_STYLE_FONT_WEIGHT_NORMAL
:
2471 case NS_STYLE_FONT_WEIGHT_BOLD
:
2472 aFont
->mFont
.weight
= value
;
2474 case NS_STYLE_FONT_WEIGHT_BOLDER
:
2475 case NS_STYLE_FONT_WEIGHT_LIGHTER
:
2476 aInherited
= PR_TRUE
;
2477 aFont
->mFont
.weight
= nsStyleUtil::ConstrainFontWeight(aParentFont
->mFont
.weight
+ value
);
2481 SetDiscrete(aFontData
.mWeight
, aFont
->mFont
.weight
, aInherited
,
2482 SETDSC_INTEGER
| SETDSC_NORMAL
| SETDSC_SYSTEM_FONT
,
2483 aParentFont
->mFont
.weight
,
2484 defaultVariableFont
->weight
,
2486 NS_STYLE_FONT_WEIGHT_NORMAL
,
2490 // Compute scriptlevel, scriptminsize and scriptsizemultiplier now so
2491 // they're available for font-size computation.
2493 // -moz-script-min-size: length
2494 if (aFontData
.mScriptMinSize
.IsLengthUnit()) {
2495 // scriptminsize in font units (em, ex) has to be interpreted relative
2496 // to the parent font, or the size definitions are circular and we
2498 aFont
->mScriptMinSize
=
2499 CalcLengthWith(aFontData
.mScriptMinSize
, aParentFont
->mSize
, aParentFont
, nsnull
,
2500 aPresContext
, aInherited
);
2503 // -moz-script-size-multiplier: factor, inherit, initial
2504 SetFactor(aFontData
.mScriptSizeMultiplier
, aFont
->mScriptSizeMultiplier
,
2505 aInherited
, aParentFont
->mScriptSizeMultiplier
,
2506 NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER
,
2509 // -moz-script-level: integer, number, inherit
2510 if (eCSSUnit_Integer
== aFontData
.mScriptLevel
.GetUnit()) {
2512 aFont
->mScriptLevel
= ClampTo8Bit(aParentFont
->mScriptLevel
+ aFontData
.mScriptLevel
.GetIntValue());
2514 else if (eCSSUnit_Number
== aFontData
.mScriptLevel
.GetUnit()) {
2516 aFont
->mScriptLevel
= ClampTo8Bit(PRInt32(aFontData
.mScriptLevel
.GetFloatValue()));
2518 else if (eCSSUnit_Inherit
== aFontData
.mScriptSizeMultiplier
.GetUnit()) {
2519 aInherited
= PR_TRUE
;
2520 aFont
->mScriptLevel
= aParentFont
->mScriptLevel
;
2522 else if (eCSSUnit_Initial
== aFontData
.mScriptSizeMultiplier
.GetUnit()) {
2523 aFont
->mScriptLevel
= 0;
2527 // font-size: enum, length, percent, inherit
2528 nscoord scriptLevelAdjustedParentSize
= aParentFont
->mSize
;
2530 nscoord scriptLevelAdjustedUnconstrainedParentSize
;
2531 scriptLevelAdjustedParentSize
=
2532 ComputeScriptLevelSize(aFont
, aParentFont
, aPresContext
,
2533 &scriptLevelAdjustedUnconstrainedParentSize
);
2534 NS_ASSERTION(!aUsedStartStruct
|| aFont
->mScriptUnconstrainedSize
== aFont
->mSize
,
2535 "If we have a start struct, we should have reset everything coming in here");
2537 SetFontSize(aPresContext
, aFontData
, aFont
, aParentFont
, &aFont
->mSize
,
2538 systemFont
, aParentFont
->mSize
, scriptLevelAdjustedParentSize
,
2539 aUsedStartStruct
, aInherited
);
2541 if (aParentFont
->mSize
== aParentFont
->mScriptUnconstrainedSize
&&
2542 scriptLevelAdjustedParentSize
== scriptLevelAdjustedUnconstrainedParentSize
) {
2543 // Fast path: we have not been affected by scriptminsize so we don't
2544 // need to call SetFontSize again to compute the
2545 // scriptminsize-unconstrained size. This is OK even if we have a
2546 // start struct, because if we have a start struct then 'font-size'
2547 // was specified and so scriptminsize has no effect.
2548 aFont
->mScriptUnconstrainedSize
= aFont
->mSize
;
2550 SetFontSize(aPresContext
, aFontData
, aFont
, aParentFont
,
2551 &aFont
->mScriptUnconstrainedSize
, systemFont
,
2552 aParentFont
->mScriptUnconstrainedSize
,
2553 scriptLevelAdjustedUnconstrainedParentSize
,
2554 aUsedStartStruct
, aInherited
);
2556 NS_ASSERTION(aFont
->mScriptUnconstrainedSize
<= aFont
->mSize
,
2557 "scriptminsize should never be making things bigger");
2560 // enforce the user' specified minimum font-size on the value that we expose
2561 // (but don't change font-size:0)
2562 if (0 < aFont
->mSize
&& aFont
->mSize
< aMinFontSize
)
2563 aFont
->mFont
.size
= aMinFontSize
;
2565 aFont
->mFont
.size
= aFont
->mSize
;
2567 // font-size-adjust: number, none, inherit, initial, -moz-system-font
2568 if (eCSSUnit_System_Font
== aFontData
.mSizeAdjust
.GetUnit()) {
2569 aFont
->mFont
.sizeAdjust
= systemFont
.sizeAdjust
;
2571 SetFactor(aFontData
.mSizeAdjust
, aFont
->mFont
.sizeAdjust
, aInherited
,
2572 aParentFont
->mFont
.sizeAdjust
, 0.0f
, SETFCT_NONE
);
2576 // - backtrack to an ancestor with the same generic font name (possibly
2577 // up to the root where default values come from the presentation context)
2578 // - re-apply cascading rules from there without caching intermediate values
2580 nsRuleNode::SetGenericFont(nsPresContext
* aPresContext
,
2581 nsStyleContext
* aContext
,
2582 PRUint8 aGenericFontID
, nscoord aMinFontSize
,
2585 // walk up the contexts until a context with the desired generic font
2586 nsAutoVoidArray contextPath
;
2587 contextPath
.AppendElement(aContext
);
2588 nsStyleContext
* higherContext
= aContext
->GetParent();
2589 while (higherContext
) {
2590 if (higherContext
->GetStyleFont()->mFlags
& aGenericFontID
) {
2591 // done walking up the higher contexts
2594 contextPath
.AppendElement(higherContext
);
2595 higherContext
= higherContext
->GetParent();
2598 // re-apply the cascading rules, starting from the higher context
2600 // If we stopped earlier because we reached the root of the style tree,
2601 // we will start with the default generic font from the presentation
2602 // context. Otherwise we start with the higher context.
2603 const nsFont
* defaultFont
= aPresContext
->GetDefaultFont(aGenericFontID
);
2604 nsStyleFont
parentFont(*defaultFont
, aPresContext
);
2605 if (higherContext
) {
2606 const nsStyleFont
* tmpFont
= higherContext
->GetStyleFont();
2607 parentFont
= *tmpFont
;
2609 *aFont
= parentFont
;
2612 PRUint32 fontBit
= nsCachedStyleData::GetBitForSID(eStyleStruct_Font
);
2614 for (PRInt32 i
= contextPath
.Count() - 1; i
>= 0; --i
) {
2615 nsStyleContext
* context
= (nsStyleContext
*)contextPath
[i
];
2616 nsRuleDataFont fontData
; // Declare a struct with null CSS values.
2617 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Font
), aPresContext
, context
);
2618 ruleData
.mFontData
= &fontData
;
2620 // Trimmed down version of ::WalkRuleTree() to re-apply the style rules
2621 // Note that we *do* need to do this for our own data, since what is
2622 // in |fontData| in ComputeFontData is only for the rules below
2624 for (nsRuleNode
* ruleNode
= context
->GetRuleNode(); ruleNode
;
2625 ruleNode
= ruleNode
->GetParent()) {
2626 if (ruleNode
->mNoneBits
& fontBit
)
2627 // no more font rules on this branch, get out
2630 nsIStyleRule
*rule
= ruleNode
->GetRule();
2632 ruleData
.mLevel
= ruleNode
->GetLevel();
2633 ruleData
.mIsImportantRule
= ruleNode
->IsImportantRule();
2634 rule
->MapRuleInfoInto(&ruleData
);
2638 // Compute the delta from the information that the rules specified
2640 // Avoid unnecessary operations in SetFont(). But we care if it's
2641 // the final value that we're computing.
2643 fontData
.mFamily
.Reset();
2645 nsRuleNode::SetFont(aPresContext
, context
, aMinFontSize
,
2646 aGenericFontID
, fontData
, &parentFont
, aFont
,
2649 // XXX Not sure if we need to do this here
2650 // If we have a post-resolve callback, handle that now.
2651 if (ruleData
.mPostResolveCallback
)
2652 (ruleData
.mPostResolveCallback
)(aFont
, &ruleData
);
2654 parentFont
= *aFont
;
2658 static PRBool
ExtractGeneric(const nsString
& aFamily
, PRBool aGeneric
,
2661 nsAutoString
*data
= static_cast<nsAutoString
*>(aData
);
2665 return PR_FALSE
; // stop enumeration
2671 nsRuleNode::ComputeFontData(void* aStartStruct
,
2672 const nsRuleDataStruct
& aData
,
2673 nsStyleContext
* aContext
,
2674 nsRuleNode
* aHighestNode
,
2675 const RuleDetail aRuleDetail
, PRBool aInherited
)
2677 COMPUTE_START_INHERITED(Font
, (mPresContext
), font
, parentFont
,
2680 // NOTE: The |aRuleDetail| passed in is a little bit conservative due
2681 // to the -moz-system-font property. We really don't need to consider
2682 // it here in determining whether to cache in the rule tree. However,
2683 // we do need to consider it in WalkRuleTree when deciding whether to
2684 // walk further up the tree. So this means that when the font struct
2685 // is fully specified using *longhand* properties (excluding
2686 // -moz-system-font), we won't cache in the rule tree even though we
2687 // could. However, it's pretty unlikely authors will do that
2688 // (although there is a pretty good chance they'll fully specify it
2689 // using the 'font' shorthand).
2691 // See if there is a minimum font-size constraint to honor
2692 nscoord minimumFontSize
=
2693 mPresContext
->GetCachedIntPref(kPresContext_MinimumFontSize
);
2695 if (minimumFontSize
< 0)
2696 minimumFontSize
= 0;
2698 PRBool useDocumentFonts
=
2699 mPresContext
->GetCachedBoolPref(kPresContext_UseDocumentFonts
);
2701 // See if we are in the chrome
2702 // We only need to know this to determine if we have to use the
2703 // document fonts (overriding the useDocumentFonts flag), or to
2704 // determine if we have to override the minimum font-size constraint.
2705 if ((!useDocumentFonts
|| minimumFontSize
> 0) && mPresContext
->IsChrome()) {
2706 // if we are not using document fonts, but this is a XUL document,
2707 // then we use the document fonts anyway
2708 useDocumentFonts
= PR_TRUE
;
2709 minimumFontSize
= 0;
2712 // Figure out if we are a generic font
2713 PRUint8 generic
= kGenericFont_NONE
;
2714 // XXXldb What if we would have had a string if we hadn't been doing
2715 // the optimization with a non-null aStartStruct?
2716 if (eCSSUnit_String
== fontData
.mFamily
.GetUnit()) {
2717 fontData
.mFamily
.GetStringValue(font
->mFont
.name
);
2718 // XXXldb Do we want to extract the generic for this if it's not only a
2720 nsFont::GetGenericID(font
->mFont
.name
, &generic
);
2722 // If we aren't allowed to use document fonts, then we are only entitled
2723 // to use the user's default variable-width font and fixed-width font
2724 if (!useDocumentFonts
) {
2725 // Extract the generic from the specified font family...
2726 nsAutoString genericName
;
2727 if (!font
->mFont
.EnumerateFamilies(ExtractGeneric
, &genericName
)) {
2728 // The specified font had a generic family.
2729 font
->mFont
.name
= genericName
;
2730 nsFont::GetGenericID(genericName
, &generic
);
2732 // ... and only use it if it's -moz-fixed or monospace
2733 if (generic
!= kGenericFont_moz_fixed
&&
2734 generic
!= kGenericFont_monospace
) {
2735 font
->mFont
.name
.Truncate();
2736 generic
= kGenericFont_NONE
;
2739 // The specified font did not have a generic family.
2740 font
->mFont
.name
.Truncate();
2741 generic
= kGenericFont_NONE
;
2746 // Now compute our font struct
2747 if (generic
== kGenericFont_NONE
) {
2748 // continue the normal processing
2749 nsRuleNode::SetFont(mPresContext
, aContext
, minimumFontSize
, generic
,
2750 fontData
, parentFont
, font
,
2751 aStartStruct
!= nsnull
, inherited
);
2754 // re-calculate the font as a generic font
2755 inherited
= PR_TRUE
;
2756 nsRuleNode::SetGenericFont(mPresContext
, aContext
, generic
,
2757 minimumFontSize
, font
);
2760 COMPUTE_END_INHERITED(Font
, font
)
2763 already_AddRefed
<nsCSSShadowArray
>
2764 nsRuleNode::GetShadowData(nsCSSValueList
* aList
,
2765 nsStyleContext
* aContext
,
2769 PRUint32 arrayLength
= 0;
2770 for (nsCSSValueList
*list2
= aList
; list2
; list2
= list2
->mNext
)
2773 NS_ASSERTION(arrayLength
> 0, "Non-null text-shadow list, yet we counted 0 items.");
2774 nsCSSShadowArray
* shadowList
= new(arrayLength
) nsCSSShadowArray(arrayLength
);
2779 nsStyleCoord tempCoord
;
2781 for (nsCSSShadowItem
* item
= shadowList
->ShadowAt(0);
2783 aList
= aList
->mNext
, ++item
) {
2784 nsCSSValue::Array
*arr
= aList
->mValue
.GetArrayValue();
2785 // OK to pass bad aParentCoord since we're not passing SETCOORD_INHERIT
2786 unitOK
= SetCoord(arr
->Item(0), tempCoord
, nsStyleCoord(),
2787 SETCOORD_LENGTH
, aContext
, mPresContext
, inherited
);
2788 NS_ASSERTION(unitOK
, "unexpected unit");
2789 item
->mXOffset
= tempCoord
.GetCoordValue();
2791 unitOK
= SetCoord(arr
->Item(1), tempCoord
, nsStyleCoord(),
2792 SETCOORD_LENGTH
, aContext
, mPresContext
, inherited
);
2793 NS_ASSERTION(unitOK
, "unexpected unit");
2794 item
->mYOffset
= tempCoord
.GetCoordValue();
2796 // Blur radius is optional in the current box-shadow spec
2797 if (arr
->Item(2).GetUnit() != eCSSUnit_Null
) {
2798 unitOK
= SetCoord(arr
->Item(2), tempCoord
, nsStyleCoord(),
2799 SETCOORD_LENGTH
, aContext
, mPresContext
, inherited
);
2800 NS_ASSERTION(unitOK
, "unexpected unit");
2801 item
->mRadius
= tempCoord
.GetCoordValue();
2806 // Find the spread radius
2807 if (aUsesSpread
&& arr
->Item(3).GetUnit() != eCSSUnit_Null
) {
2808 unitOK
= SetCoord(arr
->Item(3), tempCoord
, nsStyleCoord(),
2809 SETCOORD_LENGTH
, aContext
, mPresContext
, inherited
);
2810 NS_ASSERTION(unitOK
, "unexpected unit");
2811 item
->mSpread
= tempCoord
.GetCoordValue();
2816 if (arr
->Item(4).GetUnit() != eCSSUnit_Null
) {
2817 item
->mHasColor
= PR_TRUE
;
2818 // 2nd argument can be bogus since inherit is not a valid color
2819 unitOK
= SetColor(arr
->Item(4), 0, mPresContext
, aContext
, item
->mColor
,
2821 NS_ASSERTION(unitOK
, "unexpected unit");
2825 NS_ADDREF(shadowList
);
2830 nsRuleNode::ComputeTextData(void* aStartStruct
,
2831 const nsRuleDataStruct
& aData
,
2832 nsStyleContext
* aContext
,
2833 nsRuleNode
* aHighestNode
,
2834 const RuleDetail aRuleDetail
, PRBool aInherited
)
2836 COMPUTE_START_INHERITED(Text
, (), text
, parentText
, Text
, textData
)
2838 // letter-spacing: normal, length, inherit
2839 SetCoord(textData
.mLetterSpacing
, text
->mLetterSpacing
, parentText
->mLetterSpacing
,
2840 SETCOORD_LH
| SETCOORD_NORMAL
| SETCOORD_INITIAL_NORMAL
,
2841 aContext
, mPresContext
, inherited
);
2843 // text-shadow: none, list, inherit, initial
2844 nsCSSValueList
* list
= textData
.mTextShadow
;
2846 text
->mTextShadow
= nsnull
;
2848 // Don't need to handle none/initial explicitly: The above assignment
2849 // takes care of that
2850 if (eCSSUnit_Inherit
== list
->mValue
.GetUnit()) {
2851 inherited
= PR_TRUE
;
2852 text
->mTextShadow
= parentText
->mTextShadow
;
2853 } else if (eCSSUnit_Array
== list
->mValue
.GetUnit()) {
2855 text
->mTextShadow
= GetShadowData(list
, aContext
, PR_FALSE
, inherited
);
2859 // line-height: normal, number, length, percent, inherit
2860 if (eCSSUnit_Percent
== textData
.mLineHeight
.GetUnit()) {
2861 inherited
= PR_TRUE
;
2862 // Use |mFont.size| to pick up minimum font size.
2863 text
->mLineHeight
.SetCoordValue(
2864 nscoord(float(aContext
->GetStyleFont()->mFont
.size
) *
2865 textData
.mLineHeight
.GetPercentValue()));
2867 else if (eCSSUnit_Initial
== textData
.mLineHeight
.GetUnit() ||
2868 eCSSUnit_System_Font
== textData
.mLineHeight
.GetUnit()) {
2869 text
->mLineHeight
.SetNormalValue();
2872 SetCoord(textData
.mLineHeight
, text
->mLineHeight
, parentText
->mLineHeight
,
2873 SETCOORD_LH
| SETCOORD_FACTOR
| SETCOORD_NORMAL
,
2874 aContext
, mPresContext
, inherited
);
2875 if (textData
.mLineHeight
.IsFixedLengthUnit() ||
2876 textData
.mLineHeight
.GetUnit() == eCSSUnit_Pixel
) {
2877 nscoord lh
= nsStyleFont::ZoomText(mPresContext
,
2878 text
->mLineHeight
.GetCoordValue());
2879 nscoord minimumFontSize
=
2880 mPresContext
->GetCachedIntPref(kPresContext_MinimumFontSize
);
2882 if (minimumFontSize
> 0 && !mPresContext
->IsChrome()) {
2883 // If we applied a minimum font size, scale the line height by
2884 // the same ratio. (If we *might* have applied a minimum font
2885 // size, we can't cache in the rule tree.)
2886 inherited
= PR_TRUE
;
2887 const nsStyleFont
*font
= aContext
->GetStyleFont();
2888 if (font
->mSize
!= 0) {
2889 lh
= nscoord(float(lh
) * float(font
->mFont
.size
) / float(font
->mSize
));
2891 lh
= minimumFontSize
;
2894 text
->mLineHeight
.SetCoordValue(lh
);
2899 // text-align: enum, string, inherit, initial
2900 if (eCSSUnit_String
== textData
.mTextAlign
.GetUnit()) {
2901 NS_NOTYETIMPLEMENTED("align string");
2903 SetDiscrete(textData
.mTextAlign
, text
->mTextAlign
, inherited
,
2904 SETDSC_ENUMERATED
, parentText
->mTextAlign
,
2905 NS_STYLE_TEXT_ALIGN_DEFAULT
,
2908 // text-indent: length, percent, inherit, initial
2909 SetCoord(textData
.mTextIndent
, text
->mTextIndent
, parentText
->mTextIndent
,
2910 SETCOORD_LPH
| SETCOORD_INITIAL_ZERO
, aContext
,
2911 mPresContext
, inherited
);
2913 // text-transform: enum, none, inherit, initial
2914 SetDiscrete(textData
.mTextTransform
, text
->mTextTransform
, inherited
,
2915 SETDSC_ENUMERATED
| SETDSC_NONE
, parentText
->mTextTransform
,
2916 NS_STYLE_TEXT_TRANSFORM_NONE
, 0,
2917 NS_STYLE_TEXT_TRANSFORM_NONE
, 0, 0);
2919 // white-space: enum, normal, inherit, initial
2920 SetDiscrete(textData
.mWhiteSpace
, text
->mWhiteSpace
, inherited
,
2921 SETDSC_ENUMERATED
| SETDSC_NORMAL
, parentText
->mWhiteSpace
,
2922 NS_STYLE_WHITESPACE_NORMAL
, 0, 0,
2923 NS_STYLE_WHITESPACE_NORMAL
, 0);
2925 // word-spacing: normal, length, inherit
2926 SetCoord(textData
.mWordSpacing
, text
->mWordSpacing
, parentText
->mWordSpacing
,
2927 SETCOORD_LH
| SETCOORD_NORMAL
| SETCOORD_INITIAL_NORMAL
,
2928 aContext
, mPresContext
, inherited
);
2930 // word-wrap: enum, normal, inherit, initial
2931 SetDiscrete(textData
.mWordWrap
, text
->mWordWrap
, inherited
,
2932 SETDSC_ENUMERATED
| SETDSC_NORMAL
, parentText
->mWordWrap
,
2933 NS_STYLE_WORDWRAP_NORMAL
, 0, 0,
2934 NS_STYLE_WORDWRAP_NORMAL
, 0);
2936 COMPUTE_END_INHERITED(Text
, text
)
2940 nsRuleNode::ComputeTextResetData(void* aStartStruct
,
2941 const nsRuleDataStruct
& aData
,
2942 nsStyleContext
* aContext
,
2943 nsRuleNode
* aHighestNode
,
2944 const RuleDetail aRuleDetail
, PRBool aInherited
)
2946 COMPUTE_START_RESET(TextReset
, (), text
, parentText
, Text
, textData
)
2948 // vertical-align: enum, length, percent, inherit
2949 if (!SetCoord(textData
.mVerticalAlign
, text
->mVerticalAlign
,
2950 parentText
->mVerticalAlign
, SETCOORD_LPH
| SETCOORD_ENUMERATED
,
2951 aContext
, mPresContext
, inherited
)) {
2952 if (eCSSUnit_Initial
== textData
.mVerticalAlign
.GetUnit()) {
2953 text
->mVerticalAlign
.SetIntValue(NS_STYLE_VERTICAL_ALIGN_BASELINE
,
2954 eStyleUnit_Enumerated
);
2958 // text-decoration: none, enum (bit field), inherit, initial
2959 if (eCSSUnit_Enumerated
== textData
.mDecoration
.GetUnit()) {
2960 PRInt32 td
= textData
.mDecoration
.GetIntValue();
2961 text
->mTextDecoration
= td
;
2962 if (td
& NS_STYLE_TEXT_DECORATION_PREF_ANCHORS
) {
2963 PRBool underlineLinks
=
2964 mPresContext
->GetCachedBoolPref(kPresContext_UnderlineLinks
);
2965 if (underlineLinks
) {
2966 text
->mTextDecoration
|= NS_STYLE_TEXT_DECORATION_UNDERLINE
;
2969 text
->mTextDecoration
&= ~NS_STYLE_TEXT_DECORATION_UNDERLINE
;
2974 SetDiscrete(textData
.mDecoration
, text
->mTextDecoration
, inherited
,
2976 parentText
->mTextDecoration
,
2977 NS_STYLE_TEXT_DECORATION_NONE
, 0,
2978 NS_STYLE_TEXT_DECORATION_NONE
, 0, 0);
2980 // unicode-bidi: enum, normal, inherit, initial
2981 SetDiscrete(textData
.mUnicodeBidi
, text
->mUnicodeBidi
, inherited
,
2982 SETDSC_ENUMERATED
| SETDSC_NORMAL
,
2983 parentText
->mUnicodeBidi
,
2984 NS_STYLE_UNICODE_BIDI_NORMAL
, 0, 0,
2985 NS_STYLE_UNICODE_BIDI_NORMAL
, 0);
2987 COMPUTE_END_RESET(TextReset
, text
)
2991 nsRuleNode::ComputeUserInterfaceData(void* aStartStruct
,
2992 const nsRuleDataStruct
& aData
,
2993 nsStyleContext
* aContext
,
2994 nsRuleNode
* aHighestNode
,
2995 const RuleDetail aRuleDetail
,
2998 COMPUTE_START_INHERITED(UserInterface
, (), ui
, parentUI
,
2999 UserInterface
, uiData
)
3001 // cursor: enum, auto, url, inherit
3002 nsCSSValueList
* list
= uiData
.mCursor
;
3003 if (nsnull
!= list
) {
3004 delete [] ui
->mCursorArray
;
3005 ui
->mCursorArray
= nsnull
;
3006 ui
->mCursorArrayLength
= 0;
3008 if (eCSSUnit_Inherit
== list
->mValue
.GetUnit()) {
3009 inherited
= PR_TRUE
;
3010 ui
->mCursor
= parentUI
->mCursor
;
3011 ui
->CopyCursorArrayFrom(*parentUI
);
3013 else if (eCSSUnit_Initial
== list
->mValue
.GetUnit()) {
3014 ui
->mCursor
= NS_STYLE_CURSOR_AUTO
;
3017 // The parser will never create a list that is *all* URL values --
3019 PRUint32 arrayLength
= 0;
3020 nsCSSValueList
* list2
= list
;
3021 for ( ; list
->mValue
.GetUnit() == eCSSUnit_Array
; list
= list
->mNext
)
3022 if (list
->mValue
.GetArrayValue()->Item(0).GetImageValue())
3025 if (arrayLength
!= 0) {
3026 ui
->mCursorArray
= new nsCursorImage
[arrayLength
];
3027 if (ui
->mCursorArray
) {
3028 ui
->mCursorArrayLength
= arrayLength
;
3030 for (nsCursorImage
*item
= ui
->mCursorArray
;
3031 list2
->mValue
.GetUnit() == eCSSUnit_Array
;
3032 list2
= list2
->mNext
) {
3033 nsCSSValue::Array
*arr
= list2
->mValue
.GetArrayValue();
3034 imgIRequest
*req
= arr
->Item(0).GetImageValue();
3037 if (arr
->Item(1).GetUnit() != eCSSUnit_Null
) {
3038 item
->mHaveHotspot
= PR_TRUE
;
3039 item
->mHotspotX
= arr
->Item(1).GetFloatValue(),
3040 item
->mHotspotY
= arr
->Item(2).GetFloatValue();
3048 NS_ASSERTION(list
, "Must have non-array value at the end");
3049 NS_ASSERTION(list
->mValue
.GetUnit() == eCSSUnit_Enumerated
||
3050 list
->mValue
.GetUnit() == eCSSUnit_Auto
,
3051 "Unexpected fallback value at end of cursor list");
3053 if (eCSSUnit_Enumerated
== list
->mValue
.GetUnit()) {
3054 ui
->mCursor
= list
->mValue
.GetIntValue();
3056 else if (eCSSUnit_Auto
== list
->mValue
.GetUnit()) {
3057 ui
->mCursor
= NS_STYLE_CURSOR_AUTO
;
3062 // user-input: auto, none, enum, inherit, initial
3063 SetDiscrete(uiData
.mUserInput
, ui
->mUserInput
, inherited
,
3064 SETDSC_ENUMERATED
| SETDSC_NONE
| SETDSC_AUTO
,
3065 parentUI
->mUserInput
,
3066 NS_STYLE_USER_INPUT_AUTO
,
3067 NS_STYLE_USER_INPUT_AUTO
,
3068 NS_STYLE_USER_INPUT_NONE
,
3071 // user-modify: enum, inherit, initial
3072 SetDiscrete(uiData
.mUserModify
, ui
->mUserModify
, inherited
,
3074 parentUI
->mUserModify
,
3075 NS_STYLE_USER_MODIFY_READ_ONLY
,
3078 // user-focus: none, normal, enum, inherit, initial
3079 SetDiscrete(uiData
.mUserFocus
, ui
->mUserFocus
, inherited
,
3080 SETDSC_ENUMERATED
| SETDSC_NONE
| SETDSC_NORMAL
,
3081 parentUI
->mUserFocus
,
3082 NS_STYLE_USER_FOCUS_NONE
,
3084 NS_STYLE_USER_FOCUS_NONE
,
3085 NS_STYLE_USER_FOCUS_NORMAL
,
3088 COMPUTE_END_INHERITED(UserInterface
, ui
)
3092 nsRuleNode::ComputeUIResetData(void* aStartStruct
,
3093 const nsRuleDataStruct
& aData
,
3094 nsStyleContext
* aContext
,
3095 nsRuleNode
* aHighestNode
,
3096 const RuleDetail aRuleDetail
, PRBool aInherited
)
3098 COMPUTE_START_RESET(UIReset
, (), ui
, parentUI
, UserInterface
, uiData
)
3100 // user-select: auto, none, enum, inherit, initial
3101 SetDiscrete(uiData
.mUserSelect
, ui
->mUserSelect
, inherited
,
3102 SETDSC_ENUMERATED
| SETDSC_NONE
| SETDSC_AUTO
,
3103 parentUI
->mUserSelect
,
3104 NS_STYLE_USER_SELECT_AUTO
,
3105 NS_STYLE_USER_SELECT_AUTO
,
3106 NS_STYLE_USER_SELECT_NONE
,
3109 // ime-mode: auto, normal, enum, inherit, initial
3110 SetDiscrete(uiData
.mIMEMode
, ui
->mIMEMode
, inherited
,
3111 SETDSC_ENUMERATED
| SETDSC_NORMAL
| SETDSC_AUTO
,
3113 NS_STYLE_IME_MODE_AUTO
,
3114 NS_STYLE_IME_MODE_AUTO
,
3116 NS_STYLE_IME_MODE_NORMAL
,
3119 // force-broken-image-icons: integer, inherit, initial
3120 SetDiscrete(uiData
.mForceBrokenImageIcon
, ui
->mForceBrokenImageIcon
,
3123 parentUI
->mForceBrokenImageIcon
,
3126 COMPUTE_END_RESET(UIReset
, ui
)
3129 /* Given a -moz-transform token stream, accumulates them into an
3130 * nsStyleTransformMatrix
3132 * @param aList The nsCSSValueList of arrays to read into transform functions.
3133 * @param aContext The style context to use for unit conversion.
3134 * @param aPresContext The presentation context to use for unit conversion
3135 * @param aInherited If the value is inherited, this is set to PR_TRUE.
3136 * @return An nsStyleTransformMatrix corresponding to the net transform.
3138 static nsStyleTransformMatrix
ReadTransforms(const nsCSSValueList
* aList
,
3139 nsStyleContext
* aContext
,
3140 nsPresContext
* aPresContext
,
3143 nsStyleTransformMatrix result
;
3145 for (const nsCSSValueList
* curr
= aList
; curr
!= nsnull
; curr
= curr
->mNext
) {
3146 const nsCSSValue
&currElem
= curr
->mValue
;
3147 NS_ASSERTION(currElem
.GetUnit() == eCSSUnit_Function
,
3148 "Stream should consist solely of functions!");
3149 NS_ASSERTION(currElem
.GetArrayValue()->Count() >= 1,
3150 "Incoming function is too short!");
3152 /* Read in a single transform matrix, then accumulate it with the total. */
3153 nsStyleTransformMatrix currMatrix
;
3154 currMatrix
.SetToTransformFunction(currElem
.GetArrayValue(), aContext
,
3156 result
*= currMatrix
;
3162 nsRuleNode::ComputeDisplayData(void* aStartStruct
,
3163 const nsRuleDataStruct
& aData
,
3164 nsStyleContext
* aContext
,
3165 nsRuleNode
* aHighestNode
,
3166 const RuleDetail aRuleDetail
, PRBool aInherited
)
3168 COMPUTE_START_RESET(Display
, (), display
, parentDisplay
,
3169 Display
, displayData
)
3170 nsIAtom
* pseudoTag
= aContext
->GetPseudoType();
3171 PRBool generatedContent
= (pseudoTag
== nsCSSPseudoElements::before
||
3172 pseudoTag
== nsCSSPseudoElements::after
);
3173 NS_ASSERTION(!generatedContent
|| parentContext
,
3174 "Must have parent context for generated content");
3175 if (parentDisplay
== display
&& generatedContent
)
3176 parentDisplay
= parentContext
->GetStyleDisplay();
3178 // opacity: factor, inherit, initial
3179 SetFactor(displayData
.mOpacity
, display
->mOpacity
, inherited
,
3180 parentDisplay
->mOpacity
, 1.0f
, SETFCT_OPACITY
);
3182 // display: enum, none, inherit, initial
3183 SetDiscrete(displayData
.mDisplay
, display
->mDisplay
, inherited
,
3184 SETDSC_ENUMERATED
| SETDSC_NONE
, parentDisplay
->mDisplay
,
3185 NS_STYLE_DISPLAY_INLINE
, 0,
3186 NS_STYLE_DISPLAY_NONE
, 0, 0);
3188 // appearance: enum, none, inherit, initial
3189 SetDiscrete(displayData
.mAppearance
, display
->mAppearance
, inherited
,
3190 SETDSC_ENUMERATED
| SETDSC_NONE
, parentDisplay
->mAppearance
,
3192 NS_THEME_NONE
, 0, 0);
3194 // binding: url, none, inherit
3195 if (eCSSUnit_URL
== displayData
.mBinding
.GetUnit()) {
3196 nsCSSValue::URL
* url
= displayData
.mBinding
.GetURLStructValue();
3197 NS_ASSERTION(url
, "What's going on here?");
3199 if (NS_LIKELY(url
->mURI
)) {
3200 display
->mBinding
= url
;
3202 display
->mBinding
= nsnull
;
3205 else if (eCSSUnit_None
== displayData
.mBinding
.GetUnit() ||
3206 eCSSUnit_Initial
== displayData
.mBinding
.GetUnit()) {
3207 display
->mBinding
= nsnull
;
3209 else if (eCSSUnit_Inherit
== displayData
.mBinding
.GetUnit()) {
3210 inherited
= PR_TRUE
;
3211 display
->mBinding
= parentDisplay
->mBinding
;
3214 // position: enum, inherit, initial
3215 SetDiscrete(displayData
.mPosition
, display
->mPosition
, inherited
,
3216 SETDSC_ENUMERATED
, parentDisplay
->mPosition
,
3217 NS_STYLE_POSITION_STATIC
, 0, 0, 0, 0);
3219 // clear: enum, none, inherit, initial
3220 SetDiscrete(displayData
.mClear
, display
->mBreakType
, inherited
,
3221 SETDSC_ENUMERATED
| SETDSC_NONE
, parentDisplay
->mBreakType
,
3222 NS_STYLE_CLEAR_NONE
, 0,
3223 NS_STYLE_CLEAR_NONE
, 0, 0);
3225 // temp fix for bug 24000
3226 // Map 'auto' and 'avoid' to PR_FALSE, and 'always', 'left', and
3227 // 'right' to PR_TRUE.
3228 // "A conforming user agent may interpret the values 'left' and
3229 // 'right' as 'always'." - CSS2.1, section 13.3.1
3230 if (eCSSUnit_Enumerated
== displayData
.mBreakBefore
.GetUnit()) {
3231 display
->mBreakBefore
= (NS_STYLE_PAGE_BREAK_AVOID
!= displayData
.mBreakBefore
.GetIntValue());
3233 else if (eCSSUnit_Auto
== displayData
.mBreakBefore
.GetUnit() ||
3234 eCSSUnit_Initial
== displayData
.mBreakBefore
.GetUnit()) {
3235 display
->mBreakBefore
= PR_FALSE
;
3237 else if (eCSSUnit_Inherit
== displayData
.mBreakBefore
.GetUnit()) {
3238 inherited
= PR_TRUE
;
3239 display
->mBreakBefore
= parentDisplay
->mBreakBefore
;
3242 if (eCSSUnit_Enumerated
== displayData
.mBreakAfter
.GetUnit()) {
3243 display
->mBreakAfter
= (NS_STYLE_PAGE_BREAK_AVOID
!= displayData
.mBreakAfter
.GetIntValue());
3245 else if (eCSSUnit_Auto
== displayData
.mBreakAfter
.GetUnit() ||
3246 eCSSUnit_Initial
== displayData
.mBreakAfter
.GetUnit()) {
3247 display
->mBreakAfter
= PR_FALSE
;
3249 else if (eCSSUnit_Inherit
== displayData
.mBreakAfter
.GetUnit()) {
3250 inherited
= PR_TRUE
;
3251 display
->mBreakAfter
= parentDisplay
->mBreakAfter
;
3255 // float: enum, none, inherit, initial
3256 SetDiscrete(displayData
.mFloat
, display
->mFloats
, inherited
,
3257 SETDSC_ENUMERATED
| SETDSC_NONE
, parentDisplay
->mFloats
,
3258 NS_STYLE_FLOAT_NONE
, 0,
3259 NS_STYLE_FLOAT_NONE
, 0, 0);
3261 // overflow-x: enum, auto, inherit, initial
3262 SetDiscrete(displayData
.mOverflowX
, display
->mOverflowX
, inherited
,
3263 SETDSC_ENUMERATED
| SETDSC_AUTO
,
3264 parentDisplay
->mOverflowX
,
3265 NS_STYLE_OVERFLOW_VISIBLE
,
3266 NS_STYLE_OVERFLOW_AUTO
,
3269 // overflow-y: enum, auto, inherit, initial
3270 SetDiscrete(displayData
.mOverflowY
, display
->mOverflowY
, inherited
,
3271 SETDSC_ENUMERATED
| SETDSC_AUTO
,
3272 parentDisplay
->mOverflowY
,
3273 NS_STYLE_OVERFLOW_VISIBLE
,
3274 NS_STYLE_OVERFLOW_AUTO
,
3277 // CSS3 overflow-x and overflow-y require some fixup as well in some
3278 // cases. NS_STYLE_OVERFLOW_VISIBLE and NS_STYLE_OVERFLOW_CLIP are
3279 // meaningful only when used in both dimensions.
3280 if (display
->mOverflowX
!= display
->mOverflowY
&&
3281 (display
->mOverflowX
== NS_STYLE_OVERFLOW_VISIBLE
||
3282 display
->mOverflowX
== NS_STYLE_OVERFLOW_CLIP
||
3283 display
->mOverflowY
== NS_STYLE_OVERFLOW_VISIBLE
||
3284 display
->mOverflowY
== NS_STYLE_OVERFLOW_CLIP
)) {
3285 // We can't store in the rule tree since a more specific rule might
3286 // change these conditions.
3287 inherited
= PR_TRUE
;
3289 // NS_STYLE_OVERFLOW_CLIP is a deprecated value, so if it's specified
3290 // in only one dimension, convert it to NS_STYLE_OVERFLOW_HIDDEN.
3291 if (display
->mOverflowX
== NS_STYLE_OVERFLOW_CLIP
)
3292 display
->mOverflowX
= NS_STYLE_OVERFLOW_HIDDEN
;
3293 if (display
->mOverflowY
== NS_STYLE_OVERFLOW_CLIP
)
3294 display
->mOverflowY
= NS_STYLE_OVERFLOW_HIDDEN
;
3296 // If 'visible' is specified but doesn't match the other dimension, it
3297 // turns into 'auto'.
3298 if (display
->mOverflowX
== NS_STYLE_OVERFLOW_VISIBLE
)
3299 display
->mOverflowX
= NS_STYLE_OVERFLOW_AUTO
;
3300 if (display
->mOverflowY
== NS_STYLE_OVERFLOW_VISIBLE
)
3301 display
->mOverflowY
= NS_STYLE_OVERFLOW_AUTO
;
3304 // clip property: length, auto, inherit
3305 if (eCSSUnit_Inherit
== displayData
.mClip
.mTop
.GetUnit()) { // if one is inherit, they all are
3306 inherited
= PR_TRUE
;
3307 display
->mClipFlags
= parentDisplay
->mClipFlags
;
3308 display
->mClip
= parentDisplay
->mClip
;
3310 // if one is initial, they all are
3311 else if (eCSSUnit_Initial
== displayData
.mClip
.mTop
.GetUnit()) {
3312 display
->mClipFlags
= NS_STYLE_CLIP_AUTO
;
3313 display
->mClip
.SetRect(0,0,0,0);
3316 PRBool fullAuto
= PR_TRUE
;
3318 display
->mClipFlags
= 0; // clear it
3320 if (eCSSUnit_Auto
== displayData
.mClip
.mTop
.GetUnit()) {
3321 display
->mClip
.y
= 0;
3322 display
->mClipFlags
|= NS_STYLE_CLIP_TOP_AUTO
;
3324 else if (displayData
.mClip
.mTop
.IsLengthUnit()) {
3325 display
->mClip
.y
= CalcLength(displayData
.mClip
.mTop
, aContext
, mPresContext
, inherited
);
3326 fullAuto
= PR_FALSE
;
3328 if (eCSSUnit_Auto
== displayData
.mClip
.mBottom
.GetUnit()) {
3329 // Setting to NS_MAXSIZE for the 'auto' case ensures that
3330 // the clip rect is nonempty. It is important that mClip be
3331 // nonempty if the actual clip rect could be nonempty.
3332 display
->mClip
.height
= NS_MAXSIZE
;
3333 display
->mClipFlags
|= NS_STYLE_CLIP_BOTTOM_AUTO
;
3335 else if (displayData
.mClip
.mBottom
.IsLengthUnit()) {
3336 display
->mClip
.height
= CalcLength(displayData
.mClip
.mBottom
, aContext
, mPresContext
, inherited
) -
3338 fullAuto
= PR_FALSE
;
3340 if (eCSSUnit_Auto
== displayData
.mClip
.mLeft
.GetUnit()) {
3341 display
->mClip
.x
= 0;
3342 display
->mClipFlags
|= NS_STYLE_CLIP_LEFT_AUTO
;
3344 else if (displayData
.mClip
.mLeft
.IsLengthUnit()) {
3345 display
->mClip
.x
= CalcLength(displayData
.mClip
.mLeft
, aContext
, mPresContext
, inherited
);
3346 fullAuto
= PR_FALSE
;
3348 if (eCSSUnit_Auto
== displayData
.mClip
.mRight
.GetUnit()) {
3349 // Setting to NS_MAXSIZE for the 'auto' case ensures that
3350 // the clip rect is nonempty. It is important that mClip be
3351 // nonempty if the actual clip rect could be nonempty.
3352 display
->mClip
.width
= NS_MAXSIZE
;
3353 display
->mClipFlags
|= NS_STYLE_CLIP_RIGHT_AUTO
;
3355 else if (displayData
.mClip
.mRight
.IsLengthUnit()) {
3356 display
->mClip
.width
= CalcLength(displayData
.mClip
.mRight
, aContext
, mPresContext
, inherited
) -
3358 fullAuto
= PR_FALSE
;
3360 display
->mClipFlags
&= ~NS_STYLE_CLIP_TYPE_MASK
;
3362 display
->mClipFlags
|= NS_STYLE_CLIP_AUTO
;
3365 display
->mClipFlags
|= NS_STYLE_CLIP_RECT
;
3369 if (display
->mDisplay
!= NS_STYLE_DISPLAY_NONE
) {
3370 // CSS2 9.7 specifies display type corrections dealing with 'float'
3371 // and 'position'. Since generated content can't be floated or
3372 // positioned, we can deal with it here.
3374 if (nsCSSPseudoElements::firstLetter
== pseudoTag
) {
3375 // a non-floating first-letter must be inline
3376 // XXX this fix can go away once bug 103189 is fixed correctly
3377 display
->mDisplay
= NS_STYLE_DISPLAY_INLINE
;
3379 // We can't cache the data in the rule tree since if a more specific
3380 // rule has 'float: left' we'll end up with the wrong 'display'
3382 inherited
= PR_TRUE
;
3385 if (display
->IsAbsolutelyPositioned()) {
3386 // 1) if position is 'absolute' or 'fixed' then display must be
3387 // block-level and float must be 'none'
3389 // Backup original display value for calculation of a hypothetical
3390 // box (CSS2 10.6.4/10.6.5).
3391 // See nsHTMLReflowState::CalculateHypotheticalBox
3392 display
->mOriginalDisplay
= display
->mDisplay
;
3393 EnsureBlockDisplay(display
->mDisplay
);
3394 display
->mFloats
= NS_STYLE_FLOAT_NONE
;
3396 // We can't cache the data in the rule tree since if a more specific
3397 // rule has 'position: static' we'll end up with problems with the
3398 // 'display' and 'float' properties.
3399 inherited
= PR_TRUE
;
3400 } else if (display
->mFloats
!= NS_STYLE_FLOAT_NONE
) {
3401 // 2) if float is not none, and display is not none, then we must
3402 // set a block-level 'display' type per CSS2.1 section 9.7.
3404 EnsureBlockDisplay(display
->mDisplay
);
3406 // We can't cache the data in the rule tree since if a more specific
3407 // rule has 'float: none' we'll end up with the wrong 'display'
3409 inherited
= PR_TRUE
;
3414 /* Convert the nsCSSValueList into an nsTArray<nsTransformFunction *>. */
3415 const nsCSSValueList
*head
= displayData
.mTransform
;
3417 if (head
!= nsnull
) {
3418 /* There is a chance that we will discover that
3419 * the transform property has been set to 'none,' 'initial,' or 'inherit.'
3420 * If so, process appropriately.
3423 /* If it's 'none,' indicate that there are no transforms. */
3424 if (head
->mValue
.GetUnit() == eCSSUnit_None
)
3425 display
->mTransformPresent
= PR_FALSE
;
3427 /* If we need to inherit, do so by making a full deep-copy. */
3428 else if (head
->mValue
.GetUnit() == eCSSUnit_Inherit
) {
3429 display
->mTransformPresent
= parentDisplay
->mTransformPresent
;
3430 if (parentDisplay
->mTransformPresent
)
3431 display
->mTransform
= parentDisplay
->mTransform
;
3432 inherited
= PR_TRUE
;
3434 /* If it's 'initial', then we reset to empty. */
3435 else if (head
->mValue
.GetUnit() == eCSSUnit_Initial
)
3436 display
->mTransformPresent
= PR_FALSE
;
3438 /* Otherwise, we are looking at a list of CSS tokens. We'll read each of
3439 * them in as an array of nsTransformFunction objects, then will accumulate
3440 * them all together to form the final transform matrix.
3444 display
->mTransform
=
3445 ReadTransforms(head
, aContext
, mPresContext
, inherited
);
3447 /* Make sure to say that this data is valid! */
3448 display
->mTransformPresent
= PR_TRUE
;
3452 /* Convert -moz-transform-origin. */
3453 if (displayData
.mTransformOrigin
.mXValue
.GetUnit() != eCSSUnit_Null
||
3454 displayData
.mTransformOrigin
.mXValue
.GetUnit() != eCSSUnit_Null
) {
3456 /* If X coordinate is an enumerated type, handle it explicitly. */
3457 if (eCSSUnit_Enumerated
== displayData
.mTransformOrigin
.mXValue
.GetUnit())
3458 display
->mTransformOrigin
[0].SetPercentValue
3459 (GetFloatFromBoxPosition
3460 (displayData
.mTransformOrigin
.mXValue
.GetIntValue()));
3462 /* Convert lengths, percents, and inherit. Default value is 50%. */
3466 SetCoord(displayData
.mTransformOrigin
.mXValue
,
3467 display
->mTransformOrigin
[0],
3468 parentDisplay
->mTransformOrigin
[0],
3469 SETCOORD_LPH
| SETCOORD_INITIAL_HALF
,
3470 aContext
, mPresContext
, aInherited
);
3471 NS_ASSERTION(result
, "Malformed -moz-transform-origin parse!");
3474 /* If Y coordinate is an enumerated type, handle it explicitly. */
3475 if (eCSSUnit_Enumerated
== displayData
.mTransformOrigin
.mYValue
.GetUnit())
3476 display
->mTransformOrigin
[1].SetPercentValue
3477 (GetFloatFromBoxPosition
3478 (displayData
.mTransformOrigin
.mYValue
.GetIntValue()));
3480 /* Convert lengths, percents, initial, inherit. */
3484 SetCoord(displayData
.mTransformOrigin
.mYValue
,
3485 display
->mTransformOrigin
[1],
3486 parentDisplay
->mTransformOrigin
[1],
3487 SETCOORD_LPH
| SETCOORD_INITIAL_HALF
,
3488 aContext
, mPresContext
, aInherited
);
3489 NS_ASSERTION(result
, "Malformed -moz-transform-origin parse!");
3493 COMPUTE_END_RESET(Display
, display
)
3497 nsRuleNode::ComputeVisibilityData(void* aStartStruct
,
3498 const nsRuleDataStruct
& aData
,
3499 nsStyleContext
* aContext
,
3500 nsRuleNode
* aHighestNode
,
3501 const RuleDetail aRuleDetail
, PRBool aInherited
)
3503 COMPUTE_START_INHERITED(Visibility
, (mPresContext
),
3504 visibility
, parentVisibility
,
3505 Display
, displayData
)
3507 // direction: enum, inherit, initial
3508 SetDiscrete(displayData
.mDirection
, visibility
->mDirection
, inherited
,
3509 SETDSC_ENUMERATED
, parentVisibility
->mDirection
,
3510 (GET_BIDI_OPTION_DIRECTION(mPresContext
->GetBidi())
3511 == IBMBIDI_TEXTDIRECTION_RTL
)
3512 ? NS_STYLE_DIRECTION_RTL
: NS_STYLE_DIRECTION_LTR
,
3515 // visibility: enum, inherit, initial
3516 SetDiscrete(displayData
.mVisibility
, visibility
->mVisible
, inherited
,
3517 SETDSC_ENUMERATED
, parentVisibility
->mVisible
,
3518 NS_STYLE_VISIBILITY_VISIBLE
, 0, 0, 0, 0);
3520 // lang: string, inherit
3521 // this is not a real CSS property, it is a html attribute mapped to CSS struture
3522 if (eCSSUnit_String
== displayData
.mLang
.GetUnit()) {
3523 if (!gLangService
) {
3524 CallGetService(NS_LANGUAGEATOMSERVICE_CONTRACTID
, &gLangService
);
3529 displayData
.mLang
.GetStringValue(lang
);
3530 visibility
->mLangGroup
= gLangService
->LookupLanguage(lang
);
3534 COMPUTE_END_INHERITED(Visibility
, visibility
)
3538 nsRuleNode::ComputeColorData(void* aStartStruct
,
3539 const nsRuleDataStruct
& aData
,
3540 nsStyleContext
* aContext
,
3541 nsRuleNode
* aHighestNode
,
3542 const RuleDetail aRuleDetail
, PRBool aInherited
)
3544 COMPUTE_START_INHERITED(Color
, (mPresContext
), color
, parentColor
,
3547 // color: color, string, inherit
3548 // Special case for currentColor. According to CSS3, setting color to 'currentColor'
3549 // should behave as if it is inherited
3550 if (colorData
.mColor
.GetUnit() == eCSSUnit_EnumColor
&&
3551 colorData
.mColor
.GetIntValue() == NS_COLOR_CURRENTCOLOR
) {
3552 color
->mColor
= parentColor
->mColor
;
3553 inherited
= PR_TRUE
;
3555 else if (colorData
.mColor
.GetUnit() == eCSSUnit_Initial
) {
3556 color
->mColor
= mPresContext
->DefaultColor();
3559 SetColor(colorData
.mColor
, parentColor
->mColor
, mPresContext
, aContext
, color
->mColor
,
3563 COMPUTE_END_INHERITED(Color
, color
)
3567 nsRuleNode::ComputeBackgroundData(void* aStartStruct
,
3568 const nsRuleDataStruct
& aData
,
3569 nsStyleContext
* aContext
,
3570 nsRuleNode
* aHighestNode
,
3571 const RuleDetail aRuleDetail
,
3574 COMPUTE_START_RESET(Background
, (), bg
, parentBG
, Color
, colorData
)
3576 // save parentFlags in case bg == parentBG and we clobber them later
3577 PRUint8 parentFlags
= parentBG
->mBackgroundFlags
;
3579 // background-color: color, string, inherit
3580 if (eCSSUnit_Initial
== colorData
.mBackColor
.GetUnit()) {
3581 bg
->mBackgroundColor
= NS_RGBA(0, 0, 0, 0);
3582 } else if (!SetColor(colorData
.mBackColor
, parentBG
->mBackgroundColor
,
3583 mPresContext
, aContext
, bg
->mBackgroundColor
,
3585 NS_ASSERTION(eCSSUnit_Null
== colorData
.mBackColor
.GetUnit(),
3586 "unexpected color unit");
3589 // background-image: url (stored as image), none, inherit
3590 if (eCSSUnit_Image
== colorData
.mBackImage
.GetUnit()) {
3591 bg
->mBackgroundImage
= colorData
.mBackImage
.GetImageValue();
3593 else if (eCSSUnit_None
== colorData
.mBackImage
.GetUnit() ||
3594 eCSSUnit_Initial
== colorData
.mBackImage
.GetUnit()) {
3595 bg
->mBackgroundImage
= nsnull
;
3597 else if (eCSSUnit_Inherit
== colorData
.mBackImage
.GetUnit()) {
3598 inherited
= PR_TRUE
;
3599 bg
->mBackgroundImage
= parentBG
->mBackgroundImage
;
3602 if (bg
->mBackgroundImage
) {
3603 bg
->mBackgroundFlags
&= ~NS_STYLE_BG_IMAGE_NONE
;
3605 bg
->mBackgroundFlags
|= NS_STYLE_BG_IMAGE_NONE
;
3608 // background-repeat: enum, inherit, initial
3609 SetDiscrete(colorData
.mBackRepeat
, bg
->mBackgroundRepeat
, inherited
,
3610 SETDSC_ENUMERATED
, parentBG
->mBackgroundRepeat
,
3611 NS_STYLE_BG_REPEAT_XY
, 0, 0, 0, 0);
3613 // background-attachment: enum, inherit, initial
3614 SetDiscrete(colorData
.mBackAttachment
, bg
->mBackgroundAttachment
, inherited
,
3615 SETDSC_ENUMERATED
, parentBG
->mBackgroundAttachment
,
3616 NS_STYLE_BG_ATTACHMENT_SCROLL
, 0, 0, 0, 0);
3618 // background-clip: enum, inherit, initial
3619 SetDiscrete(colorData
.mBackClip
, bg
->mBackgroundClip
, inherited
,
3620 SETDSC_ENUMERATED
, parentBG
->mBackgroundClip
,
3621 NS_STYLE_BG_CLIP_BORDER
, 0, 0, 0, 0);
3623 // background-inline-policy: enum, inherit, initial
3624 SetDiscrete(colorData
.mBackInlinePolicy
, bg
->mBackgroundInlinePolicy
,
3625 inherited
, SETDSC_ENUMERATED
,
3626 parentBG
->mBackgroundInlinePolicy
,
3627 NS_STYLE_BG_INLINE_POLICY_CONTINUOUS
, 0, 0, 0, 0);
3629 // background-origin: enum, inherit, initial
3630 SetDiscrete(colorData
.mBackOrigin
, bg
->mBackgroundOrigin
, inherited
,
3631 SETDSC_ENUMERATED
, parentBG
->mBackgroundOrigin
,
3632 NS_STYLE_BG_ORIGIN_PADDING
, 0, 0, 0, 0);
3634 // background-position: enum, length, percent (flags), inherit
3635 if (eCSSUnit_Percent
== colorData
.mBackPosition
.mXValue
.GetUnit()) {
3636 bg
->mBackgroundXPosition
.mFloat
= colorData
.mBackPosition
.mXValue
.GetPercentValue();
3637 bg
->mBackgroundFlags
|= NS_STYLE_BG_X_POSITION_PERCENT
;
3638 bg
->mBackgroundFlags
&= ~NS_STYLE_BG_X_POSITION_LENGTH
;
3640 else if (colorData
.mBackPosition
.mXValue
.IsLengthUnit()) {
3641 bg
->mBackgroundXPosition
.mCoord
= CalcLength(colorData
.mBackPosition
.mXValue
,
3642 aContext
, mPresContext
, inherited
);
3643 bg
->mBackgroundFlags
|= NS_STYLE_BG_X_POSITION_LENGTH
;
3644 bg
->mBackgroundFlags
&= ~NS_STYLE_BG_X_POSITION_PERCENT
;
3646 else if (eCSSUnit_Enumerated
== colorData
.mBackPosition
.mXValue
.GetUnit()) {
3647 bg
->mBackgroundXPosition
.mFloat
=
3648 GetFloatFromBoxPosition(colorData
.mBackPosition
.mXValue
.GetIntValue());
3650 bg
->mBackgroundFlags
|= NS_STYLE_BG_X_POSITION_PERCENT
;
3651 bg
->mBackgroundFlags
&= ~NS_STYLE_BG_X_POSITION_LENGTH
;
3653 else if (eCSSUnit_Inherit
== colorData
.mBackPosition
.mXValue
.GetUnit()) {
3654 inherited
= PR_TRUE
;
3655 bg
->mBackgroundXPosition
= parentBG
->mBackgroundXPosition
;
3656 bg
->mBackgroundFlags
&= ~(NS_STYLE_BG_X_POSITION_LENGTH
| NS_STYLE_BG_X_POSITION_PERCENT
);
3657 bg
->mBackgroundFlags
|= (parentFlags
& (NS_STYLE_BG_X_POSITION_LENGTH
| NS_STYLE_BG_X_POSITION_PERCENT
));
3659 else if (eCSSUnit_Initial
== colorData
.mBackPosition
.mXValue
.GetUnit()) {
3660 bg
->mBackgroundFlags
&= ~(NS_STYLE_BG_X_POSITION_LENGTH
| NS_STYLE_BG_X_POSITION_PERCENT
);
3663 if (eCSSUnit_Percent
== colorData
.mBackPosition
.mYValue
.GetUnit()) {
3664 bg
->mBackgroundYPosition
.mFloat
= colorData
.mBackPosition
.mYValue
.GetPercentValue();
3665 bg
->mBackgroundFlags
|= NS_STYLE_BG_Y_POSITION_PERCENT
;
3666 bg
->mBackgroundFlags
&= ~NS_STYLE_BG_Y_POSITION_LENGTH
;
3668 else if (colorData
.mBackPosition
.mYValue
.IsLengthUnit()) {
3669 bg
->mBackgroundYPosition
.mCoord
= CalcLength(colorData
.mBackPosition
.mYValue
,
3670 aContext
, mPresContext
, inherited
);
3671 bg
->mBackgroundFlags
|= NS_STYLE_BG_Y_POSITION_LENGTH
;
3672 bg
->mBackgroundFlags
&= ~NS_STYLE_BG_Y_POSITION_PERCENT
;
3674 else if (eCSSUnit_Enumerated
== colorData
.mBackPosition
.mYValue
.GetUnit()) {
3675 bg
->mBackgroundYPosition
.mFloat
=
3676 GetFloatFromBoxPosition(colorData
.mBackPosition
.mYValue
.GetIntValue());
3678 bg
->mBackgroundFlags
|= NS_STYLE_BG_Y_POSITION_PERCENT
;
3679 bg
->mBackgroundFlags
&= ~NS_STYLE_BG_Y_POSITION_LENGTH
;
3681 else if (eCSSUnit_Inherit
== colorData
.mBackPosition
.mYValue
.GetUnit()) {
3682 inherited
= PR_TRUE
;
3683 bg
->mBackgroundYPosition
= parentBG
->mBackgroundYPosition
;
3684 bg
->mBackgroundFlags
&= ~(NS_STYLE_BG_Y_POSITION_LENGTH
| NS_STYLE_BG_Y_POSITION_PERCENT
);
3685 bg
->mBackgroundFlags
|= (parentFlags
& (NS_STYLE_BG_Y_POSITION_LENGTH
| NS_STYLE_BG_Y_POSITION_PERCENT
));
3687 else if (eCSSUnit_Initial
== colorData
.mBackPosition
.mYValue
.GetUnit()) {
3688 bg
->mBackgroundFlags
&= ~(NS_STYLE_BG_Y_POSITION_LENGTH
| NS_STYLE_BG_Y_POSITION_PERCENT
);
3691 COMPUTE_END_RESET(Background
, bg
)
3695 nsRuleNode::ComputeMarginData(void* aStartStruct
,
3696 const nsRuleDataStruct
& aData
,
3697 nsStyleContext
* aContext
,
3698 nsRuleNode
* aHighestNode
,
3699 const RuleDetail aRuleDetail
, PRBool aInherited
)
3701 COMPUTE_START_RESET(Margin
, (), margin
, parentMargin
, Margin
, marginData
)
3703 // margin: length, percent, auto, inherit
3705 nsCSSRect
ourMargin(marginData
.mMargin
);
3706 AdjustLogicalBoxProp(aContext
,
3707 marginData
.mMarginLeftLTRSource
,
3708 marginData
.mMarginLeftRTLSource
,
3709 marginData
.mMarginStart
, marginData
.mMarginEnd
,
3710 NS_SIDE_LEFT
, ourMargin
, inherited
);
3711 AdjustLogicalBoxProp(aContext
,
3712 marginData
.mMarginRightLTRSource
,
3713 marginData
.mMarginRightRTLSource
,
3714 marginData
.mMarginEnd
, marginData
.mMarginStart
,
3715 NS_SIDE_RIGHT
, ourMargin
, inherited
);
3716 NS_FOR_CSS_SIDES(side
) {
3717 nsStyleCoord parentCoord
= parentMargin
->mMargin
.Get(side
);
3718 if (SetCoord(ourMargin
.*(nsCSSRect::sides
[side
]),
3719 coord
, parentCoord
, SETCOORD_LPAH
| SETCOORD_INITIAL_ZERO
,
3720 aContext
, mPresContext
, inherited
)) {
3721 margin
->mMargin
.Set(side
, coord
);
3725 margin
->RecalcData();
3726 COMPUTE_END_RESET(Margin
, margin
)
3730 nsRuleNode::ComputeBorderData(void* aStartStruct
,
3731 const nsRuleDataStruct
& aData
,
3732 nsStyleContext
* aContext
,
3733 nsRuleNode
* aHighestNode
,
3734 const RuleDetail aRuleDetail
, PRBool aInherited
)
3736 COMPUTE_START_RESET(Border
, (mPresContext
), border
, parentBorder
,
3739 // -moz-box-shadow: none, list, inherit, initial
3740 nsCSSValueList
* list
= marginData
.mBoxShadow
;
3742 // This handles 'none' and 'initial'
3743 border
->mBoxShadow
= nsnull
;
3745 if (eCSSUnit_Inherit
== list
->mValue
.GetUnit()) {
3746 inherited
= PR_TRUE
;
3747 border
->mBoxShadow
= parentBorder
->mBoxShadow
;
3748 } else if (eCSSUnit_Array
== list
->mValue
.GetUnit()) {
3750 border
->mBoxShadow
= GetShadowData(list
, aContext
, PR_TRUE
, inherited
);
3754 // border-width, border-*-width: length, enum, inherit
3756 nsCSSRect
ourBorderWidth(marginData
.mBorderWidth
);
3757 AdjustLogicalBoxProp(aContext
,
3758 marginData
.mBorderLeftWidthLTRSource
,
3759 marginData
.mBorderLeftWidthRTLSource
,
3760 marginData
.mBorderStartWidth
,
3761 marginData
.mBorderEndWidth
,
3762 NS_SIDE_LEFT
, ourBorderWidth
, inherited
);
3763 AdjustLogicalBoxProp(aContext
,
3764 marginData
.mBorderRightWidthLTRSource
,
3765 marginData
.mBorderRightWidthRTLSource
,
3766 marginData
.mBorderEndWidth
,
3767 marginData
.mBorderStartWidth
,
3768 NS_SIDE_RIGHT
, ourBorderWidth
, inherited
);
3769 { // scope for compilers with broken |for| loop scoping
3770 NS_FOR_CSS_SIDES(side
) {
3771 const nsCSSValue
&value
= ourBorderWidth
.*(nsCSSRect::sides
[side
]);
3772 NS_ASSERTION(eCSSUnit_Percent
!= value
.GetUnit(),
3773 "Percentage borders not implemented yet "
3774 "If implementing, make sure to fix all consumers of "
3775 "nsStyleBorder, the IsPercentageAwareChild method, "
3776 "the nsAbsoluteContainingBlock::FrameDependsOnContainer "
3778 "nsLineLayout::IsPercentageAwareReplacedElement method "
3779 "and probably some other places");
3780 if (eCSSUnit_Enumerated
== value
.GetUnit()) {
3781 NS_ASSERTION(value
.GetIntValue() == NS_STYLE_BORDER_WIDTH_THIN
||
3782 value
.GetIntValue() == NS_STYLE_BORDER_WIDTH_MEDIUM
||
3783 value
.GetIntValue() == NS_STYLE_BORDER_WIDTH_THICK
,
3784 "Unexpected enum value");
3785 border
->SetBorderWidth(side
,
3786 (mPresContext
->GetBorderWidthTable())[value
.GetIntValue()]);
3788 // OK to pass bad aParentCoord since we're not passing SETCOORD_INHERIT
3789 else if (SetCoord(value
, coord
, nsStyleCoord(), SETCOORD_LENGTH
,
3790 aContext
, mPresContext
, inherited
)) {
3791 NS_ASSERTION(coord
.GetUnit() == eStyleUnit_Coord
, "unexpected unit");
3792 border
->SetBorderWidth(side
, coord
.GetCoordValue());
3794 else if (eCSSUnit_Inherit
== value
.GetUnit()) {
3795 inherited
= PR_TRUE
;
3796 border
->SetBorderWidth(side
,
3797 parentBorder
->GetComputedBorder().side(side
));
3799 else if (eCSSUnit_Initial
== value
.GetUnit()) {
3800 border
->SetBorderWidth(side
,
3801 (mPresContext
->GetBorderWidthTable())[NS_STYLE_BORDER_WIDTH_MEDIUM
]);
3804 NS_ASSERTION(eCSSUnit_Null
== value
.GetUnit(),
3805 "missing case handling border width");
3810 // border-style, border-*-style: enum, none, inherit
3811 nsCSSRect
ourStyle(marginData
.mBorderStyle
);
3812 AdjustLogicalBoxProp(aContext
,
3813 marginData
.mBorderLeftStyleLTRSource
,
3814 marginData
.mBorderLeftStyleRTLSource
,
3815 marginData
.mBorderStartStyle
, marginData
.mBorderEndStyle
,
3816 NS_SIDE_LEFT
, ourStyle
, inherited
);
3817 AdjustLogicalBoxProp(aContext
,
3818 marginData
.mBorderRightStyleLTRSource
,
3819 marginData
.mBorderRightStyleRTLSource
,
3820 marginData
.mBorderEndStyle
, marginData
.mBorderStartStyle
,
3821 NS_SIDE_RIGHT
, ourStyle
, inherited
);
3822 { // scope for compilers with broken |for| loop scoping
3823 NS_FOR_CSS_SIDES(side
) {
3824 const nsCSSValue
&value
= ourStyle
.*(nsCSSRect::sides
[side
]);
3825 nsCSSUnit unit
= value
.GetUnit();
3826 if (eCSSUnit_Enumerated
== unit
) {
3827 border
->SetBorderStyle(side
, value
.GetIntValue());
3829 else if (eCSSUnit_None
== unit
|| eCSSUnit_Initial
== unit
) {
3830 border
->SetBorderStyle(side
, NS_STYLE_BORDER_STYLE_NONE
);
3832 else if (eCSSUnit_Inherit
== unit
) {
3833 inherited
= PR_TRUE
;
3834 border
->SetBorderStyle(side
, parentBorder
->GetBorderStyle(side
));
3839 // -moz-border-*-colors: color, string, enum
3840 nscolor borderColor
;
3841 nscolor unused
= NS_RGB(0,0,0);
3843 { // scope for compilers with broken |for| loop scoping
3844 NS_FOR_CSS_SIDES(side
) {
3845 nsCSSValueList
* list
=
3846 marginData
.mBorderColors
.*(nsCSSValueListRect::sides
[side
]);
3847 // FIXME Bug 389404: Implement inherit and -moz-initial.
3849 // Some composite border color information has been specified for this
3851 border
->EnsureBorderColors();
3852 border
->ClearBorderColors(side
);
3854 if (SetColor(list
->mValue
, unused
, mPresContext
,
3855 aContext
, borderColor
, inherited
))
3856 border
->AppendBorderColor(side
, borderColor
);
3863 // border-color, border-*-color: color, string, enum, inherit
3864 nsCSSRect
ourBorderColor(marginData
.mBorderColor
);
3866 AdjustLogicalBoxProp(aContext
,
3867 marginData
.mBorderLeftColorLTRSource
,
3868 marginData
.mBorderLeftColorRTLSource
,
3869 marginData
.mBorderStartColor
, marginData
.mBorderEndColor
,
3870 NS_SIDE_LEFT
, ourBorderColor
, inherited
);
3871 AdjustLogicalBoxProp(aContext
,
3872 marginData
.mBorderRightColorLTRSource
,
3873 marginData
.mBorderRightColorRTLSource
,
3874 marginData
.mBorderEndColor
, marginData
.mBorderStartColor
,
3875 NS_SIDE_RIGHT
, ourBorderColor
, inherited
);
3876 { // scope for compilers with broken |for| loop scoping
3877 NS_FOR_CSS_SIDES(side
) {
3878 const nsCSSValue
&value
= ourBorderColor
.*(nsCSSRect::sides
[side
]);
3879 if (eCSSUnit_Inherit
== value
.GetUnit()) {
3880 if (parentContext
) {
3881 inherited
= PR_TRUE
;
3882 parentBorder
->GetBorderColor(side
, borderColor
, foreground
);
3884 // We want to inherit the color from the parent, not use the
3885 // color on the element where this chunk of style data will be
3886 // used. We can ensure that the data for the parent are fully
3887 // computed (unlike for the element where this will be used, for
3888 // which the color could be specified on a more specific rule).
3889 border
->SetBorderColor(side
, parentContext
->GetStyleColor()->mColor
);
3891 border
->SetBorderColor(side
, borderColor
);
3894 border
->SetBorderToForeground(side
);
3897 else if (SetColor(value
, unused
, mPresContext
, aContext
, borderColor
, inherited
)) {
3898 border
->SetBorderColor(side
, borderColor
);
3900 else if (eCSSUnit_Enumerated
== value
.GetUnit()) {
3901 switch (value
.GetIntValue()) {
3902 case NS_STYLE_COLOR_MOZ_USE_TEXT_COLOR
:
3903 border
->SetBorderToForeground(side
);
3907 else if (eCSSUnit_Initial
== value
.GetUnit()) {
3908 border
->SetBorderToForeground(side
);
3913 // -moz-border-radius: length, percent, inherit
3914 { // scope for compilers with broken |for| loop scoping
3915 NS_FOR_CSS_SIDES(side
) {
3916 nsStyleCoord parentCoord
= parentBorder
->mBorderRadius
.Get(side
);
3917 if (SetCoord(marginData
.mBorderRadius
.*(nsCSSRect::sides
[side
]), coord
,
3918 parentCoord
, SETCOORD_LPH
| SETCOORD_INITIAL_ZERO
,
3919 aContext
, mPresContext
, inherited
))
3920 border
->mBorderRadius
.Set(side
, coord
);
3924 // float-edge: enum, inherit, initial
3925 SetDiscrete(marginData
.mFloatEdge
, border
->mFloatEdge
, inherited
,
3926 SETDSC_ENUMERATED
, parentBorder
->mFloatEdge
,
3927 NS_STYLE_FLOAT_EDGE_CONTENT
, 0, 0, 0, 0);
3930 if (eCSSUnit_Array
== marginData
.mBorderImage
.GetUnit()) {
3931 nsCSSValue::Array
*arr
= marginData
.mBorderImage
.GetArrayValue();
3934 if (eCSSUnit_Image
== arr
->Item(0).GetUnit()) {
3935 border
->SetBorderImage(arr
->Item(0).GetImageValue());
3938 // the numbers saying where to split the image
3939 NS_FOR_CSS_SIDES(side
) {
3940 // an uninitialized parentCoord is ok because I'm not passing SETCOORD_INHERIT
3941 if (SetCoord(arr
->Item(1 + side
), coord
, nsStyleCoord(),
3942 SETCOORD_FACTOR
| SETCOORD_PERCENT
, aContext
,
3943 mPresContext
, inherited
)) {
3944 border
->mBorderImageSplit
.Set(side
, coord
);
3948 // possible replacement for border-width
3949 // if have one - have all four (see CSSParserImpl::ParseBorderImage())
3950 if (eCSSUnit_Null
!= arr
->Item(5).GetUnit()) {
3951 NS_FOR_CSS_SIDES(side
) {
3952 // an uninitialized parentCoord is ok because I'm not passing SETCOORD_INHERIT
3953 if (!SetCoord(arr
->Item(5 + side
), coord
, nsStyleCoord(),
3954 SETCOORD_LENGTH
, aContext
, mPresContext
, inherited
)) {
3955 NS_NOTREACHED("SetCoord for border-width replacement from border-image failed");
3957 if (coord
.GetUnit() == eStyleUnit_Coord
) {
3958 border
->SetBorderImageWidthOverride(side
, coord
.GetCoordValue());
3960 NS_WARNING("a border-width replacement from border-image "
3961 "has a unit that's not eStyleUnit_Coord");
3962 border
->SetBorderImageWidthOverride(side
, 0);
3965 border
->mHaveBorderImageWidth
= PR_TRUE
;
3967 border
->mHaveBorderImageWidth
= PR_FALSE
;
3970 // stretch/round/repeat keywords
3971 if (eCSSUnit_Null
== arr
->Item(9).GetUnit()) {
3972 // default, both horizontal and vertical are stretch
3973 border
->mBorderImageHFill
= NS_STYLE_BORDER_IMAGE_STRETCH
;
3974 border
->mBorderImageVFill
= NS_STYLE_BORDER_IMAGE_STRETCH
;
3976 // have horizontal value
3977 border
->mBorderImageHFill
= arr
->Item(9).GetIntValue();
3978 if (eCSSUnit_Null
== arr
->Item(10).GetUnit()) {
3979 // vertical same as horizontal
3980 border
->mBorderImageVFill
= border
->mBorderImageHFill
;
3982 // have vertical value
3983 border
->mBorderImageVFill
= arr
->Item(10).GetIntValue();
3986 } else if (eCSSUnit_None
== marginData
.mBorderImage
.GetUnit() ||
3987 eCSSUnit_Initial
== marginData
.mBorderImage
.GetUnit()) {
3988 border
->mHaveBorderImageWidth
= PR_FALSE
;
3989 border
->SetBorderImage(nsnull
);
3990 } else if (eCSSUnit_Inherit
== marginData
.mBorderImage
.GetUnit()) {
3991 NS_FOR_CSS_SIDES(side
) {
3992 border
->SetBorderImageWidthOverride(side
, parentBorder
->mBorderImageWidth
.side(side
));
3994 border
->mBorderImageSplit
= parentBorder
->mBorderImageSplit
;
3995 border
->mBorderImageHFill
= parentBorder
->mBorderImageHFill
;
3996 border
->mBorderImageVFill
= parentBorder
->mBorderImageVFill
;
3997 border
->mHaveBorderImageWidth
= parentBorder
->mHaveBorderImageWidth
;
3998 border
->SetBorderImage(parentBorder
->GetBorderImage());
4001 COMPUTE_END_RESET(Border
, border
)
4005 nsRuleNode::ComputePaddingData(void* aStartStruct
,
4006 const nsRuleDataStruct
& aData
,
4007 nsStyleContext
* aContext
,
4008 nsRuleNode
* aHighestNode
,
4009 const RuleDetail aRuleDetail
, PRBool aInherited
)
4011 COMPUTE_START_RESET(Padding
, (), padding
, parentPadding
, Margin
, marginData
)
4013 // padding: length, percent, inherit
4015 nsCSSRect
ourPadding(marginData
.mPadding
);
4016 AdjustLogicalBoxProp(aContext
,
4017 marginData
.mPaddingLeftLTRSource
,
4018 marginData
.mPaddingLeftRTLSource
,
4019 marginData
.mPaddingStart
, marginData
.mPaddingEnd
,
4020 NS_SIDE_LEFT
, ourPadding
, inherited
);
4021 AdjustLogicalBoxProp(aContext
,
4022 marginData
.mPaddingRightLTRSource
,
4023 marginData
.mPaddingRightRTLSource
,
4024 marginData
.mPaddingEnd
, marginData
.mPaddingStart
,
4025 NS_SIDE_RIGHT
, ourPadding
, inherited
);
4026 NS_FOR_CSS_SIDES(side
) {
4027 nsStyleCoord parentCoord
= parentPadding
->mPadding
.Get(side
);
4028 if (SetCoord(ourPadding
.*(nsCSSRect::sides
[side
]),
4029 coord
, parentCoord
, SETCOORD_LPH
| SETCOORD_INITIAL_ZERO
,
4030 aContext
, mPresContext
, inherited
)) {
4031 padding
->mPadding
.Set(side
, coord
);
4035 padding
->RecalcData();
4036 COMPUTE_END_RESET(Padding
, padding
)
4040 nsRuleNode::ComputeOutlineData(void* aStartStruct
,
4041 const nsRuleDataStruct
& aData
,
4042 nsStyleContext
* aContext
,
4043 nsRuleNode
* aHighestNode
,
4044 const RuleDetail aRuleDetail
, PRBool aInherited
)
4046 COMPUTE_START_RESET(Outline
, (mPresContext
), outline
, parentOutline
,
4049 // outline-width: length, enum, inherit
4050 if (eCSSUnit_Initial
== marginData
.mOutlineWidth
.GetUnit()) {
4051 outline
->mOutlineWidth
=
4052 nsStyleCoord(NS_STYLE_BORDER_WIDTH_MEDIUM
, eStyleUnit_Enumerated
);
4055 SetCoord(marginData
.mOutlineWidth
, outline
->mOutlineWidth
,
4056 parentOutline
->mOutlineWidth
, SETCOORD_LEH
, aContext
,
4057 mPresContext
, inherited
);
4060 // outline-offset: length, inherit
4061 nsStyleCoord tempCoord
;
4062 if (SetCoord(marginData
.mOutlineOffset
, tempCoord
,
4063 parentOutline
->mOutlineOffset
,
4064 SETCOORD_LH
| SETCOORD_INITIAL_ZERO
, aContext
, mPresContext
,
4066 outline
->mOutlineOffset
= tempCoord
.GetCoordValue();
4068 NS_ASSERTION(marginData
.mOutlineOffset
.GetUnit() == eCSSUnit_Null
,
4072 // outline-color: color, string, enum, inherit
4073 nscolor outlineColor
;
4074 nscolor unused
= NS_RGB(0,0,0);
4075 if (eCSSUnit_Inherit
== marginData
.mOutlineColor
.GetUnit()) {
4076 if (parentContext
) {
4077 inherited
= PR_TRUE
;
4078 if (parentOutline
->GetOutlineColor(outlineColor
))
4079 outline
->SetOutlineColor(outlineColor
);
4081 #ifdef GFX_HAS_INVERT
4082 outline
->SetOutlineInitialColor();
4084 // We want to inherit the color from the parent, not use the
4085 // color on the element where this chunk of style data will be
4086 // used. We can ensure that the data for the parent are fully
4087 // computed (unlike for the element where this will be used, for
4088 // which the color could be specified on a more specific rule).
4089 outline
->SetOutlineColor(parentContext
->GetStyleColor()->mColor
);
4093 outline
->SetOutlineInitialColor();
4096 else if (SetColor(marginData
.mOutlineColor
, unused
, mPresContext
, aContext
, outlineColor
, inherited
))
4097 outline
->SetOutlineColor(outlineColor
);
4098 else if (eCSSUnit_Enumerated
== marginData
.mOutlineColor
.GetUnit() ||
4099 eCSSUnit_Initial
== marginData
.mOutlineColor
.GetUnit()) {
4100 outline
->SetOutlineInitialColor();
4103 // -moz-outline-radius: length, percent, inherit
4105 { // scope for compilers with broken |for| loop scoping
4106 NS_FOR_CSS_SIDES(side
) {
4107 nsStyleCoord parentCoord
= parentOutline
->mOutlineRadius
.Get(side
);
4108 if (SetCoord(marginData
.mOutlineRadius
.*(nsCSSRect::sides
[side
]), coord
,
4109 parentCoord
, SETCOORD_LPH
| SETCOORD_INITIAL_ZERO
,
4110 aContext
, mPresContext
, inherited
))
4111 outline
->mOutlineRadius
.Set(side
, coord
);
4115 // outline-style: auto, enum, none, inherit, initial
4116 // cannot use SetDiscrete because of SetOutlineStyle
4117 if (eCSSUnit_Enumerated
== marginData
.mOutlineStyle
.GetUnit())
4118 outline
->SetOutlineStyle(marginData
.mOutlineStyle
.GetIntValue());
4119 else if (eCSSUnit_None
== marginData
.mOutlineStyle
.GetUnit() ||
4120 eCSSUnit_Initial
== marginData
.mOutlineStyle
.GetUnit())
4121 outline
->SetOutlineStyle(NS_STYLE_BORDER_STYLE_NONE
);
4122 else if (eCSSUnit_Auto
== marginData
.mOutlineStyle
.GetUnit()) {
4123 outline
->SetOutlineStyle(NS_STYLE_BORDER_STYLE_AUTO
);
4124 } else if (eCSSUnit_Inherit
== marginData
.mOutlineStyle
.GetUnit()) {
4125 inherited
= PR_TRUE
;
4126 outline
->SetOutlineStyle(parentOutline
->GetOutlineStyle());
4129 outline
->RecalcData(mPresContext
);
4130 COMPUTE_END_RESET(Outline
, outline
)
4134 nsRuleNode::ComputeListData(void* aStartStruct
,
4135 const nsRuleDataStruct
& aData
,
4136 nsStyleContext
* aContext
,
4137 nsRuleNode
* aHighestNode
,
4138 const RuleDetail aRuleDetail
, PRBool aInherited
)
4140 COMPUTE_START_INHERITED(List
, (), list
, parentList
, List
, listData
)
4142 // list-style-type: enum, none, inherit, initial
4143 SetDiscrete(listData
.mType
, list
->mListStyleType
, inherited
,
4144 SETDSC_ENUMERATED
| SETDSC_NONE
, parentList
->mListStyleType
,
4145 NS_STYLE_LIST_STYLE_DISC
, 0,
4146 NS_STYLE_LIST_STYLE_NONE
, 0, 0);
4148 // list-style-image: url, none, inherit
4149 if (eCSSUnit_Image
== listData
.mImage
.GetUnit()) {
4150 list
->mListStyleImage
= listData
.mImage
.GetImageValue();
4152 else if (eCSSUnit_None
== listData
.mImage
.GetUnit() ||
4153 eCSSUnit_Initial
== listData
.mImage
.GetUnit()) {
4154 list
->mListStyleImage
= nsnull
;
4156 else if (eCSSUnit_Inherit
== listData
.mImage
.GetUnit()) {
4157 inherited
= PR_TRUE
;
4158 list
->mListStyleImage
= parentList
->mListStyleImage
;
4161 // list-style-position: enum, inherit, initial
4162 SetDiscrete(listData
.mPosition
, list
->mListStylePosition
, inherited
,
4163 SETDSC_ENUMERATED
, parentList
->mListStylePosition
,
4164 NS_STYLE_LIST_STYLE_POSITION_OUTSIDE
, 0, 0, 0, 0);
4166 // image region property: length, auto, inherit
4167 if (eCSSUnit_Inherit
== listData
.mImageRegion
.mTop
.GetUnit()) { // if one is inherit, they all are
4168 inherited
= PR_TRUE
;
4169 list
->mImageRegion
= parentList
->mImageRegion
;
4171 // if one is -moz-initial, they all are
4172 else if (eCSSUnit_Initial
== listData
.mImageRegion
.mTop
.GetUnit()) {
4173 list
->mImageRegion
.Empty();
4176 if (eCSSUnit_Auto
== listData
.mImageRegion
.mTop
.GetUnit())
4177 list
->mImageRegion
.y
= 0;
4178 else if (listData
.mImageRegion
.mTop
.IsLengthUnit())
4179 list
->mImageRegion
.y
= CalcLength(listData
.mImageRegion
.mTop
, aContext
, mPresContext
, inherited
);
4181 if (eCSSUnit_Auto
== listData
.mImageRegion
.mBottom
.GetUnit())
4182 list
->mImageRegion
.height
= 0;
4183 else if (listData
.mImageRegion
.mBottom
.IsLengthUnit())
4184 list
->mImageRegion
.height
= CalcLength(listData
.mImageRegion
.mBottom
, aContext
,
4185 mPresContext
, inherited
) - list
->mImageRegion
.y
;
4187 if (eCSSUnit_Auto
== listData
.mImageRegion
.mLeft
.GetUnit())
4188 list
->mImageRegion
.x
= 0;
4189 else if (listData
.mImageRegion
.mLeft
.IsLengthUnit())
4190 list
->mImageRegion
.x
= CalcLength(listData
.mImageRegion
.mLeft
, aContext
, mPresContext
, inherited
);
4192 if (eCSSUnit_Auto
== listData
.mImageRegion
.mRight
.GetUnit())
4193 list
->mImageRegion
.width
= 0;
4194 else if (listData
.mImageRegion
.mRight
.IsLengthUnit())
4195 list
->mImageRegion
.width
= CalcLength(listData
.mImageRegion
.mRight
, aContext
, mPresContext
, inherited
) -
4196 list
->mImageRegion
.x
;
4199 COMPUTE_END_INHERITED(List
, list
)
4203 nsRuleNode::ComputePositionData(void* aStartStruct
,
4204 const nsRuleDataStruct
& aData
,
4205 nsStyleContext
* aContext
,
4206 nsRuleNode
* aHighestNode
,
4207 const RuleDetail aRuleDetail
, PRBool aInherited
)
4209 COMPUTE_START_RESET(Position
, (), pos
, parentPos
, Position
, posData
)
4211 // box offsets: length, percent, auto, inherit
4213 NS_FOR_CSS_SIDES(side
) {
4214 nsStyleCoord parentCoord
= parentPos
->mOffset
.Get(side
);
4215 if (SetCoord(posData
.mOffset
.*(nsCSSRect::sides
[side
]),
4216 coord
, parentCoord
, SETCOORD_LPAH
| SETCOORD_INITIAL_AUTO
,
4217 aContext
, mPresContext
, inherited
)) {
4218 pos
->mOffset
.Set(side
, coord
);
4222 SetCoord(posData
.mWidth
, pos
->mWidth
, parentPos
->mWidth
,
4223 SETCOORD_LPAEH
| SETCOORD_INITIAL_AUTO
, aContext
,
4224 mPresContext
, inherited
);
4225 SetCoord(posData
.mMinWidth
, pos
->mMinWidth
, parentPos
->mMinWidth
,
4226 SETCOORD_LPEH
| SETCOORD_INITIAL_ZERO
, aContext
,
4227 mPresContext
, inherited
);
4228 SetCoord(posData
.mMaxWidth
, pos
->mMaxWidth
, parentPos
->mMaxWidth
,
4229 SETCOORD_LPOEH
| SETCOORD_INITIAL_NONE
, aContext
,
4230 mPresContext
, inherited
);
4232 SetCoord(posData
.mHeight
, pos
->mHeight
, parentPos
->mHeight
,
4233 SETCOORD_LPAH
| SETCOORD_INITIAL_AUTO
, aContext
,
4234 mPresContext
, inherited
);
4235 SetCoord(posData
.mMinHeight
, pos
->mMinHeight
, parentPos
->mMinHeight
,
4236 SETCOORD_LPH
| SETCOORD_INITIAL_ZERO
, aContext
,
4237 mPresContext
, inherited
);
4238 SetCoord(posData
.mMaxHeight
, pos
->mMaxHeight
, parentPos
->mMaxHeight
,
4239 SETCOORD_LPOH
| SETCOORD_INITIAL_NONE
, aContext
,
4240 mPresContext
, inherited
);
4242 // box-sizing: enum, inherit, initial
4243 SetDiscrete(posData
.mBoxSizing
, pos
->mBoxSizing
, inherited
,
4244 SETDSC_ENUMERATED
, parentPos
->mBoxSizing
,
4245 NS_STYLE_BOX_SIZING_CONTENT
, 0, 0, 0, 0);
4248 if (! SetCoord(posData
.mZIndex
, pos
->mZIndex
, parentPos
->mZIndex
,
4249 SETCOORD_IA
| SETCOORD_INITIAL_AUTO
, aContext
,
4250 nsnull
, inherited
)) {
4251 if (eCSSUnit_Inherit
== posData
.mZIndex
.GetUnit()) {
4252 // handle inherit, because it's ok to inherit 'auto' here
4253 inherited
= PR_TRUE
;
4254 pos
->mZIndex
= parentPos
->mZIndex
;
4258 COMPUTE_END_RESET(Position
, pos
)
4262 nsRuleNode::ComputeTableData(void* aStartStruct
,
4263 const nsRuleDataStruct
& aData
,
4264 nsStyleContext
* aContext
,
4265 nsRuleNode
* aHighestNode
,
4266 const RuleDetail aRuleDetail
, PRBool aInherited
)
4268 COMPUTE_START_RESET(Table
, (), table
, parentTable
, Table
, tableData
)
4270 // table-layout: auto, enum, inherit, initial
4271 SetDiscrete(tableData
.mLayout
, table
->mLayoutStrategy
, inherited
,
4272 SETDSC_ENUMERATED
| SETDSC_AUTO
,
4273 parentTable
->mLayoutStrategy
,
4274 NS_STYLE_TABLE_LAYOUT_AUTO
,
4275 NS_STYLE_TABLE_LAYOUT_AUTO
, 0, 0, 0);
4277 // rules: enum (not a real CSS prop)
4278 if (eCSSUnit_Enumerated
== tableData
.mRules
.GetUnit())
4279 table
->mRules
= tableData
.mRules
.GetIntValue();
4281 // frame: enum (not a real CSS prop)
4282 if (eCSSUnit_Enumerated
== tableData
.mFrame
.GetUnit())
4283 table
->mFrame
= tableData
.mFrame
.GetIntValue();
4285 // cols: enum, int (not a real CSS prop)
4286 if (eCSSUnit_Enumerated
== tableData
.mCols
.GetUnit() ||
4287 eCSSUnit_Integer
== tableData
.mCols
.GetUnit())
4288 table
->mCols
= tableData
.mCols
.GetIntValue();
4290 // span: pixels (not a real CSS prop)
4291 if (eCSSUnit_Enumerated
== tableData
.mSpan
.GetUnit() ||
4292 eCSSUnit_Integer
== tableData
.mSpan
.GetUnit())
4293 table
->mSpan
= tableData
.mSpan
.GetIntValue();
4295 COMPUTE_END_RESET(Table
, table
)
4299 nsRuleNode::ComputeTableBorderData(void* aStartStruct
,
4300 const nsRuleDataStruct
& aData
,
4301 nsStyleContext
* aContext
,
4302 nsRuleNode
* aHighestNode
,
4303 const RuleDetail aRuleDetail
, PRBool aInherited
)
4305 COMPUTE_START_INHERITED(TableBorder
, (mPresContext
), table
, parentTable
,
4308 // border-collapse: enum, inherit, initial
4309 SetDiscrete(tableData
.mBorderCollapse
, table
->mBorderCollapse
, inherited
,
4310 SETDSC_ENUMERATED
, parentTable
->mBorderCollapse
,
4311 NS_STYLE_BORDER_SEPARATE
, 0, 0, 0, 0);
4313 // border-spacing-x: length, inherit
4314 nsStyleCoord tempCoord
;
4315 if (SetCoord(tableData
.mBorderSpacing
.mXValue
, tempCoord
,
4316 parentTable
->mBorderSpacingX
,
4317 SETCOORD_LH
| SETCOORD_INITIAL_ZERO
,
4318 aContext
, mPresContext
, inherited
)) {
4319 table
->mBorderSpacingX
= tempCoord
.GetCoordValue();
4321 NS_ASSERTION(tableData
.mBorderSpacing
.mXValue
.GetUnit() == eCSSUnit_Null
,
4325 // border-spacing-y: length, inherit
4326 if (SetCoord(tableData
.mBorderSpacing
.mYValue
, tempCoord
,
4327 parentTable
->mBorderSpacingY
,
4328 SETCOORD_LH
| SETCOORD_INITIAL_ZERO
,
4329 aContext
, mPresContext
, inherited
)) {
4330 table
->mBorderSpacingY
= tempCoord
.GetCoordValue();
4332 NS_ASSERTION(tableData
.mBorderSpacing
.mYValue
.GetUnit() == eCSSUnit_Null
,
4336 // caption-side: enum, inherit, initial
4337 SetDiscrete(tableData
.mCaptionSide
, table
->mCaptionSide
, inherited
,
4338 SETDSC_ENUMERATED
, parentTable
->mCaptionSide
,
4339 NS_STYLE_CAPTION_SIDE_TOP
, 0, 0, 0, 0);
4341 // empty-cells: enum, inherit, initial
4342 SetDiscrete(tableData
.mEmptyCells
, table
->mEmptyCells
, inherited
,
4343 SETDSC_ENUMERATED
, parentTable
->mEmptyCells
,
4344 (mPresContext
->CompatibilityMode() == eCompatibility_NavQuirks
)
4345 ? NS_STYLE_TABLE_EMPTY_CELLS_SHOW_BACKGROUND
4346 : NS_STYLE_TABLE_EMPTY_CELLS_SHOW
,
4349 COMPUTE_END_INHERITED(TableBorder
, table
)
4353 nsRuleNode::ComputeContentData(void* aStartStruct
,
4354 const nsRuleDataStruct
& aData
,
4355 nsStyleContext
* aContext
,
4356 nsRuleNode
* aHighestNode
,
4357 const RuleDetail aRuleDetail
, PRBool aInherited
)
4359 COMPUTE_START_RESET(Content
, (), content
, parentContent
,
4360 Content
, contentData
)
4362 // content: [string, url, counter, attr, enum]+, normal, none, inherit
4364 nsAutoString buffer
;
4365 nsCSSValueList
* contentValue
= contentData
.mContent
;
4367 if (eCSSUnit_Normal
== contentValue
->mValue
.GetUnit() ||
4368 eCSSUnit_None
== contentValue
->mValue
.GetUnit() ||
4369 eCSSUnit_Initial
== contentValue
->mValue
.GetUnit()) {
4370 // "normal", "none", and "initial" all mean no content
4371 content
->AllocateContents(0);
4373 else if (eCSSUnit_Inherit
== contentValue
->mValue
.GetUnit()) {
4374 inherited
= PR_TRUE
;
4375 count
= parentContent
->ContentCount();
4376 if (NS_SUCCEEDED(content
->AllocateContents(count
))) {
4377 while (0 < count
--) {
4378 content
->ContentAt(count
) = parentContent
->ContentAt(count
);
4384 while (contentValue
) {
4386 contentValue
= contentValue
->mNext
;
4388 if (NS_SUCCEEDED(content
->AllocateContents(count
))) {
4389 const nsAutoString nullStr
;
4391 contentValue
= contentData
.mContent
;
4392 while (contentValue
) {
4393 const nsCSSValue
& value
= contentValue
->mValue
;
4394 nsCSSUnit unit
= value
.GetUnit();
4395 nsStyleContentType type
;
4396 nsStyleContentData
&data
= content
->ContentAt(count
++);
4398 case eCSSUnit_String
: type
= eStyleContentType_String
; break;
4399 case eCSSUnit_Image
: type
= eStyleContentType_Image
; break;
4400 case eCSSUnit_Attr
: type
= eStyleContentType_Attr
; break;
4401 case eCSSUnit_Counter
: type
= eStyleContentType_Counter
; break;
4402 case eCSSUnit_Counters
: type
= eStyleContentType_Counters
; break;
4403 case eCSSUnit_Enumerated
:
4404 switch (value
.GetIntValue()) {
4405 case NS_STYLE_CONTENT_OPEN_QUOTE
:
4406 type
= eStyleContentType_OpenQuote
; break;
4407 case NS_STYLE_CONTENT_CLOSE_QUOTE
:
4408 type
= eStyleContentType_CloseQuote
; break;
4409 case NS_STYLE_CONTENT_NO_OPEN_QUOTE
:
4410 type
= eStyleContentType_NoOpenQuote
; break;
4411 case NS_STYLE_CONTENT_NO_CLOSE_QUOTE
:
4412 type
= eStyleContentType_NoCloseQuote
; break;
4413 case NS_STYLE_CONTENT_ALT_CONTENT
:
4414 type
= eStyleContentType_AltContent
; break;
4416 NS_ERROR("bad content value");
4420 NS_ERROR("bad content type");
4423 if (type
== eStyleContentType_Image
) {
4424 data
.mContent
.mImage
= value
.GetImageValue();
4425 NS_IF_ADDREF(data
.mContent
.mImage
);
4427 else if (type
<= eStyleContentType_Attr
) {
4428 value
.GetStringValue(buffer
);
4430 data
.mContent
.mString
= NS_strdup(buffer
.get());
4432 else if (type
<= eStyleContentType_Counters
) {
4433 data
.mContent
.mCounters
= value
.GetArrayValue();
4434 data
.mContent
.mCounters
->AddRef();
4437 data
.mContent
.mString
= nsnull
;
4439 contentValue
= contentValue
->mNext
;
4445 // counter-increment: [string [int]]+, none, inherit
4446 nsCSSValuePairList
* ourIncrement
= contentData
.mCounterIncrement
;
4448 if (eCSSUnit_None
== ourIncrement
->mXValue
.GetUnit() ||
4449 eCSSUnit_Initial
== ourIncrement
->mXValue
.GetUnit()) {
4450 content
->AllocateCounterIncrements(0);
4452 else if (eCSSUnit_Inherit
== ourIncrement
->mXValue
.GetUnit()) {
4453 inherited
= PR_TRUE
;
4454 count
= parentContent
->CounterIncrementCount();
4455 if (NS_SUCCEEDED(content
->AllocateCounterIncrements(count
))) {
4456 while (0 < count
--) {
4457 const nsStyleCounterData
*data
=
4458 parentContent
->GetCounterIncrementAt(count
);
4459 content
->SetCounterIncrementAt(count
, data
->mCounter
, data
->mValue
);
4463 else if (eCSSUnit_String
== ourIncrement
->mXValue
.GetUnit()) {
4465 while (ourIncrement
) {
4467 ourIncrement
= ourIncrement
->mNext
;
4469 if (NS_SUCCEEDED(content
->AllocateCounterIncrements(count
))) {
4471 ourIncrement
= contentData
.mCounterIncrement
;
4472 while (ourIncrement
) {
4474 if (eCSSUnit_Integer
== ourIncrement
->mYValue
.GetUnit()) {
4475 increment
= ourIncrement
->mYValue
.GetIntValue();
4480 ourIncrement
->mXValue
.GetStringValue(buffer
);
4481 content
->SetCounterIncrementAt(count
++, buffer
, increment
);
4482 ourIncrement
= ourIncrement
->mNext
;
4488 // counter-reset: [string [int]]+, none, inherit
4489 nsCSSValuePairList
* ourReset
= contentData
.mCounterReset
;
4491 if (eCSSUnit_None
== ourReset
->mXValue
.GetUnit() ||
4492 eCSSUnit_Initial
== ourReset
->mXValue
.GetUnit()) {
4493 content
->AllocateCounterResets(0);
4495 else if (eCSSUnit_Inherit
== ourReset
->mXValue
.GetUnit()) {
4496 inherited
= PR_TRUE
;
4497 count
= parentContent
->CounterResetCount();
4498 if (NS_SUCCEEDED(content
->AllocateCounterResets(count
))) {
4499 while (0 < count
--) {
4500 const nsStyleCounterData
*data
=
4501 parentContent
->GetCounterResetAt(count
);
4502 content
->SetCounterResetAt(count
, data
->mCounter
, data
->mValue
);
4506 else if (eCSSUnit_String
== ourReset
->mXValue
.GetUnit()) {
4510 ourReset
= ourReset
->mNext
;
4512 if (NS_SUCCEEDED(content
->AllocateCounterResets(count
))) {
4514 ourReset
= contentData
.mCounterReset
;
4517 if (eCSSUnit_Integer
== ourReset
->mYValue
.GetUnit()) {
4518 reset
= ourReset
->mYValue
.GetIntValue();
4523 ourReset
->mXValue
.GetStringValue(buffer
);
4524 content
->SetCounterResetAt(count
++, buffer
, reset
);
4525 ourReset
= ourReset
->mNext
;
4531 // marker-offset: length, auto, inherit
4532 SetCoord(contentData
.mMarkerOffset
, content
->mMarkerOffset
, parentContent
->mMarkerOffset
,
4533 SETCOORD_LH
| SETCOORD_AUTO
| SETCOORD_INITIAL_AUTO
, aContext
,
4534 mPresContext
, inherited
);
4536 COMPUTE_END_RESET(Content
, content
)
4540 nsRuleNode::ComputeQuotesData(void* aStartStruct
,
4541 const nsRuleDataStruct
& aData
,
4542 nsStyleContext
* aContext
,
4543 nsRuleNode
* aHighestNode
,
4544 const RuleDetail aRuleDetail
, PRBool aInherited
)
4546 COMPUTE_START_INHERITED(Quotes
, (), quotes
, parentQuotes
,
4547 Content
, contentData
)
4549 // quotes: inherit, initial, none, [string string]+
4550 nsCSSValuePairList
* ourQuotes
= contentData
.mQuotes
;
4552 if (eCSSUnit_Inherit
== ourQuotes
->mXValue
.GetUnit()) {
4553 inherited
= PR_TRUE
;
4554 quotes
->CopyFrom(*parentQuotes
);
4556 else if (eCSSUnit_Initial
== ourQuotes
->mXValue
.GetUnit()) {
4557 quotes
->SetInitial();
4559 else if (eCSSUnit_None
== ourQuotes
->mXValue
.GetUnit()) {
4560 quotes
->AllocateQuotes(0);
4562 else if (eCSSUnit_String
== ourQuotes
->mXValue
.GetUnit()) {
4563 nsAutoString buffer
;
4564 nsAutoString closeBuffer
;
4569 ourQuotes
= ourQuotes
->mNext
;
4571 if (NS_SUCCEEDED(quotes
->AllocateQuotes(count
))) {
4573 ourQuotes
= contentData
.mQuotes
;
4575 ourQuotes
->mXValue
.GetStringValue(buffer
);
4576 ourQuotes
->mYValue
.GetStringValue(closeBuffer
);
4578 Unquote(closeBuffer
);
4579 quotes
->SetQuotesAt(count
++, buffer
, closeBuffer
);
4580 ourQuotes
= ourQuotes
->mNext
;
4586 COMPUTE_END_INHERITED(Quotes
, quotes
)
4590 nsRuleNode::ComputeXULData(void* aStartStruct
,
4591 const nsRuleDataStruct
& aData
,
4592 nsStyleContext
* aContext
,
4593 nsRuleNode
* aHighestNode
,
4594 const RuleDetail aRuleDetail
, PRBool aInherited
)
4596 COMPUTE_START_RESET(XUL
, (), xul
, parentXUL
, XUL
, xulData
)
4598 // box-align: enum, inherit, initial
4599 SetDiscrete(xulData
.mBoxAlign
, xul
->mBoxAlign
, inherited
,
4600 SETDSC_ENUMERATED
, parentXUL
->mBoxAlign
,
4601 NS_STYLE_BOX_ALIGN_STRETCH
, 0, 0, 0, 0);
4603 // box-direction: enum, inherit, initial
4604 SetDiscrete(xulData
.mBoxDirection
, xul
->mBoxDirection
, inherited
,
4605 SETDSC_ENUMERATED
, parentXUL
->mBoxDirection
,
4606 NS_STYLE_BOX_DIRECTION_NORMAL
, 0, 0, 0, 0);
4608 // box-flex: factor, inherit
4609 SetFactor(xulData
.mBoxFlex
, xul
->mBoxFlex
, inherited
,
4610 parentXUL
->mBoxFlex
, 0.0f
);
4612 // box-orient: enum, inherit, initial
4613 SetDiscrete(xulData
.mBoxOrient
, xul
->mBoxOrient
, inherited
,
4614 SETDSC_ENUMERATED
, parentXUL
->mBoxOrient
,
4615 NS_STYLE_BOX_ORIENT_HORIZONTAL
, 0, 0, 0, 0);
4617 // box-pack: enum, inherit, initial
4618 SetDiscrete(xulData
.mBoxPack
, xul
->mBoxPack
, inherited
,
4619 SETDSC_ENUMERATED
, parentXUL
->mBoxPack
,
4620 NS_STYLE_BOX_PACK_START
, 0, 0, 0, 0);
4622 // box-ordinal-group: integer, inherit, initial
4623 SetDiscrete(xulData
.mBoxOrdinal
, xul
->mBoxOrdinal
, inherited
,
4624 SETDSC_INTEGER
, parentXUL
->mBoxOrdinal
, 1,
4627 if (eCSSUnit_Inherit
== xulData
.mStackSizing
.GetUnit()) {
4628 inherited
= PR_TRUE
;
4629 xul
->mStretchStack
= parentXUL
->mStretchStack
;
4630 } else if (eCSSUnit_Initial
== xulData
.mStackSizing
.GetUnit()) {
4631 xul
->mStretchStack
= PR_TRUE
;
4632 } else if (eCSSUnit_Enumerated
== xulData
.mStackSizing
.GetUnit()) {
4633 xul
->mStretchStack
= xulData
.mStackSizing
.GetIntValue() ==
4634 NS_STYLE_STACK_SIZING_STRETCH_TO_FIT
;
4637 COMPUTE_END_RESET(XUL
, xul
)
4641 nsRuleNode::ComputeColumnData(void* aStartStruct
,
4642 const nsRuleDataStruct
& aData
,
4643 nsStyleContext
* aContext
,
4644 nsRuleNode
* aHighestNode
,
4645 const RuleDetail aRuleDetail
, PRBool aInherited
)
4647 COMPUTE_START_RESET(Column
, (mPresContext
), column
, parent
, Column
, columnData
)
4649 // column-width: length, auto, inherit
4650 SetCoord(columnData
.mColumnWidth
,
4651 column
->mColumnWidth
, parent
->mColumnWidth
,
4652 SETCOORD_LAH
| SETCOORD_INITIAL_AUTO
,
4653 aContext
, mPresContext
, inherited
);
4655 // column-gap: length, percentage, inherit, normal
4656 SetCoord(columnData
.mColumnGap
,
4657 column
->mColumnGap
, parent
->mColumnGap
,
4658 SETCOORD_LPH
| SETCOORD_NORMAL
| SETCOORD_INITIAL_NORMAL
,
4659 aContext
, mPresContext
, inherited
);
4661 // column-count: auto, integer, inherit
4662 if (eCSSUnit_Auto
== columnData
.mColumnCount
.GetUnit() ||
4663 eCSSUnit_Initial
== columnData
.mColumnCount
.GetUnit()) {
4664 column
->mColumnCount
= NS_STYLE_COLUMN_COUNT_AUTO
;
4665 } else if (eCSSUnit_Integer
== columnData
.mColumnCount
.GetUnit()) {
4666 column
->mColumnCount
= columnData
.mColumnCount
.GetIntValue();
4667 // Max 1000 columns - wallpaper for bug 345583.
4668 column
->mColumnCount
= PR_MIN(column
->mColumnCount
, 1000);
4669 } else if (eCSSUnit_Inherit
== columnData
.mColumnCount
.GetUnit()) {
4670 inherited
= PR_TRUE
;
4671 column
->mColumnCount
= parent
->mColumnCount
;
4674 // column-rule-width: length, enum, inherit
4675 const nsCSSValue
& widthValue
= columnData
.mColumnRuleWidth
;
4676 if (eCSSUnit_Initial
== widthValue
.GetUnit()) {
4677 column
->SetColumnRuleWidth(
4678 (mPresContext
->GetBorderWidthTable())[NS_STYLE_BORDER_WIDTH_MEDIUM
]);
4680 else if (eCSSUnit_Enumerated
== widthValue
.GetUnit()) {
4681 NS_ASSERTION(widthValue
.GetIntValue() == NS_STYLE_BORDER_WIDTH_THIN
||
4682 widthValue
.GetIntValue() == NS_STYLE_BORDER_WIDTH_MEDIUM
||
4683 widthValue
.GetIntValue() == NS_STYLE_BORDER_WIDTH_THICK
,
4684 "Unexpected enum value");
4685 column
->SetColumnRuleWidth(
4686 (mPresContext
->GetBorderWidthTable())[widthValue
.GetIntValue()]);
4688 else if (eCSSUnit_Inherit
== widthValue
.GetUnit()) {
4689 column
->SetColumnRuleWidth(parent
->GetComputedColumnRuleWidth());
4690 inherited
= PR_TRUE
;
4692 else if (widthValue
.IsLengthUnit()) {
4693 column
->SetColumnRuleWidth(CalcLength(widthValue
, aContext
,
4694 mPresContext
, inherited
));
4697 // column-rule-style: enum, none, inherit
4698 const nsCSSValue
& styleValue
= columnData
.mColumnRuleStyle
;
4699 if (eCSSUnit_Enumerated
== styleValue
.GetUnit()) {
4700 column
->mColumnRuleStyle
= styleValue
.GetIntValue();
4702 else if (eCSSUnit_None
== styleValue
.GetUnit() ||
4703 eCSSUnit_Initial
== styleValue
.GetUnit()) {
4704 column
->mColumnRuleStyle
= NS_STYLE_BORDER_STYLE_NONE
;
4706 else if (eCSSUnit_Inherit
== styleValue
.GetUnit()) {
4707 inherited
= PR_TRUE
;
4708 column
->mColumnRuleStyle
= parent
->mColumnRuleStyle
;
4711 // column-rule-color: color, inherit
4712 const nsCSSValue
& colorValue
= columnData
.mColumnRuleColor
;
4713 if (eCSSUnit_Inherit
== colorValue
.GetUnit()) {
4714 inherited
= PR_TRUE
;
4715 column
->mColumnRuleColorIsForeground
= PR_FALSE
;
4716 if (parent
->mColumnRuleColorIsForeground
) {
4717 column
->mColumnRuleColor
= parentContext
->GetStyleColor()->mColor
;
4719 column
->mColumnRuleColor
= parent
->mColumnRuleColor
;
4722 else if (eCSSUnit_Initial
== colorValue
.GetUnit()) {
4723 column
->mColumnRuleColorIsForeground
= PR_TRUE
;
4725 else if (SetColor(colorValue
, 0, mPresContext
, aContext
, column
->mColumnRuleColor
, inherited
)) {
4726 column
->mColumnRuleColorIsForeground
= PR_FALSE
;
4729 COMPUTE_END_RESET(Column
, column
)
4734 SetSVGPaint(const nsCSSValuePair
& aValue
, const nsStyleSVGPaint
& parentPaint
,
4735 nsPresContext
* aPresContext
, nsStyleContext
*aContext
,
4736 nsStyleSVGPaint
& aResult
, nsStyleSVGPaintType aInitialPaintType
,
4741 if (aValue
.mXValue
.GetUnit() == eCSSUnit_Inherit
) {
4742 aResult
= parentPaint
;
4743 aInherited
= PR_TRUE
;
4744 } else if (aValue
.mXValue
.GetUnit() == eCSSUnit_None
) {
4745 aResult
.SetType(eStyleSVGPaintType_None
);
4746 } else if (aValue
.mXValue
.GetUnit() == eCSSUnit_Initial
) {
4747 aResult
.SetType(aInitialPaintType
);
4748 aResult
.mPaint
.mColor
= NS_RGB(0, 0, 0);
4749 aResult
.mFallbackColor
= NS_RGB(0, 0, 0);
4750 } else if (aValue
.mXValue
.GetUnit() == eCSSUnit_URL
) {
4751 aResult
.SetType(eStyleSVGPaintType_Server
);
4752 aResult
.mPaint
.mPaintServer
= aValue
.mXValue
.GetURLValue();
4753 NS_IF_ADDREF(aResult
.mPaint
.mPaintServer
);
4754 if (aValue
.mYValue
.GetUnit() == eCSSUnit_None
) {
4755 aResult
.mFallbackColor
= NS_RGBA(0, 0, 0, 0);
4757 NS_ASSERTION(aValue
.mYValue
.GetUnit() != eCSSUnit_Inherit
, "cannot inherit fallback colour");
4758 SetColor(aValue
.mYValue
, NS_RGB(0, 0, 0), aPresContext
, aContext
, aResult
.mFallbackColor
, aInherited
);
4760 } else if (SetColor(aValue
.mXValue
, parentPaint
.mPaint
.mColor
, aPresContext
, aContext
, color
, aInherited
)) {
4761 aResult
.SetType(eStyleSVGPaintType_Color
);
4762 aResult
.mPaint
.mColor
= color
;
4767 nsRuleNode::ComputeSVGData(void* aStartStruct
,
4768 const nsRuleDataStruct
& aData
,
4769 nsStyleContext
* aContext
,
4770 nsRuleNode
* aHighestNode
,
4771 const RuleDetail aRuleDetail
, PRBool aInherited
)
4773 COMPUTE_START_INHERITED(SVG
, (), svg
, parentSVG
, SVG
, SVGData
)
4775 // clip-rule: enum, inherit, initial
4776 SetDiscrete(SVGData
.mClipRule
, svg
->mClipRule
, inherited
,
4777 SETDSC_ENUMERATED
, parentSVG
->mClipRule
,
4778 NS_STYLE_FILL_RULE_NONZERO
, 0, 0, 0, 0);
4780 // color-interpolation: enum, auto, inherit, initial
4781 SetDiscrete(SVGData
.mColorInterpolation
, svg
->mColorInterpolation
, inherited
,
4782 SETDSC_ENUMERATED
| SETDSC_AUTO
,
4783 parentSVG
->mColorInterpolation
,
4784 NS_STYLE_COLOR_INTERPOLATION_SRGB
,
4785 NS_STYLE_COLOR_INTERPOLATION_AUTO
, 0, 0, 0);
4787 // color-interpolation-filters: enum, auto, inherit, initial
4788 SetDiscrete(SVGData
.mColorInterpolationFilters
,
4789 svg
->mColorInterpolationFilters
, inherited
,
4790 SETDSC_ENUMERATED
| SETDSC_AUTO
,
4791 parentSVG
->mColorInterpolationFilters
,
4792 NS_STYLE_COLOR_INTERPOLATION_LINEARRGB
,
4793 NS_STYLE_COLOR_INTERPOLATION_AUTO
, 0, 0, 0);
4796 SetSVGPaint(SVGData
.mFill
, parentSVG
->mFill
, mPresContext
, aContext
,
4797 svg
->mFill
, eStyleSVGPaintType_Color
, inherited
);
4799 // fill-opacity: factor, inherit, initial
4800 SetFactor(SVGData
.mFillOpacity
, svg
->mFillOpacity
, inherited
,
4801 parentSVG
->mFillOpacity
, 1.0f
, SETFCT_OPACITY
);
4803 // fill-rule: enum, inherit, initial
4804 SetDiscrete(SVGData
.mFillRule
, svg
->mFillRule
, inherited
,
4805 SETDSC_ENUMERATED
, parentSVG
->mFillRule
,
4806 NS_STYLE_FILL_RULE_NONZERO
, 0, 0, 0, 0);
4808 // marker-end: url, none, inherit
4809 if (eCSSUnit_URL
== SVGData
.mMarkerEnd
.GetUnit()) {
4810 svg
->mMarkerEnd
= SVGData
.mMarkerEnd
.GetURLValue();
4811 } else if (eCSSUnit_None
== SVGData
.mMarkerEnd
.GetUnit() ||
4812 eCSSUnit_Initial
== SVGData
.mMarkerEnd
.GetUnit()) {
4813 svg
->mMarkerEnd
= nsnull
;
4814 } else if (eCSSUnit_Inherit
== SVGData
.mMarkerEnd
.GetUnit()) {
4815 inherited
= PR_TRUE
;
4816 svg
->mMarkerEnd
= parentSVG
->mMarkerEnd
;
4819 // marker-mid: url, none, inherit
4820 if (eCSSUnit_URL
== SVGData
.mMarkerMid
.GetUnit()) {
4821 svg
->mMarkerMid
= SVGData
.mMarkerMid
.GetURLValue();
4822 } else if (eCSSUnit_None
== SVGData
.mMarkerMid
.GetUnit() ||
4823 eCSSUnit_Initial
== SVGData
.mMarkerMid
.GetUnit()) {
4824 svg
->mMarkerMid
= nsnull
;
4825 } else if (eCSSUnit_Inherit
== SVGData
.mMarkerMid
.GetUnit()) {
4826 inherited
= PR_TRUE
;
4827 svg
->mMarkerMid
= parentSVG
->mMarkerMid
;
4830 // marker-start: url, none, inherit
4831 if (eCSSUnit_URL
== SVGData
.mMarkerStart
.GetUnit()) {
4832 svg
->mMarkerStart
= SVGData
.mMarkerStart
.GetURLValue();
4833 } else if (eCSSUnit_None
== SVGData
.mMarkerStart
.GetUnit() ||
4834 eCSSUnit_Initial
== SVGData
.mMarkerStart
.GetUnit()) {
4835 svg
->mMarkerStart
= nsnull
;
4836 } else if (eCSSUnit_Inherit
== SVGData
.mMarkerStart
.GetUnit()) {
4837 inherited
= PR_TRUE
;
4838 svg
->mMarkerStart
= parentSVG
->mMarkerStart
;
4841 // pointer-events: enum, none, inherit, initial
4842 SetDiscrete(SVGData
.mPointerEvents
, svg
->mPointerEvents
, inherited
,
4843 SETDSC_ENUMERATED
| SETDSC_NONE
, parentSVG
->mPointerEvents
,
4844 NS_STYLE_POINTER_EVENTS_VISIBLEPAINTED
, 0,
4845 NS_STYLE_POINTER_EVENTS_NONE
, 0, 0);
4847 // shape-rendering: enum, auto, inherit
4848 SetDiscrete(SVGData
.mShapeRendering
, svg
->mShapeRendering
, inherited
,
4849 SETDSC_ENUMERATED
| SETDSC_AUTO
,
4850 parentSVG
->mShapeRendering
,
4851 NS_STYLE_SHAPE_RENDERING_AUTO
,
4852 NS_STYLE_SHAPE_RENDERING_AUTO
, 0, 0, 0);
4855 SetSVGPaint(SVGData
.mStroke
, parentSVG
->mStroke
, mPresContext
, aContext
,
4856 svg
->mStroke
, eStyleSVGPaintType_None
, inherited
);
4858 // stroke-dasharray: <dasharray>, none, inherit
4859 nsCSSValueList
*list
= SVGData
.mStrokeDasharray
;
4861 if (eCSSUnit_Inherit
== list
->mValue
.GetUnit()) {
4862 // only do the copy if weren't already set up by the copy constructor
4863 // FIXME Bug 389408: This is broken when aStartStruct is non-null!
4864 if (!svg
->mStrokeDasharray
) {
4865 inherited
= PR_TRUE
;
4866 svg
->mStrokeDasharrayLength
= parentSVG
->mStrokeDasharrayLength
;
4867 if (svg
->mStrokeDasharrayLength
) {
4868 svg
->mStrokeDasharray
= new nsStyleCoord
[svg
->mStrokeDasharrayLength
];
4869 if (svg
->mStrokeDasharray
)
4870 memcpy(svg
->mStrokeDasharray
,
4871 parentSVG
->mStrokeDasharray
,
4872 svg
->mStrokeDasharrayLength
* sizeof(nsStyleCoord
));
4874 svg
->mStrokeDasharrayLength
= 0;
4878 delete [] svg
->mStrokeDasharray
;
4879 svg
->mStrokeDasharray
= nsnull
;
4880 svg
->mStrokeDasharrayLength
= 0;
4882 if (eCSSUnit_Initial
!= list
->mValue
.GetUnit() &&
4883 eCSSUnit_None
!= list
->mValue
.GetUnit()) {
4884 // count number of values
4885 nsCSSValueList
*value
= SVGData
.mStrokeDasharray
;
4886 while (nsnull
!= value
) {
4887 ++svg
->mStrokeDasharrayLength
;
4888 value
= value
->mNext
;
4891 NS_ASSERTION(svg
->mStrokeDasharrayLength
!= 0, "no dasharray items");
4893 svg
->mStrokeDasharray
= new nsStyleCoord
[svg
->mStrokeDasharrayLength
];
4895 if (svg
->mStrokeDasharray
) {
4896 value
= SVGData
.mStrokeDasharray
;
4898 while (nsnull
!= value
) {
4899 SetCoord(value
->mValue
,
4900 svg
->mStrokeDasharray
[i
++], nsnull
,
4901 SETCOORD_LP
| SETCOORD_FACTOR
,
4902 aContext
, mPresContext
, inherited
);
4903 value
= value
->mNext
;
4906 svg
->mStrokeDasharrayLength
= 0;
4911 // stroke-dashoffset: <dashoffset>, inherit
4912 SetCoord(SVGData
.mStrokeDashoffset
,
4913 svg
->mStrokeDashoffset
, parentSVG
->mStrokeDashoffset
,
4914 SETCOORD_LPH
| SETCOORD_FACTOR
| SETCOORD_INITIAL_ZERO
,
4915 aContext
, mPresContext
, inherited
);
4917 // stroke-linecap: enum, inherit, initial
4918 SetDiscrete(SVGData
.mStrokeLinecap
, svg
->mStrokeLinecap
, inherited
,
4919 SETDSC_ENUMERATED
, parentSVG
->mStrokeLinecap
,
4920 NS_STYLE_STROKE_LINECAP_BUTT
, 0, 0, 0, 0);
4922 // stroke-linejoin: enum, inherit, initial
4923 SetDiscrete(SVGData
.mStrokeLinejoin
, svg
->mStrokeLinejoin
, inherited
,
4924 SETDSC_ENUMERATED
, parentSVG
->mStrokeLinejoin
,
4925 NS_STYLE_STROKE_LINEJOIN_MITER
, 0, 0, 0, 0);
4927 // stroke-miterlimit: <miterlimit>, inherit
4928 SetFactor(SVGData
.mStrokeMiterlimit
, svg
->mStrokeMiterlimit
, inherited
,
4929 parentSVG
->mStrokeMiterlimit
, 4.0f
);
4932 SetFactor(SVGData
.mStrokeOpacity
, svg
->mStrokeOpacity
, inherited
,
4933 parentSVG
->mStrokeOpacity
, 1.0f
, SETFCT_OPACITY
);
4936 if (eCSSUnit_Initial
== SVGData
.mStrokeWidth
.GetUnit()) {
4937 svg
->mStrokeWidth
.SetCoordValue(nsPresContext::CSSPixelsToAppUnits(1));
4939 SetCoord(SVGData
.mStrokeWidth
,
4940 svg
->mStrokeWidth
, parentSVG
->mStrokeWidth
,
4941 SETCOORD_LPH
| SETCOORD_FACTOR
,
4942 aContext
, mPresContext
, inherited
);
4945 // text-anchor: enum, inherit, initial
4946 SetDiscrete(SVGData
.mTextAnchor
, svg
->mTextAnchor
, inherited
,
4947 SETDSC_ENUMERATED
, parentSVG
->mTextAnchor
,
4948 NS_STYLE_TEXT_ANCHOR_START
, 0, 0, 0, 0);
4950 // text-rendering: enum, auto, inherit, initial
4951 SetDiscrete(SVGData
.mTextRendering
, svg
->mTextRendering
, inherited
,
4952 SETDSC_ENUMERATED
| SETDSC_AUTO
,
4953 parentSVG
->mTextRendering
,
4954 NS_STYLE_TEXT_RENDERING_AUTO
,
4955 NS_STYLE_TEXT_RENDERING_AUTO
, 0, 0, 0);
4957 COMPUTE_END_INHERITED(SVG
, svg
)
4961 nsRuleNode::ComputeSVGResetData(void* aStartStruct
,
4962 const nsRuleDataStruct
& aData
,
4963 nsStyleContext
* aContext
,
4964 nsRuleNode
* aHighestNode
,
4965 const RuleDetail aRuleDetail
, PRBool aInherited
)
4967 COMPUTE_START_RESET(SVGReset
, (), svgReset
, parentSVGReset
, SVG
, SVGData
)
4970 if (eCSSUnit_Initial
== SVGData
.mStopColor
.GetUnit()) {
4971 svgReset
->mStopColor
= NS_RGB(0, 0, 0);
4973 SetColor(SVGData
.mStopColor
, parentSVGReset
->mStopColor
,
4974 mPresContext
, aContext
, svgReset
->mStopColor
, inherited
);
4978 if (eCSSUnit_Initial
== SVGData
.mFloodColor
.GetUnit()) {
4979 svgReset
->mFloodColor
= NS_RGB(0, 0, 0);
4981 SetColor(SVGData
.mFloodColor
, parentSVGReset
->mFloodColor
,
4982 mPresContext
, aContext
, svgReset
->mFloodColor
, inherited
);
4986 if (eCSSUnit_Initial
== SVGData
.mLightingColor
.GetUnit()) {
4987 svgReset
->mLightingColor
= NS_RGB(255, 255, 255);
4989 SetColor(SVGData
.mLightingColor
, parentSVGReset
->mLightingColor
,
4990 mPresContext
, aContext
, svgReset
->mLightingColor
, inherited
);
4993 // clip-path: url, none, inherit
4994 if (eCSSUnit_URL
== SVGData
.mClipPath
.GetUnit()) {
4995 svgReset
->mClipPath
= SVGData
.mClipPath
.GetURLValue();
4996 } else if (eCSSUnit_None
== SVGData
.mClipPath
.GetUnit() ||
4997 eCSSUnit_Initial
== SVGData
.mClipPath
.GetUnit()) {
4998 svgReset
->mClipPath
= nsnull
;
4999 } else if (eCSSUnit_Inherit
== SVGData
.mClipPath
.GetUnit()) {
5000 inherited
= PR_TRUE
;
5001 svgReset
->mClipPath
= parentSVGReset
->mClipPath
;
5005 SetFactor(SVGData
.mStopOpacity
, svgReset
->mStopOpacity
, inherited
,
5006 parentSVGReset
->mStopOpacity
, 1.0f
, SETFCT_OPACITY
);
5009 SetFactor(SVGData
.mFloodOpacity
, svgReset
->mFloodOpacity
, inherited
,
5010 parentSVGReset
->mFloodOpacity
, 1.0f
, SETFCT_OPACITY
);
5012 // dominant-baseline: enum, auto, inherit, initial
5013 SetDiscrete(SVGData
.mDominantBaseline
, svgReset
->mDominantBaseline
,
5015 SETDSC_ENUMERATED
| SETDSC_AUTO
,
5016 parentSVGReset
->mDominantBaseline
,
5017 NS_STYLE_DOMINANT_BASELINE_AUTO
,
5018 NS_STYLE_DOMINANT_BASELINE_AUTO
, 0, 0, 0);
5020 // filter: url, none, inherit
5021 if (eCSSUnit_URL
== SVGData
.mFilter
.GetUnit()) {
5022 svgReset
->mFilter
= SVGData
.mFilter
.GetURLValue();
5023 } else if (eCSSUnit_None
== SVGData
.mFilter
.GetUnit() ||
5024 eCSSUnit_Initial
== SVGData
.mFilter
.GetUnit()) {
5025 svgReset
->mFilter
= nsnull
;
5026 } else if (eCSSUnit_Inherit
== SVGData
.mFilter
.GetUnit()) {
5027 inherited
= PR_TRUE
;
5028 svgReset
->mFilter
= parentSVGReset
->mFilter
;
5031 // mask: url, none, inherit
5032 if (eCSSUnit_URL
== SVGData
.mMask
.GetUnit()) {
5033 svgReset
->mMask
= SVGData
.mMask
.GetURLValue();
5034 } else if (eCSSUnit_None
== SVGData
.mMask
.GetUnit() ||
5035 eCSSUnit_Initial
== SVGData
.mMask
.GetUnit()) {
5036 svgReset
->mMask
= nsnull
;
5037 } else if (eCSSUnit_Inherit
== SVGData
.mMask
.GetUnit()) {
5038 inherited
= PR_TRUE
;
5039 svgReset
->mMask
= parentSVGReset
->mMask
;
5042 COMPUTE_END_RESET(SVGReset
, svgReset
)
5047 nsRuleNode::GetParentData(const nsStyleStructID aSID
)
5049 NS_PRECONDITION(mDependentBits
& nsCachedStyleData::GetBitForSID(aSID
),
5050 "should be called when node depends on parent data");
5051 NS_ASSERTION(mStyleData
.GetStyleData(aSID
) == nsnull
,
5052 "both struct and dependent bits present");
5053 // Walk up the rule tree from this rule node (towards less specific
5055 PRUint32 bit
= nsCachedStyleData::GetBitForSID(aSID
);
5056 nsRuleNode
*ruleNode
= mParent
;
5057 while (ruleNode
->mDependentBits
& bit
) {
5058 NS_ASSERTION(ruleNode
->mStyleData
.GetStyleData(aSID
) == nsnull
,
5059 "both struct and dependent bits present");
5060 ruleNode
= ruleNode
->mParent
;
5063 return ruleNode
->mStyleData
.GetStyleData(aSID
);
5066 #define STYLE_STRUCT(name_, checkdata_cb_, ctor_args_) \
5067 inline const nsStyle##name_ * \
5068 nsRuleNode::GetParent##name_() \
5070 NS_PRECONDITION(mDependentBits & \
5071 nsCachedStyleData::GetBitForSID(eStyleStruct_##name_), \
5072 "should be called when node depends on parent data"); \
5073 NS_ASSERTION(mStyleData.GetStyle##name_() == nsnull, \
5074 "both struct and dependent bits present"); \
5075 /* Walk up the rule tree from this rule node (towards less specific */ \
5077 PRUint32 bit = nsCachedStyleData::GetBitForSID(eStyleStruct_##name_); \
5078 nsRuleNode *ruleNode = mParent; \
5079 while (ruleNode->mDependentBits & bit) { \
5080 NS_ASSERTION(ruleNode->mStyleData.GetStyle##name_() == nsnull, \
5081 "both struct and dependent bits present"); \
5082 ruleNode = ruleNode->mParent; \
5085 return ruleNode->mStyleData.GetStyle##name_(); \
5087 #include "nsStyleStructList.h"
5091 nsRuleNode::GetStyleData(nsStyleStructID aSID
,
5092 nsStyleContext
* aContext
,
5093 PRBool aComputeData
)
5096 if (mDependentBits
& nsCachedStyleData::GetBitForSID(aSID
)) {
5097 // We depend on an ancestor for this struct since the cached struct
5098 // it has is also appropriate for this rule node. Just go up the
5099 // rule tree and return the first cached struct we find.
5100 data
= GetParentData(aSID
);
5101 NS_ASSERTION(data
, "dependent bits set but no cached struct present");
5105 data
= mStyleData
.GetStyleData(aSID
);
5106 if (NS_LIKELY(data
!= nsnull
))
5107 return data
; // We have a fully specified struct. Just return it.
5109 if (NS_UNLIKELY(!aComputeData
))
5112 // Nothing is cached. We'll have to delve further and examine our rules.
5113 #define STYLE_STRUCT_TEST aSID
5114 #define STYLE_STRUCT(name, checkdata_cb, ctor_args) \
5115 data = Get##name##Data(aContext);
5116 #include "nsStyleStructList.h"
5118 #undef STYLE_STRUCT_TEST
5120 if (NS_LIKELY(data
!= nsnull
))
5123 NS_NOTREACHED("could not create style struct");
5124 // To ensure that |GetStyleData| never returns null (even when we're
5125 // out of memory), we'll get the style set and get a copy of the
5126 // default values for the given style struct from the set. Note that
5127 // this works fine even if |this| is a rule node that has been
5128 // destroyed (leftover from a previous rule tree) but is somehow still
5130 return mPresContext
->PresShell()->StyleSet()->
5131 DefaultStyleData()->GetStyleData(aSID
);
5134 // See comments above in GetStyleData for an explanation of what the
5136 #define STYLE_STRUCT(name_, checkdata_cb_, ctor_args_) \
5137 const nsStyle##name_* \
5138 nsRuleNode::GetStyle##name_(nsStyleContext* aContext, PRBool aComputeData) \
5140 const nsStyle##name_ *data; \
5141 if (mDependentBits & \
5142 nsCachedStyleData::GetBitForSID(eStyleStruct_##name_)) { \
5143 data = GetParent##name_(); \
5144 NS_ASSERTION(data, "dependent bits set but no cached struct present"); \
5148 data = mStyleData.GetStyle##name_(); \
5149 if (NS_LIKELY(data != nsnull)) \
5152 if (NS_UNLIKELY(!aComputeData)) \
5156 static_cast<const nsStyle##name_ *>(Get##name_##Data(aContext)); \
5158 if (NS_LIKELY(data != nsnull)) \
5161 NS_NOTREACHED("could not create style struct"); \
5163 static_cast<const nsStyle##name_ *>( \
5164 mPresContext->PresShell()->StyleSet()-> \
5165 DefaultStyleData()->GetStyleData(eStyleStruct_##name_)); \
5167 #include "nsStyleStructList.h"
5173 for (nsRuleNode
*node
= this;
5174 node
&& !(node
->mDependentBits
& NS_RULE_NODE_GC_MARK
);
5175 node
= node
->mParent
)
5176 node
->mDependentBits
|= NS_RULE_NODE_GC_MARK
;
5179 PR_STATIC_CALLBACK(PLDHashOperator
)
5180 SweepRuleNodeChildren(PLDHashTable
*table
, PLDHashEntryHdr
*hdr
,
5181 PRUint32 number
, void *arg
)
5183 ChildrenHashEntry
*entry
= static_cast<ChildrenHashEntry
*>(hdr
);
5184 if (entry
->mRuleNode
->Sweep())
5185 return PL_DHASH_REMOVE
; // implies NEXT, unless |ed with STOP
5186 return PL_DHASH_NEXT
;
5192 // If we're not marked, then we have to delete ourself.
5193 // However, we never allow the root node to GC itself, because nsStyleSet
5194 // wants to hold onto the root node and not worry about re-creating a
5195 // rule walker if the root node is deleted.
5196 if (!(mDependentBits
& NS_RULE_NODE_GC_MARK
) && !IsRoot()) {
5201 // Clear our mark, for the next time around.
5202 mDependentBits
&= ~NS_RULE_NODE_GC_MARK
;
5204 // Call sweep on the children, since some may not be marked, and
5205 // remove any deleted children from the child lists.
5206 if (HaveChildren()) {
5207 if (ChildrenAreHashed()) {
5208 PLDHashTable
*children
= ChildrenHash();
5209 PL_DHashTableEnumerate(children
, SweepRuleNodeChildren
, nsnull
);
5211 for (nsRuleNode
**children
= ChildrenListPtr(); *children
; ) {
5212 nsRuleNode
*next
= (*children
)->mNextSibling
;
5213 if ((*children
)->Sweep()) {
5214 // This rule node was destroyed, so implicitly advance by
5215 // making *children point to the next entry.
5219 children
= &(*children
)->mNextSibling
;
5228 nsRuleNode::HasAuthorSpecifiedRules(nsStyleContext
* aStyleContext
,
5229 PRUint32 ruleTypeMask
)
5231 nsRuleDataColor colorData
;
5232 nsRuleDataMargin marginData
;
5233 PRUint32 nValues
= 0;
5235 PRUint32 inheritBits
= 0;
5236 if (ruleTypeMask
& NS_AUTHOR_SPECIFIED_BACKGROUND
)
5237 inheritBits
|= NS_STYLE_INHERIT_BIT(Background
);
5239 if (ruleTypeMask
& NS_AUTHOR_SPECIFIED_BORDER
)
5240 inheritBits
|= NS_STYLE_INHERIT_BIT(Border
);
5242 if (ruleTypeMask
& NS_AUTHOR_SPECIFIED_PADDING
)
5243 inheritBits
|= NS_STYLE_INHERIT_BIT(Padding
);
5245 /* We're relying on the use of |aStyleContext| not mutating it! */
5246 nsRuleData
ruleData(inheritBits
,
5247 aStyleContext
->PresContext(), aStyleContext
);
5248 ruleData
.mColorData
= &colorData
;
5249 ruleData
.mMarginData
= &marginData
;
5251 nsCSSValue
* backgroundValues
[] = {
5252 &colorData
.mBackColor
,
5253 &colorData
.mBackImage
5256 nsCSSValue
* borderValues
[] = {
5257 &marginData
.mBorderColor
.mTop
,
5258 &marginData
.mBorderStyle
.mTop
,
5259 &marginData
.mBorderWidth
.mTop
,
5260 &marginData
.mBorderColor
.mRight
,
5261 &marginData
.mBorderStyle
.mRight
,
5262 &marginData
.mBorderWidth
.mRight
,
5263 &marginData
.mBorderColor
.mBottom
,
5264 &marginData
.mBorderStyle
.mBottom
,
5265 &marginData
.mBorderWidth
.mBottom
,
5266 &marginData
.mBorderColor
.mLeft
,
5267 &marginData
.mBorderStyle
.mLeft
,
5268 &marginData
.mBorderWidth
.mLeft
5269 // XXX add &marginData.mBorder{Start,End}{Width,Color,Style}
5272 nsCSSValue
* paddingValues
[] = {
5273 &marginData
.mPadding
.mTop
,
5274 &marginData
.mPadding
.mRight
,
5275 &marginData
.mPadding
.mBottom
,
5276 &marginData
.mPadding
.mLeft
,
5277 &marginData
.mPaddingStart
,
5278 &marginData
.mPaddingEnd
5281 nsCSSValue
* values
[NS_ARRAY_LENGTH(backgroundValues
) +
5282 NS_ARRAY_LENGTH(borderValues
) +
5283 NS_ARRAY_LENGTH(paddingValues
)];
5285 if (ruleTypeMask
& NS_AUTHOR_SPECIFIED_BACKGROUND
) {
5286 memcpy(&values
[nValues
], backgroundValues
, NS_ARRAY_LENGTH(backgroundValues
) * sizeof(nsCSSValue
*));
5287 nValues
+= NS_ARRAY_LENGTH(backgroundValues
);
5290 if (ruleTypeMask
& NS_AUTHOR_SPECIFIED_BORDER
) {
5291 memcpy(&values
[nValues
], borderValues
, NS_ARRAY_LENGTH(borderValues
) * sizeof(nsCSSValue
*));
5292 nValues
+= NS_ARRAY_LENGTH(borderValues
);
5295 if (ruleTypeMask
& NS_AUTHOR_SPECIFIED_PADDING
) {
5296 memcpy(&values
[nValues
], paddingValues
, NS_ARRAY_LENGTH(paddingValues
) * sizeof(nsCSSValue
*));
5297 nValues
+= NS_ARRAY_LENGTH(paddingValues
);
5300 // We need to be careful not to count styles covered up by
5301 // user-important or UA-important declarations.
5302 for (nsRuleNode
* ruleNode
= aStyleContext
->GetRuleNode(); ruleNode
;
5303 ruleNode
= ruleNode
->GetParent()) {
5304 nsIStyleRule
*rule
= ruleNode
->GetRule();
5306 ruleData
.mLevel
= ruleNode
->GetLevel();
5307 ruleData
.mIsImportantRule
= ruleNode
->IsImportantRule();
5308 rule
->MapRuleInfoInto(&ruleData
);
5309 // Do the same nulling out as in GetBorderData, GetBackgroundData
5310 // or GetPaddingData.
5311 // We are sharing with some style rule. It really owns the data.
5312 marginData
.mBoxShadow
= nsnull
;
5314 if (ruleData
.mLevel
== nsStyleSet::eAgentSheet
||
5315 ruleData
.mLevel
== nsStyleSet::eUserSheet
) {
5316 // This is a rule whose effect we want to ignore, so if any of
5317 // the properties we care about were set, set them to the dummy
5318 // value that they'll never otherwise get.
5319 for (PRUint32 i
= 0; i
< nValues
; ++i
)
5320 if (values
[i
]->GetUnit() != eCSSUnit_Null
)
5321 values
[i
]->SetDummyValue();
5323 // If any of the values we care about was set by the above rule,
5324 // we have author style.
5325 for (PRUint32 i
= 0; i
< nValues
; ++i
)
5326 if (values
[i
]->GetUnit() != eCSSUnit_Null
&&
5327 values
[i
]->GetUnit() != eCSSUnit_Dummy
) // see above