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 */ 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
);
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 */ 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 mChildren
.asVoid
= 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 mDependentBits((PRUint32(aLevel
) << NS_RULE_NODE_LEVEL_SHIFT
) |
683 (aIsImportant
? NS_RULE_NODE_IS_IMPORTANT
: 0)),
686 mChildren
.asVoid
= nsnull
;
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 (* 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 static 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 static 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_, flags_, 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_, flags_, 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_, flags_, 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_, flags_, 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_, flags_, 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_, flags_, 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_, flags_, 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_, flags_, 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_, flags_, 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_, flags_, 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_, flags_, 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_, flags_, 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_, flags_, 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_, flags_, 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_, flags_, 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_, flags_, 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_, flags_, 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_, flags_, 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_, flags_, 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_, flags_, 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_, flags_, 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_, flags_, 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_, flags_, 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();
1668 /* Reset structs don't inherit from first-line. */
1669 /* See similar code in COMPUTE_START_RESET */
1670 while (parentContext
&&
1671 parentContext
->GetPseudoType() == nsCSSPseudoElements::firstLine
) {
1672 parentContext
= parentContext
->GetParent();
1675 if (parentContext
) {
1676 // We have a parent, and so we should just inherit from the parent.
1677 // Set the inherit bits on our context. These bits tell the style context that
1678 // it never has to go back to the rule tree for data. Instead the style context tree
1679 // should be walked to find the data.
1680 const void* parentStruct
= parentContext
->GetStyleData(aSID
);
1681 aContext
->AddStyleBit(bit
); // makes const_cast OK.
1682 aContext
->SetStyle(aSID
, const_cast<void*>(parentStruct
));
1683 return parentStruct
;
1686 // We are the root. In the case of fonts, the default values just
1687 // come from the pres context.
1688 return SetDefaultOnRoot(aSID
, aContext
);
1691 // We need to compute the data from the information that the rules specified.
1693 #define STYLE_STRUCT_TEST aSID
1694 #define STYLE_STRUCT(name, checkdata_cb, ctor_args) \
1695 res = Compute##name##Data(startStruct, *aSpecificData, aContext, \
1696 highestNode, detail, !aRuleData->mCanStoreInRuleTree);
1697 #include "nsStyleStructList.h"
1699 #undef STYLE_STRUCT_TEST
1701 // If we have a post-resolve callback, handle that now.
1702 if (aRuleData
->mPostResolveCallback
&& (NS_LIKELY(res
!= nsnull
)))
1703 (*aRuleData
->mPostResolveCallback
)(const_cast<void*>(res
), aRuleData
);
1705 // Now return the result.
1710 nsRuleNode::SetDefaultOnRoot(const nsStyleStructID aSID
, nsStyleContext
* aContext
)
1713 case eStyleStruct_Font
:
1715 nsStyleFont
* fontData
= new (mPresContext
) nsStyleFont(mPresContext
);
1716 if (NS_LIKELY(fontData
!= nsnull
)) {
1717 nscoord minimumFontSize
=
1718 mPresContext
->GetCachedIntPref(kPresContext_MinimumFontSize
);
1720 if (minimumFontSize
> 0 && !mPresContext
->IsChrome()) {
1721 fontData
->mFont
.size
= PR_MAX(fontData
->mSize
, minimumFontSize
);
1724 fontData
->mFont
.size
= fontData
->mSize
;
1726 aContext
->SetStyle(eStyleStruct_Font
, fontData
);
1730 case eStyleStruct_Display
:
1732 nsStyleDisplay
* disp
= new (mPresContext
) nsStyleDisplay();
1733 if (NS_LIKELY(disp
!= nsnull
)) {
1734 aContext
->SetStyle(eStyleStruct_Display
, disp
);
1738 case eStyleStruct_Visibility
:
1740 nsStyleVisibility
* vis
= new (mPresContext
) nsStyleVisibility(mPresContext
);
1741 if (NS_LIKELY(vis
!= nsnull
)) {
1742 aContext
->SetStyle(eStyleStruct_Visibility
, vis
);
1746 case eStyleStruct_Text
:
1748 nsStyleText
* text
= new (mPresContext
) nsStyleText();
1749 if (NS_LIKELY(text
!= nsnull
)) {
1750 aContext
->SetStyle(eStyleStruct_Text
, text
);
1754 case eStyleStruct_TextReset
:
1756 nsStyleTextReset
* text
= new (mPresContext
) nsStyleTextReset();
1757 if (NS_LIKELY(text
!= nsnull
)) {
1758 aContext
->SetStyle(eStyleStruct_TextReset
, text
);
1762 case eStyleStruct_Color
:
1764 nsStyleColor
* color
= new (mPresContext
) nsStyleColor(mPresContext
);
1765 if (NS_LIKELY(color
!= nsnull
)) {
1766 aContext
->SetStyle(eStyleStruct_Color
, color
);
1770 case eStyleStruct_Background
:
1772 nsStyleBackground
* bg
= new (mPresContext
) nsStyleBackground();
1773 if (NS_LIKELY(bg
!= nsnull
)) {
1774 aContext
->SetStyle(eStyleStruct_Background
, bg
);
1778 case eStyleStruct_Margin
:
1780 nsStyleMargin
* margin
= new (mPresContext
) nsStyleMargin();
1781 if (NS_LIKELY(margin
!= nsnull
)) {
1782 aContext
->SetStyle(eStyleStruct_Margin
, margin
);
1786 case eStyleStruct_Border
:
1788 nsStyleBorder
* border
= new (mPresContext
) nsStyleBorder(mPresContext
);
1789 if (NS_LIKELY(border
!= nsnull
)) {
1790 aContext
->SetStyle(eStyleStruct_Border
, border
);
1794 case eStyleStruct_Padding
:
1796 nsStylePadding
* padding
= new (mPresContext
) nsStylePadding();
1797 if (NS_LIKELY(padding
!= nsnull
)) {
1798 aContext
->SetStyle(eStyleStruct_Padding
, padding
);
1802 case eStyleStruct_Outline
:
1804 nsStyleOutline
* outline
= new (mPresContext
) nsStyleOutline(mPresContext
);
1805 if (NS_LIKELY(outline
!= nsnull
)) {
1806 aContext
->SetStyle(eStyleStruct_Outline
, outline
);
1810 case eStyleStruct_List
:
1812 nsStyleList
* list
= new (mPresContext
) nsStyleList();
1813 if (NS_LIKELY(list
!= nsnull
)) {
1814 aContext
->SetStyle(eStyleStruct_List
, list
);
1818 case eStyleStruct_Position
:
1820 nsStylePosition
* pos
= new (mPresContext
) nsStylePosition();
1821 if (NS_LIKELY(pos
!= nsnull
)) {
1822 aContext
->SetStyle(eStyleStruct_Position
, pos
);
1826 case eStyleStruct_Table
:
1828 nsStyleTable
* table
= new (mPresContext
) nsStyleTable();
1829 if (NS_LIKELY(table
!= nsnull
)) {
1830 aContext
->SetStyle(eStyleStruct_Table
, table
);
1834 case eStyleStruct_TableBorder
:
1836 nsStyleTableBorder
* table
= new (mPresContext
) nsStyleTableBorder(mPresContext
);
1837 if (NS_LIKELY(table
!= nsnull
)) {
1838 aContext
->SetStyle(eStyleStruct_TableBorder
, table
);
1842 case eStyleStruct_Content
:
1844 nsStyleContent
* content
= new (mPresContext
) nsStyleContent();
1845 if (NS_LIKELY(content
!= nsnull
)) {
1846 aContext
->SetStyle(eStyleStruct_Content
, content
);
1850 case eStyleStruct_Quotes
:
1852 nsStyleQuotes
* quotes
= new (mPresContext
) nsStyleQuotes();
1853 if (NS_LIKELY(quotes
!= nsnull
)) {
1854 aContext
->SetStyle(eStyleStruct_Quotes
, quotes
);
1858 case eStyleStruct_UserInterface
:
1860 nsStyleUserInterface
* ui
= new (mPresContext
) nsStyleUserInterface();
1861 if (NS_LIKELY(ui
!= nsnull
)) {
1862 aContext
->SetStyle(eStyleStruct_UserInterface
, ui
);
1866 case eStyleStruct_UIReset
:
1868 nsStyleUIReset
* ui
= new (mPresContext
) nsStyleUIReset();
1869 if (NS_LIKELY(ui
!= nsnull
)) {
1870 aContext
->SetStyle(eStyleStruct_UIReset
, ui
);
1875 case eStyleStruct_XUL
:
1877 nsStyleXUL
* xul
= new (mPresContext
) nsStyleXUL();
1878 if (NS_LIKELY(xul
!= nsnull
)) {
1879 aContext
->SetStyle(eStyleStruct_XUL
, xul
);
1884 case eStyleStruct_Column
:
1886 nsStyleColumn
* column
= new (mPresContext
) nsStyleColumn(mPresContext
);
1887 if (NS_LIKELY(column
!= nsnull
)) {
1888 aContext
->SetStyle(eStyleStruct_Column
, column
);
1894 case eStyleStruct_SVG
:
1896 nsStyleSVG
* svg
= new (mPresContext
) nsStyleSVG();
1897 if (NS_LIKELY(svg
!= nsnull
)) {
1898 aContext
->SetStyle(eStyleStruct_SVG
, svg
);
1903 case eStyleStruct_SVGReset
:
1905 nsStyleSVGReset
* svgReset
= new (mPresContext
) nsStyleSVGReset();
1906 if (NS_LIKELY(svgReset
!= nsnull
)) {
1907 aContext
->SetStyle(eStyleStruct_SVGReset
, svgReset
);
1914 * unhandled case: nsStyleStructID_Length.
1915 * last item of nsStyleStructID, to know its length.
1923 * This function handles cascading of *-left or *-right box properties
1924 * against *-start (which is L for LTR and R for RTL) or *-end (which is
1925 * R for LTR and L for RTL).
1927 * Cascading these properties correctly is hard because we need to
1928 * cascade two properties as one, but which two properties depends on a
1929 * third property ('direction'). We solve this by treating each of
1930 * these properties (say, 'margin-start') as a shorthand that sets a
1931 * property containing the value of the property specified
1932 * ('margin-start-value') and sets a pair of properties
1933 * ('margin-left-ltr-source' and 'margin-right-rtl-source') saying which
1934 * of the properties we use. Thus, when we want to compute the value of
1935 * 'margin-left' when 'direction' is 'ltr', we look at the value of
1936 * 'margin-left-ltr-source', which tells us whether to use the highest
1937 * 'margin-left' in the cascade or the highest 'margin-start'.
1939 * Finally, since we can compute the normal (*-left and *-right)
1940 * properties in a loop, this function works by modifying the data we
1941 * will use in that loop (which the caller must copy from the const
1945 nsRuleNode::AdjustLogicalBoxProp(nsStyleContext
* aContext
,
1946 const nsCSSValue
& aLTRSource
,
1947 const nsCSSValue
& aRTLSource
,
1948 const nsCSSValue
& aLTRLogicalValue
,
1949 const nsCSSValue
& aRTLLogicalValue
,
1951 nsCSSRect
& aValueRect
,
1954 PRBool LTRlogical
= aLTRSource
.GetUnit() == eCSSUnit_Enumerated
&&
1955 aLTRSource
.GetIntValue() == NS_BOXPROP_SOURCE_LOGICAL
;
1956 PRBool RTLlogical
= aRTLSource
.GetUnit() == eCSSUnit_Enumerated
&&
1957 aRTLSource
.GetIntValue() == NS_BOXPROP_SOURCE_LOGICAL
;
1958 if (LTRlogical
|| RTLlogical
) {
1959 // We can't cache anything on the rule tree if we use any data from
1960 // the style context, since data cached in the rule tree could be
1961 // used with a style context with a different value.
1962 aInherited
= PR_TRUE
;
1963 PRUint8 dir
= aContext
->GetStyleVisibility()->mDirection
;
1965 if (dir
== NS_STYLE_DIRECTION_LTR
) {
1967 aValueRect
.*(nsCSSRect::sides
[aSide
]) = aLTRLogicalValue
;
1970 aValueRect
.*(nsCSSRect::sides
[aSide
]) = aRTLLogicalValue
;
1976 * Begin an nsRuleNode::Compute*Data function for an inherited struct.
1978 * @param type_ The nsStyle* type this function computes.
1979 * @param ctorargs_ The arguments used for the default nsStyle* constructor.
1980 * @param data_ Variable (declared here) holding the result of this
1982 * @param parentdata_ Variable (declared here) holding the parent style
1983 * context's data for this struct.
1984 * @param rdtype_ The nsCSS* struct type used to compute this struct's data.
1985 * @param rdata_ Variable (declared here) holding the nsCSS* used here.
1987 #define COMPUTE_START_INHERITED(type_, ctorargs_, data_, parentdata_, rdtype_, rdata_) \
1988 NS_ASSERTION(aRuleDetail != eRuleFullInherited, \
1989 "should not have bothered calling Compute*Data"); \
1991 nsStyleContext* parentContext = aContext->GetParent(); \
1993 const nsRuleData##rdtype_& rdata_ = \
1994 static_cast<const nsRuleData##rdtype_&>(aData); \
1995 nsStyle##type_* data_ = nsnull; \
1996 const nsStyle##type_* parentdata_ = nsnull; \
1997 PRBool inherited = aInherited; \
1999 /* If |inherited| might be false by the time we're done, we can't call */ \
2000 /* parentContext->GetStyle##type_() since it could recur into setting */ \
2001 /* the same struct on the same rule node, causing a leak. */ \
2002 if (parentContext && aRuleDetail != eRuleFullReset && \
2003 (!aStartStruct || (aRuleDetail != eRulePartialReset && \
2004 aRuleDetail != eRuleNone))) \
2005 parentdata_ = parentContext->GetStyle##type_(); \
2007 /* We only need to compute the delta between this computed data and */ \
2008 /* our computed data. */ \
2009 data_ = new (mPresContext) \
2010 nsStyle##type_(*static_cast<nsStyle##type_*>(aStartStruct)); \
2012 if (aRuleDetail != eRuleFullMixed && aRuleDetail != eRuleFullReset) { \
2013 /* No question. We will have to inherit. Go ahead and init */ \
2014 /* with inherited vals from parent. */ \
2015 inherited = PR_TRUE; \
2017 data_ = new (mPresContext) nsStyle##type_(*parentdata_); \
2019 data_ = new (mPresContext) nsStyle##type_ ctorargs_; \
2022 data_ = new (mPresContext) nsStyle##type_ ctorargs_; \
2025 if (NS_UNLIKELY(!data_)) \
2026 return nsnull; /* Out Of Memory */ \
2028 parentdata_ = data_;
2031 * Begin an nsRuleNode::Compute*Data function for a reset struct.
2033 * @param type_ The nsStyle* type this function computes.
2034 * @param ctorargs_ The arguments used for the default nsStyle* constructor.
2035 * @param data_ Variable (declared here) holding the result of this
2037 * @param parentdata_ Variable (declared here) holding the parent style
2038 * context's data for this struct.
2039 * @param rdtype_ The nsCSS* struct type used to compute this struct's data.
2040 * @param rdata_ Variable (declared here) holding the nsCSS* used here.
2042 #define COMPUTE_START_RESET(type_, ctorargs_, data_, parentdata_, rdtype_, rdata_) \
2043 NS_ASSERTION(aRuleDetail != eRuleFullInherited, \
2044 "should not have bothered calling Compute*Data"); \
2046 nsStyleContext* parentContext = aContext->GetParent(); \
2047 /* Reset structs don't inherit from first-line */ \
2048 /* See similar code in WalkRuleTree */ \
2049 while (parentContext && \
2050 parentContext->GetPseudoType() == nsCSSPseudoElements::firstLine) { \
2051 parentContext = parentContext->GetParent(); \
2054 const nsRuleData##rdtype_& rdata_ = \
2055 static_cast<const nsRuleData##rdtype_&>(aData); \
2056 nsStyle##type_* data_; \
2058 /* We only need to compute the delta between this computed data and */ \
2059 /* our computed data. */ \
2060 data_ = new (mPresContext) \
2061 nsStyle##type_(*static_cast<nsStyle##type_*>(aStartStruct)); \
2063 data_ = new (mPresContext) nsStyle##type_ ctorargs_; \
2065 if (NS_UNLIKELY(!data_)) \
2066 return nsnull; /* Out Of Memory */ \
2068 /* If |inherited| might be false by the time we're done, we can't call */ \
2069 /* parentContext->GetStyle##type_() since it could recur into setting */ \
2070 /* the same struct on the same rule node, causing a leak. */ \
2071 const nsStyle##type_* parentdata_ = data_; \
2072 if (parentContext && \
2073 aRuleDetail != eRuleFullReset && \
2074 aRuleDetail != eRulePartialReset && \
2075 aRuleDetail != eRuleNone) \
2076 parentdata_ = parentContext->GetStyle##type_(); \
2077 PRBool inherited = aInherited;
2080 * Begin an nsRuleNode::Compute*Data function for an inherited struct.
2082 * @param type_ The nsStyle* type this function computes.
2083 * @param data_ Variable holding the result of this function.
2085 #define COMPUTE_END_INHERITED(type_, data_) \
2087 /* We inherited, and therefore can't be cached in the rule node. We */ \
2088 /* have to be put right on the style context. */ \
2089 aContext->SetStyle(eStyleStruct_##type_, data_); \
2091 /* We were fully specified and can therefore be cached right on the */ \
2093 if (!aHighestNode->mStyleData.mInheritedData) { \
2094 aHighestNode->mStyleData.mInheritedData = \
2095 new (mPresContext) nsInheritedStyleData; \
2096 if (NS_UNLIKELY(!aHighestNode->mStyleData.mInheritedData)) { \
2097 data_->Destroy(mPresContext); \
2101 aHighestNode->mStyleData.mInheritedData->m##type_##Data = data_; \
2102 /* Propagate the bit down. */ \
2103 PropagateDependentBit(NS_STYLE_INHERIT_BIT(type_), aHighestNode); \
2109 * Begin an nsRuleNode::Compute*Data function for a reset struct.
2111 * @param type_ The nsStyle* type this function computes.
2112 * @param data_ Variable holding the result of this function.
2114 #define COMPUTE_END_RESET(type_, data_) \
2116 /* We inherited, and therefore can't be cached in the rule node. We */ \
2117 /* have to be put right on the style context. */ \
2118 aContext->SetStyle(eStyleStruct_##type_, data_); \
2120 /* We were fully specified and can therefore be cached right on the */ \
2122 if (!aHighestNode->mStyleData.mResetData) { \
2123 aHighestNode->mStyleData.mResetData = \
2124 new (mPresContext) nsResetStyleData; \
2125 if (NS_UNLIKELY(!aHighestNode->mStyleData.mResetData)) { \
2126 data_->Destroy(mPresContext); \
2130 aHighestNode->mStyleData.mResetData->m##type_##Data = data_; \
2131 /* Propagate the bit down. */ \
2132 PropagateDependentBit(NS_STYLE_INHERIT_BIT(type_), aHighestNode); \
2138 // This function figures out how much scaling should be suppressed to
2139 // satisfy scriptminsize. This is our attempt to implement
2140 // http://www.w3.org/TR/MathML2/chapter3.html#id.3.3.4.2.2
2141 // This is called after mScriptLevel, mScriptMinSize and mScriptSizeMultiplier
2142 // have been set in aFont.
2144 // Here are the invariants we enforce:
2145 // 1) A decrease in size must not reduce the size below minscriptsize.
2146 // 2) An increase in size must not increase the size above the size we would
2147 // have if minscriptsize had not been applied anywhere.
2148 // 3) The scriptlevel-induced size change must between 1.0 and the parent's
2149 // scriptsizemultiplier^(new script level - old script level), as close to the
2150 // latter as possible subject to constraints 1 and 2.
2152 ComputeScriptLevelSize(const nsStyleFont
* aFont
, const nsStyleFont
* aParentFont
,
2153 nsPresContext
* aPresContext
, nscoord
* aUnconstrainedSize
)
2155 PRInt32 scriptLevelChange
=
2156 aFont
->mScriptLevel
- aParentFont
->mScriptLevel
;
2157 if (scriptLevelChange
== 0) {
2158 *aUnconstrainedSize
= aParentFont
->mScriptUnconstrainedSize
;
2159 // Constraint #3 says that we cannot change size, and #1 and #2 are always
2160 // satisfied with no change. It's important this be fast because it covers
2161 // all non-MathML content.
2162 return aParentFont
->mSize
;
2165 // Compute actual value of minScriptSize
2166 nscoord minScriptSize
=
2167 nsStyleFont::ZoomText(aPresContext
, aParentFont
->mScriptMinSize
);
2169 double scriptLevelScale
=
2170 pow(aParentFont
->mScriptSizeMultiplier
, scriptLevelChange
);
2171 // Compute the size we would have had if minscriptsize had never been
2172 // applied, also prevent overflow (bug 413274)
2173 *aUnconstrainedSize
=
2174 NSToCoordRound(PR_MIN(aParentFont
->mScriptUnconstrainedSize
*scriptLevelScale
,
2176 // Compute the size we could get via scriptlevel change
2177 nscoord scriptLevelSize
=
2178 NSToCoordRound(PR_MIN(aParentFont
->mSize
*scriptLevelScale
,
2180 if (scriptLevelScale
<= 1.0) {
2181 if (aParentFont
->mSize
<= minScriptSize
) {
2182 // We can't decrease the font size at all, so just stick to no change
2183 // (authors are allowed to explicitly set the font size smaller than
2185 return aParentFont
->mSize
;
2187 // We can decrease, so apply constraint #1
2188 return PR_MAX(minScriptSize
, scriptLevelSize
);
2190 // scriptminsize can only make sizes larger than the unconstrained size
2191 NS_ASSERTION(*aUnconstrainedSize
<= scriptLevelSize
, "How can this ever happen?");
2192 // Apply constraint #2
2193 return PR_MIN(scriptLevelSize
, PR_MAX(*aUnconstrainedSize
, minScriptSize
));
2199 nsRuleNode::SetFontSize(nsPresContext
* aPresContext
,
2200 const nsRuleDataFont
& aFontData
,
2201 const nsStyleFont
* aFont
,
2202 const nsStyleFont
* aParentFont
,
2204 const nsFont
& aSystemFont
,
2205 nscoord aParentSize
,
2206 nscoord aScriptLevelAdjustedParentSize
,
2207 PRBool aUsedStartStruct
,
2210 PRBool zoom
= PR_FALSE
;
2211 PRInt32 baseSize
= (PRInt32
) aPresContext
->
2212 GetDefaultFont(aFont
->mGenericID
)->size
;
2213 if (eCSSUnit_Enumerated
== aFontData
.mSize
.GetUnit()) {
2214 PRInt32 value
= aFontData
.mSize
.GetIntValue();
2215 PRInt32 scaler
= aPresContext
->FontScaler();
2216 float scaleFactor
= nsStyleUtil::GetScalingFactor(scaler
);
2219 if ((NS_STYLE_FONT_SIZE_XXSMALL
<= value
) &&
2220 (value
<= NS_STYLE_FONT_SIZE_XXLARGE
)) {
2221 *aSize
= nsStyleUtil::CalcFontPointSize(value
, baseSize
,
2222 scaleFactor
, aPresContext
, eFontSize_CSS
);
2224 else if (NS_STYLE_FONT_SIZE_XXXLARGE
== value
) {
2225 // <font size="7"> is not specified in CSS, so we don't use eFontSize_CSS.
2226 *aSize
= nsStyleUtil::CalcFontPointSize(value
, baseSize
,
2227 scaleFactor
, aPresContext
);
2229 else if (NS_STYLE_FONT_SIZE_LARGER
== value
||
2230 NS_STYLE_FONT_SIZE_SMALLER
== value
) {
2231 aInherited
= PR_TRUE
;
2233 // Un-zoom so we use the tables correctly. We'll then rezoom due
2234 // to the |zoom = PR_TRUE| above.
2235 // Note that relative units here use the parent's size unadjusted
2236 // for scriptlevel changes. A scriptlevel change between us and the parent
2237 // is simply ignored.
2238 nscoord parentSize
=
2239 nsStyleFont::UnZoomText(aPresContext
, aParentSize
);
2241 if (NS_STYLE_FONT_SIZE_LARGER
== value
) {
2242 *aSize
= nsStyleUtil::FindNextLargerFontSize(parentSize
,
2243 baseSize
, scaleFactor
, aPresContext
, eFontSize_CSS
);
2244 NS_ASSERTION(*aSize
> parentSize
,
2245 "FindNextLargerFontSize failed");
2248 *aSize
= nsStyleUtil::FindNextSmallerFontSize(parentSize
,
2249 baseSize
, scaleFactor
, aPresContext
, eFontSize_CSS
);
2250 NS_ASSERTION(*aSize
< parentSize
||
2251 parentSize
<= nsPresContext::CSSPixelsToAppUnits(1),
2252 "FindNextSmallerFontSize failed");
2255 NS_NOTREACHED("unexpected value");
2258 else if (aFontData
.mSize
.IsLengthUnit()) {
2259 // Note that font-based length units use the parent's size unadjusted
2260 // for scriptlevel changes. A scriptlevel change between us and the parent
2261 // is simply ignored.
2262 *aSize
= CalcLengthWith(aFontData
.mSize
, aParentSize
, aParentFont
, nsnull
,
2263 aPresContext
, aInherited
);
2264 zoom
= aFontData
.mSize
.IsFixedLengthUnit() ||
2265 aFontData
.mSize
.GetUnit() == eCSSUnit_Pixel
;
2267 else if (eCSSUnit_Percent
== aFontData
.mSize
.GetUnit()) {
2268 aInherited
= PR_TRUE
;
2269 // Note that % units use the parent's size unadjusted for scriptlevel
2270 // changes. A scriptlevel change between us and the parent is simply
2272 *aSize
= NSToCoordRound(aParentSize
*
2273 aFontData
.mSize
.GetPercentValue());
2276 else if (eCSSUnit_System_Font
== aFontData
.mSize
.GetUnit()) {
2277 // this becomes our cascading size
2278 *aSize
= aSystemFont
.size
;
2281 else if (eCSSUnit_Inherit
== aFontData
.mSize
.GetUnit()) {
2282 aInherited
= PR_TRUE
;
2283 // We apply scriptlevel change for this case, because the default is
2284 // to inherit and we don't want explicit "inherit" to differ from the
2286 *aSize
= aScriptLevelAdjustedParentSize
;
2289 else if (eCSSUnit_Initial
== aFontData
.mSize
.GetUnit()) {
2290 // The initial value is 'medium', which has magical sizing based on
2291 // the generic font family, so do that here too.
2295 NS_ASSERTION(eCSSUnit_Null
== aFontData
.mSize
.GetUnit(),
2296 "What kind of font-size value is this?");
2298 // if aUsedStartStruct is true, then every single property in the
2299 // font struct is being set all at once. This means scriptlevel is not
2300 // going to have any influence on the font size; there is no need to
2301 // do anything here.
2302 if (!aUsedStartStruct
&& aParentSize
!= aScriptLevelAdjustedParentSize
) {
2303 // There was no rule affecting the size but the size has been
2304 // affected by the parent's size via scriptlevel change. So treat
2305 // this as inherited.
2306 aInherited
= PR_TRUE
;
2307 *aSize
= aScriptLevelAdjustedParentSize
;
2312 // We want to zoom the cascaded size so that em-based measurements,
2313 // line-heights, etc., work.
2315 *aSize
= nsStyleFont::ZoomText(aPresContext
, *aSize
);
2319 static PRInt8
ClampTo8Bit(PRInt32 aValue
) {
2324 return PRInt8(aValue
);
2328 nsRuleNode::SetFont(nsPresContext
* aPresContext
, nsStyleContext
* aContext
,
2329 nscoord aMinFontSize
,
2330 PRUint8 aGenericFontID
, const nsRuleDataFont
& aFontData
,
2331 const nsStyleFont
* aParentFont
,
2332 nsStyleFont
* aFont
, PRBool aUsedStartStruct
,
2335 const nsFont
* defaultVariableFont
=
2336 aPresContext
->GetDefaultFont(kPresContext_DefaultVariableFont_ID
);
2338 // -moz-system-font: enum (never inherit!)
2340 if (eCSSUnit_Enumerated
== aFontData
.mSystemFont
.GetUnit()) {
2341 nsSystemFontID sysID
;
2342 switch (aFontData
.mSystemFont
.GetIntValue()) {
2343 case NS_STYLE_FONT_CAPTION
: sysID
= eSystemFont_Caption
; break; // css2
2344 case NS_STYLE_FONT_ICON
: sysID
= eSystemFont_Icon
; break;
2345 case NS_STYLE_FONT_MENU
: sysID
= eSystemFont_Menu
; break;
2346 case NS_STYLE_FONT_MESSAGE_BOX
: sysID
= eSystemFont_MessageBox
; break;
2347 case NS_STYLE_FONT_SMALL_CAPTION
: sysID
= eSystemFont_SmallCaption
; break;
2348 case NS_STYLE_FONT_STATUS_BAR
: sysID
= eSystemFont_StatusBar
; break;
2349 case NS_STYLE_FONT_WINDOW
: sysID
= eSystemFont_Window
; break; // css3
2350 case NS_STYLE_FONT_DOCUMENT
: sysID
= eSystemFont_Document
; break;
2351 case NS_STYLE_FONT_WORKSPACE
: sysID
= eSystemFont_Workspace
; break;
2352 case NS_STYLE_FONT_DESKTOP
: sysID
= eSystemFont_Desktop
; break;
2353 case NS_STYLE_FONT_INFO
: sysID
= eSystemFont_Info
; break;
2354 case NS_STYLE_FONT_DIALOG
: sysID
= eSystemFont_Dialog
; break;
2355 case NS_STYLE_FONT_BUTTON
: sysID
= eSystemFont_Button
; break;
2356 case NS_STYLE_FONT_PULL_DOWN_MENU
:sysID
= eSystemFont_PullDownMenu
; break;
2357 case NS_STYLE_FONT_LIST
: sysID
= eSystemFont_List
; break;
2358 case NS_STYLE_FONT_FIELD
: sysID
= eSystemFont_Field
; break;
2361 // GetSystemFont sets the font face but not necessarily the size
2362 // XXX Or at least it used to -- no longer true for thebes. Maybe
2363 // it should be again, though.
2364 systemFont
.size
= defaultVariableFont
->size
;
2366 if (NS_FAILED(aPresContext
->DeviceContext()->GetSystemFont(sysID
,
2368 systemFont
.name
= defaultVariableFont
->name
;
2371 // XXXldb All of this platform-specific stuff should be in the
2372 // nsIDeviceContext implementations, not here.
2376 // As far as I can tell the system default fonts and sizes for
2377 // on MS-Windows for Buttons, Listboxes/Comboxes and Text Fields are
2378 // all pre-determined and cannot be changed by either the control panel
2379 // or programmtically.
2382 // Fields (text fields)
2383 // Button and Selects (listboxes/comboboxes)
2384 // We use whatever font is defined by the system. Which it appears
2385 // (and the assumption is) it is always a proportional font. Then we
2386 // always use 2 points smaller than what the browser has defined as
2387 // the default proportional font.
2388 case eSystemFont_Field
:
2389 case eSystemFont_Button
:
2390 case eSystemFont_List
:
2391 // Assumption: system defined font is proportional
2393 PR_MAX(defaultVariableFont
->size
- aPresContext
->PointsToAppUnits(2), 0);
2398 // In case somebody explicitly used -moz-use-system-font.
2399 systemFont
= *defaultVariableFont
;
2403 // font-family: string list, enum, inherit
2404 NS_ASSERTION(eCSSUnit_Enumerated
!= aFontData
.mFamily
.GetUnit(),
2405 "system fonts should not be in mFamily anymore");
2406 if (eCSSUnit_String
== aFontData
.mFamily
.GetUnit()) {
2407 // set the correct font if we are using DocumentFonts OR we are overriding for XUL
2409 if (aGenericFontID
== kGenericFont_NONE
) {
2410 // only bother appending fallback fonts if this isn't a fallback generic font itself
2411 if (!aFont
->mFont
.name
.IsEmpty())
2412 aFont
->mFont
.name
.Append((PRUnichar
)',');
2413 // defaultVariableFont.name should always be "serif" or "sans-serif".
2414 aFont
->mFont
.name
.Append(defaultVariableFont
->name
);
2416 aFont
->mFont
.familyNameQuirks
=
2417 (aPresContext
->CompatibilityMode() == eCompatibility_NavQuirks
&&
2418 aFontData
.mFamilyFromHTML
);
2419 aFont
->mFont
.systemFont
= PR_FALSE
;
2420 // Technically this is redundant with the code below, but it's good
2421 // to have since we'll still want it once we get rid of
2422 // SetGenericFont (bug 380915).
2423 aFont
->mGenericID
= aGenericFontID
;
2425 else if (eCSSUnit_System_Font
== aFontData
.mFamily
.GetUnit()) {
2426 aFont
->mFont
.name
= systemFont
.name
;
2427 aFont
->mFont
.familyNameQuirks
= PR_FALSE
;
2428 aFont
->mFont
.systemFont
= PR_TRUE
;
2429 aFont
->mGenericID
= kGenericFont_NONE
;
2431 else if (eCSSUnit_Inherit
== aFontData
.mFamily
.GetUnit()) {
2432 aInherited
= PR_TRUE
;
2433 aFont
->mFont
.name
= aParentFont
->mFont
.name
;
2434 aFont
->mFont
.familyNameQuirks
= aParentFont
->mFont
.familyNameQuirks
;
2435 aFont
->mFont
.systemFont
= aParentFont
->mFont
.systemFont
;
2436 aFont
->mGenericID
= aParentFont
->mGenericID
;
2438 else if (eCSSUnit_Initial
== aFontData
.mFamily
.GetUnit()) {
2439 aFont
->mFont
.name
= defaultVariableFont
->name
;
2440 aFont
->mFont
.familyNameQuirks
= PR_FALSE
;
2441 aFont
->mFont
.systemFont
= defaultVariableFont
->systemFont
;
2442 aFont
->mGenericID
= kGenericFont_NONE
;
2445 // When we're in the loop in SetGenericFont, we must ensure that we
2446 // always keep aFont->mFlags set to the correct generic. But we have
2447 // to be careful not to touch it when we're called directly from
2448 // ComputeFontData, because we could have a start struct.
2449 if (aGenericFontID
!= kGenericFont_NONE
) {
2450 aFont
->mGenericID
= aGenericFontID
;
2453 // font-style: enum, normal, inherit, initial, -moz-system-font
2454 SetDiscrete(aFontData
.mStyle
, aFont
->mFont
.style
, aInherited
,
2455 SETDSC_ENUMERATED
| SETDSC_NORMAL
| SETDSC_SYSTEM_FONT
,
2456 aParentFont
->mFont
.style
,
2457 defaultVariableFont
->style
,
2459 NS_STYLE_FONT_STYLE_NORMAL
,
2462 // font-variant: enum, normal, inherit, initial, -moz-system-font
2463 SetDiscrete(aFontData
.mVariant
, aFont
->mFont
.variant
, aInherited
,
2464 SETDSC_ENUMERATED
| SETDSC_NORMAL
| SETDSC_SYSTEM_FONT
,
2465 aParentFont
->mFont
.variant
,
2466 defaultVariableFont
->variant
,
2468 NS_STYLE_FONT_VARIANT_NORMAL
,
2469 systemFont
.variant
);
2471 // font-weight: int, enum, normal, inherit, initial, -moz-system-font
2472 // special handling for enum
2473 if (eCSSUnit_Enumerated
== aFontData
.mWeight
.GetUnit()) {
2474 PRInt32 value
= aFontData
.mWeight
.GetIntValue();
2476 case NS_STYLE_FONT_WEIGHT_NORMAL
:
2477 case NS_STYLE_FONT_WEIGHT_BOLD
:
2478 aFont
->mFont
.weight
= value
;
2480 case NS_STYLE_FONT_WEIGHT_BOLDER
:
2481 case NS_STYLE_FONT_WEIGHT_LIGHTER
:
2482 aInherited
= PR_TRUE
;
2483 aFont
->mFont
.weight
= nsStyleUtil::ConstrainFontWeight(aParentFont
->mFont
.weight
+ value
);
2487 SetDiscrete(aFontData
.mWeight
, aFont
->mFont
.weight
, aInherited
,
2488 SETDSC_INTEGER
| SETDSC_NORMAL
| SETDSC_SYSTEM_FONT
,
2489 aParentFont
->mFont
.weight
,
2490 defaultVariableFont
->weight
,
2492 NS_STYLE_FONT_WEIGHT_NORMAL
,
2496 // Compute scriptlevel, scriptminsize and scriptsizemultiplier now so
2497 // they're available for font-size computation.
2499 // -moz-script-min-size: length
2500 if (aFontData
.mScriptMinSize
.IsLengthUnit()) {
2501 // scriptminsize in font units (em, ex) has to be interpreted relative
2502 // to the parent font, or the size definitions are circular and we
2504 aFont
->mScriptMinSize
=
2505 CalcLengthWith(aFontData
.mScriptMinSize
, aParentFont
->mSize
, aParentFont
, nsnull
,
2506 aPresContext
, aInherited
);
2509 // -moz-script-size-multiplier: factor, inherit, initial
2510 SetFactor(aFontData
.mScriptSizeMultiplier
, aFont
->mScriptSizeMultiplier
,
2511 aInherited
, aParentFont
->mScriptSizeMultiplier
,
2512 NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER
,
2515 // -moz-script-level: integer, number, inherit
2516 if (eCSSUnit_Integer
== aFontData
.mScriptLevel
.GetUnit()) {
2518 aFont
->mScriptLevel
= ClampTo8Bit(aParentFont
->mScriptLevel
+ aFontData
.mScriptLevel
.GetIntValue());
2520 else if (eCSSUnit_Number
== aFontData
.mScriptLevel
.GetUnit()) {
2522 aFont
->mScriptLevel
= ClampTo8Bit(PRInt32(aFontData
.mScriptLevel
.GetFloatValue()));
2524 else if (eCSSUnit_Inherit
== aFontData
.mScriptSizeMultiplier
.GetUnit()) {
2525 aInherited
= PR_TRUE
;
2526 aFont
->mScriptLevel
= aParentFont
->mScriptLevel
;
2528 else if (eCSSUnit_Initial
== aFontData
.mScriptSizeMultiplier
.GetUnit()) {
2529 aFont
->mScriptLevel
= 0;
2533 // font-size: enum, length, percent, inherit
2534 nscoord scriptLevelAdjustedParentSize
= aParentFont
->mSize
;
2536 nscoord scriptLevelAdjustedUnconstrainedParentSize
;
2537 scriptLevelAdjustedParentSize
=
2538 ComputeScriptLevelSize(aFont
, aParentFont
, aPresContext
,
2539 &scriptLevelAdjustedUnconstrainedParentSize
);
2540 NS_ASSERTION(!aUsedStartStruct
|| aFont
->mScriptUnconstrainedSize
== aFont
->mSize
,
2541 "If we have a start struct, we should have reset everything coming in here");
2543 SetFontSize(aPresContext
, aFontData
, aFont
, aParentFont
, &aFont
->mSize
,
2544 systemFont
, aParentFont
->mSize
, scriptLevelAdjustedParentSize
,
2545 aUsedStartStruct
, aInherited
);
2547 if (aParentFont
->mSize
== aParentFont
->mScriptUnconstrainedSize
&&
2548 scriptLevelAdjustedParentSize
== scriptLevelAdjustedUnconstrainedParentSize
) {
2549 // Fast path: we have not been affected by scriptminsize so we don't
2550 // need to call SetFontSize again to compute the
2551 // scriptminsize-unconstrained size. This is OK even if we have a
2552 // start struct, because if we have a start struct then 'font-size'
2553 // was specified and so scriptminsize has no effect.
2554 aFont
->mScriptUnconstrainedSize
= aFont
->mSize
;
2556 SetFontSize(aPresContext
, aFontData
, aFont
, aParentFont
,
2557 &aFont
->mScriptUnconstrainedSize
, systemFont
,
2558 aParentFont
->mScriptUnconstrainedSize
,
2559 scriptLevelAdjustedUnconstrainedParentSize
,
2560 aUsedStartStruct
, aInherited
);
2562 NS_ASSERTION(aFont
->mScriptUnconstrainedSize
<= aFont
->mSize
,
2563 "scriptminsize should never be making things bigger");
2566 // enforce the user' specified minimum font-size on the value that we expose
2567 // (but don't change font-size:0)
2568 if (0 < aFont
->mSize
&& aFont
->mSize
< aMinFontSize
)
2569 aFont
->mFont
.size
= aMinFontSize
;
2571 aFont
->mFont
.size
= aFont
->mSize
;
2573 // font-size-adjust: number, none, inherit, initial, -moz-system-font
2574 if (eCSSUnit_System_Font
== aFontData
.mSizeAdjust
.GetUnit()) {
2575 aFont
->mFont
.sizeAdjust
= systemFont
.sizeAdjust
;
2577 SetFactor(aFontData
.mSizeAdjust
, aFont
->mFont
.sizeAdjust
, aInherited
,
2578 aParentFont
->mFont
.sizeAdjust
, 0.0f
, SETFCT_NONE
);
2582 // - backtrack to an ancestor with the same generic font name (possibly
2583 // up to the root where default values come from the presentation context)
2584 // - re-apply cascading rules from there without caching intermediate values
2586 nsRuleNode::SetGenericFont(nsPresContext
* aPresContext
,
2587 nsStyleContext
* aContext
,
2588 PRUint8 aGenericFontID
, nscoord aMinFontSize
,
2591 // walk up the contexts until a context with the desired generic font
2592 nsAutoVoidArray contextPath
;
2593 contextPath
.AppendElement(aContext
);
2594 nsStyleContext
* higherContext
= aContext
->GetParent();
2595 while (higherContext
) {
2596 if (higherContext
->GetStyleFont()->mGenericID
== aGenericFontID
) {
2597 // done walking up the higher contexts
2600 contextPath
.AppendElement(higherContext
);
2601 higherContext
= higherContext
->GetParent();
2604 // re-apply the cascading rules, starting from the higher context
2606 // If we stopped earlier because we reached the root of the style tree,
2607 // we will start with the default generic font from the presentation
2608 // context. Otherwise we start with the higher context.
2609 const nsFont
* defaultFont
= aPresContext
->GetDefaultFont(aGenericFontID
);
2610 nsStyleFont
parentFont(*defaultFont
, aPresContext
);
2611 if (higherContext
) {
2612 const nsStyleFont
* tmpFont
= higherContext
->GetStyleFont();
2613 parentFont
= *tmpFont
;
2615 *aFont
= parentFont
;
2618 PRUint32 fontBit
= nsCachedStyleData::GetBitForSID(eStyleStruct_Font
);
2620 for (PRInt32 i
= contextPath
.Count() - 1; i
>= 0; --i
) {
2621 nsStyleContext
* context
= (nsStyleContext
*)contextPath
[i
];
2622 nsRuleDataFont fontData
; // Declare a struct with null CSS values.
2623 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Font
), aPresContext
, context
);
2624 ruleData
.mFontData
= &fontData
;
2626 // Trimmed down version of ::WalkRuleTree() to re-apply the style rules
2627 // Note that we *do* need to do this for our own data, since what is
2628 // in |fontData| in ComputeFontData is only for the rules below
2630 for (nsRuleNode
* ruleNode
= context
->GetRuleNode(); ruleNode
;
2631 ruleNode
= ruleNode
->GetParent()) {
2632 if (ruleNode
->mNoneBits
& fontBit
)
2633 // no more font rules on this branch, get out
2636 nsIStyleRule
*rule
= ruleNode
->GetRule();
2638 ruleData
.mLevel
= ruleNode
->GetLevel();
2639 ruleData
.mIsImportantRule
= ruleNode
->IsImportantRule();
2640 rule
->MapRuleInfoInto(&ruleData
);
2644 // Compute the delta from the information that the rules specified
2646 // Avoid unnecessary operations in SetFont(). But we care if it's
2647 // the final value that we're computing.
2649 fontData
.mFamily
.Reset();
2651 nsRuleNode::SetFont(aPresContext
, context
, aMinFontSize
,
2652 aGenericFontID
, fontData
, &parentFont
, aFont
,
2655 // XXX Not sure if we need to do this here
2656 // If we have a post-resolve callback, handle that now.
2657 if (ruleData
.mPostResolveCallback
)
2658 (ruleData
.mPostResolveCallback
)(aFont
, &ruleData
);
2660 parentFont
= *aFont
;
2664 static PRBool
ExtractGeneric(const nsString
& aFamily
, PRBool aGeneric
,
2667 nsAutoString
*data
= static_cast<nsAutoString
*>(aData
);
2671 return PR_FALSE
; // stop enumeration
2677 nsRuleNode::ComputeFontData(void* aStartStruct
,
2678 const nsRuleDataStruct
& aData
,
2679 nsStyleContext
* aContext
,
2680 nsRuleNode
* aHighestNode
,
2681 const RuleDetail aRuleDetail
, PRBool aInherited
)
2683 COMPUTE_START_INHERITED(Font
, (mPresContext
), font
, parentFont
,
2686 // NOTE: The |aRuleDetail| passed in is a little bit conservative due
2687 // to the -moz-system-font property. We really don't need to consider
2688 // it here in determining whether to cache in the rule tree. However,
2689 // we do need to consider it in WalkRuleTree when deciding whether to
2690 // walk further up the tree. So this means that when the font struct
2691 // is fully specified using *longhand* properties (excluding
2692 // -moz-system-font), we won't cache in the rule tree even though we
2693 // could. However, it's pretty unlikely authors will do that
2694 // (although there is a pretty good chance they'll fully specify it
2695 // using the 'font' shorthand).
2697 // See if there is a minimum font-size constraint to honor
2698 nscoord minimumFontSize
=
2699 mPresContext
->GetCachedIntPref(kPresContext_MinimumFontSize
);
2701 if (minimumFontSize
< 0)
2702 minimumFontSize
= 0;
2704 PRBool useDocumentFonts
=
2705 mPresContext
->GetCachedBoolPref(kPresContext_UseDocumentFonts
);
2707 // See if we are in the chrome
2708 // We only need to know this to determine if we have to use the
2709 // document fonts (overriding the useDocumentFonts flag), or to
2710 // determine if we have to override the minimum font-size constraint.
2711 if ((!useDocumentFonts
|| minimumFontSize
> 0) && mPresContext
->IsChrome()) {
2712 // if we are not using document fonts, but this is a XUL document,
2713 // then we use the document fonts anyway
2714 useDocumentFonts
= PR_TRUE
;
2715 minimumFontSize
= 0;
2718 // Figure out if we are a generic font
2719 PRUint8 generic
= kGenericFont_NONE
;
2720 // XXXldb What if we would have had a string if we hadn't been doing
2721 // the optimization with a non-null aStartStruct?
2722 if (eCSSUnit_String
== fontData
.mFamily
.GetUnit()) {
2723 fontData
.mFamily
.GetStringValue(font
->mFont
.name
);
2724 // XXXldb Do we want to extract the generic for this if it's not only a
2726 nsFont::GetGenericID(font
->mFont
.name
, &generic
);
2728 // If we aren't allowed to use document fonts, then we are only entitled
2729 // to use the user's default variable-width font and fixed-width font
2730 if (!useDocumentFonts
) {
2731 // Extract the generic from the specified font family...
2732 nsAutoString genericName
;
2733 if (!font
->mFont
.EnumerateFamilies(ExtractGeneric
, &genericName
)) {
2734 // The specified font had a generic family.
2735 font
->mFont
.name
= genericName
;
2736 nsFont::GetGenericID(genericName
, &generic
);
2738 // ... and only use it if it's -moz-fixed or monospace
2739 if (generic
!= kGenericFont_moz_fixed
&&
2740 generic
!= kGenericFont_monospace
) {
2741 font
->mFont
.name
.Truncate();
2742 generic
= kGenericFont_NONE
;
2745 // The specified font did not have a generic family.
2746 font
->mFont
.name
.Truncate();
2747 generic
= kGenericFont_NONE
;
2752 // Now compute our font struct
2753 if (generic
== kGenericFont_NONE
) {
2754 // continue the normal processing
2755 nsRuleNode::SetFont(mPresContext
, aContext
, minimumFontSize
, generic
,
2756 fontData
, parentFont
, font
,
2757 aStartStruct
!= nsnull
, inherited
);
2760 // re-calculate the font as a generic font
2761 inherited
= PR_TRUE
;
2762 nsRuleNode::SetGenericFont(mPresContext
, aContext
, generic
,
2763 minimumFontSize
, font
);
2766 COMPUTE_END_INHERITED(Font
, font
)
2769 already_AddRefed
<nsCSSShadowArray
>
2770 nsRuleNode::GetShadowData(nsCSSValueList
* aList
,
2771 nsStyleContext
* aContext
,
2775 PRUint32 arrayLength
= 0;
2776 for (nsCSSValueList
*list2
= aList
; list2
; list2
= list2
->mNext
)
2779 NS_ASSERTION(arrayLength
> 0, "Non-null text-shadow list, yet we counted 0 items.");
2780 nsCSSShadowArray
* shadowList
= new(arrayLength
) nsCSSShadowArray(arrayLength
);
2785 nsStyleCoord tempCoord
;
2787 for (nsCSSShadowItem
* item
= shadowList
->ShadowAt(0);
2789 aList
= aList
->mNext
, ++item
) {
2790 nsCSSValue::Array
*arr
= aList
->mValue
.GetArrayValue();
2791 // OK to pass bad aParentCoord since we're not passing SETCOORD_INHERIT
2792 unitOK
= SetCoord(arr
->Item(0), tempCoord
, nsStyleCoord(),
2793 SETCOORD_LENGTH
, aContext
, mPresContext
, inherited
);
2794 NS_ASSERTION(unitOK
, "unexpected unit");
2795 item
->mXOffset
= tempCoord
.GetCoordValue();
2797 unitOK
= SetCoord(arr
->Item(1), tempCoord
, nsStyleCoord(),
2798 SETCOORD_LENGTH
, aContext
, mPresContext
, inherited
);
2799 NS_ASSERTION(unitOK
, "unexpected unit");
2800 item
->mYOffset
= tempCoord
.GetCoordValue();
2802 // Blur radius is optional in the current box-shadow spec
2803 if (arr
->Item(2).GetUnit() != eCSSUnit_Null
) {
2804 unitOK
= SetCoord(arr
->Item(2), tempCoord
, nsStyleCoord(),
2805 SETCOORD_LENGTH
, aContext
, mPresContext
, inherited
);
2806 NS_ASSERTION(unitOK
, "unexpected unit");
2807 item
->mRadius
= tempCoord
.GetCoordValue();
2812 // Find the spread radius
2813 if (aUsesSpread
&& arr
->Item(3).GetUnit() != eCSSUnit_Null
) {
2814 unitOK
= SetCoord(arr
->Item(3), tempCoord
, nsStyleCoord(),
2815 SETCOORD_LENGTH
, aContext
, mPresContext
, inherited
);
2816 NS_ASSERTION(unitOK
, "unexpected unit");
2817 item
->mSpread
= tempCoord
.GetCoordValue();
2822 if (arr
->Item(4).GetUnit() != eCSSUnit_Null
) {
2823 item
->mHasColor
= PR_TRUE
;
2824 // 2nd argument can be bogus since inherit is not a valid color
2825 unitOK
= SetColor(arr
->Item(4), 0, mPresContext
, aContext
, item
->mColor
,
2827 NS_ASSERTION(unitOK
, "unexpected unit");
2831 NS_ADDREF(shadowList
);
2836 nsRuleNode::ComputeTextData(void* aStartStruct
,
2837 const nsRuleDataStruct
& aData
,
2838 nsStyleContext
* aContext
,
2839 nsRuleNode
* aHighestNode
,
2840 const RuleDetail aRuleDetail
, PRBool aInherited
)
2842 COMPUTE_START_INHERITED(Text
, (), text
, parentText
, Text
, textData
)
2844 // letter-spacing: normal, length, inherit
2845 SetCoord(textData
.mLetterSpacing
, text
->mLetterSpacing
, parentText
->mLetterSpacing
,
2846 SETCOORD_LH
| SETCOORD_NORMAL
| SETCOORD_INITIAL_NORMAL
,
2847 aContext
, mPresContext
, inherited
);
2849 // text-shadow: none, list, inherit, initial
2850 nsCSSValueList
* list
= textData
.mTextShadow
;
2852 text
->mTextShadow
= nsnull
;
2854 // Don't need to handle none/initial explicitly: The above assignment
2855 // takes care of that
2856 if (eCSSUnit_Inherit
== list
->mValue
.GetUnit()) {
2857 inherited
= PR_TRUE
;
2858 text
->mTextShadow
= parentText
->mTextShadow
;
2859 } else if (eCSSUnit_Array
== list
->mValue
.GetUnit()) {
2861 text
->mTextShadow
= GetShadowData(list
, aContext
, PR_FALSE
, inherited
);
2865 // line-height: normal, number, length, percent, inherit
2866 if (eCSSUnit_Percent
== textData
.mLineHeight
.GetUnit()) {
2867 inherited
= PR_TRUE
;
2868 // Use |mFont.size| to pick up minimum font size.
2869 text
->mLineHeight
.SetCoordValue(
2870 nscoord(float(aContext
->GetStyleFont()->mFont
.size
) *
2871 textData
.mLineHeight
.GetPercentValue()));
2873 else if (eCSSUnit_Initial
== textData
.mLineHeight
.GetUnit() ||
2874 eCSSUnit_System_Font
== textData
.mLineHeight
.GetUnit()) {
2875 text
->mLineHeight
.SetNormalValue();
2878 SetCoord(textData
.mLineHeight
, text
->mLineHeight
, parentText
->mLineHeight
,
2879 SETCOORD_LH
| SETCOORD_FACTOR
| SETCOORD_NORMAL
,
2880 aContext
, mPresContext
, inherited
);
2881 if (textData
.mLineHeight
.IsFixedLengthUnit() ||
2882 textData
.mLineHeight
.GetUnit() == eCSSUnit_Pixel
) {
2883 nscoord lh
= nsStyleFont::ZoomText(mPresContext
,
2884 text
->mLineHeight
.GetCoordValue());
2885 nscoord minimumFontSize
=
2886 mPresContext
->GetCachedIntPref(kPresContext_MinimumFontSize
);
2888 if (minimumFontSize
> 0 && !mPresContext
->IsChrome()) {
2889 // If we applied a minimum font size, scale the line height by
2890 // the same ratio. (If we *might* have applied a minimum font
2891 // size, we can't cache in the rule tree.)
2892 inherited
= PR_TRUE
;
2893 const nsStyleFont
*font
= aContext
->GetStyleFont();
2894 if (font
->mSize
!= 0) {
2895 lh
= nscoord(float(lh
) * float(font
->mFont
.size
) / float(font
->mSize
));
2897 lh
= minimumFontSize
;
2900 text
->mLineHeight
.SetCoordValue(lh
);
2905 // text-align: enum, string, inherit, initial
2906 if (eCSSUnit_String
== textData
.mTextAlign
.GetUnit()) {
2907 NS_NOTYETIMPLEMENTED("align string");
2909 SetDiscrete(textData
.mTextAlign
, text
->mTextAlign
, inherited
,
2910 SETDSC_ENUMERATED
, parentText
->mTextAlign
,
2911 NS_STYLE_TEXT_ALIGN_DEFAULT
,
2914 // text-indent: length, percent, inherit, initial
2915 SetCoord(textData
.mTextIndent
, text
->mTextIndent
, parentText
->mTextIndent
,
2916 SETCOORD_LPH
| SETCOORD_INITIAL_ZERO
, aContext
,
2917 mPresContext
, inherited
);
2919 // text-transform: enum, none, inherit, initial
2920 SetDiscrete(textData
.mTextTransform
, text
->mTextTransform
, inherited
,
2921 SETDSC_ENUMERATED
| SETDSC_NONE
, parentText
->mTextTransform
,
2922 NS_STYLE_TEXT_TRANSFORM_NONE
, 0,
2923 NS_STYLE_TEXT_TRANSFORM_NONE
, 0, 0);
2925 // white-space: enum, normal, inherit, initial
2926 SetDiscrete(textData
.mWhiteSpace
, text
->mWhiteSpace
, inherited
,
2927 SETDSC_ENUMERATED
| SETDSC_NORMAL
, parentText
->mWhiteSpace
,
2928 NS_STYLE_WHITESPACE_NORMAL
, 0, 0,
2929 NS_STYLE_WHITESPACE_NORMAL
, 0);
2931 // word-spacing: normal, length, inherit
2932 SetCoord(textData
.mWordSpacing
, text
->mWordSpacing
, parentText
->mWordSpacing
,
2933 SETCOORD_LH
| SETCOORD_NORMAL
| SETCOORD_INITIAL_NORMAL
,
2934 aContext
, mPresContext
, inherited
);
2936 // word-wrap: enum, normal, inherit, initial
2937 SetDiscrete(textData
.mWordWrap
, text
->mWordWrap
, inherited
,
2938 SETDSC_ENUMERATED
| SETDSC_NORMAL
, parentText
->mWordWrap
,
2939 NS_STYLE_WORDWRAP_NORMAL
, 0, 0,
2940 NS_STYLE_WORDWRAP_NORMAL
, 0);
2942 COMPUTE_END_INHERITED(Text
, text
)
2946 nsRuleNode::ComputeTextResetData(void* aStartStruct
,
2947 const nsRuleDataStruct
& aData
,
2948 nsStyleContext
* aContext
,
2949 nsRuleNode
* aHighestNode
,
2950 const RuleDetail aRuleDetail
, PRBool aInherited
)
2952 COMPUTE_START_RESET(TextReset
, (), text
, parentText
, Text
, textData
)
2954 // vertical-align: enum, length, percent, inherit
2955 if (!SetCoord(textData
.mVerticalAlign
, text
->mVerticalAlign
,
2956 parentText
->mVerticalAlign
, SETCOORD_LPH
| SETCOORD_ENUMERATED
,
2957 aContext
, mPresContext
, inherited
)) {
2958 if (eCSSUnit_Initial
== textData
.mVerticalAlign
.GetUnit()) {
2959 text
->mVerticalAlign
.SetIntValue(NS_STYLE_VERTICAL_ALIGN_BASELINE
,
2960 eStyleUnit_Enumerated
);
2964 // text-decoration: none, enum (bit field), inherit, initial
2965 if (eCSSUnit_Enumerated
== textData
.mDecoration
.GetUnit()) {
2966 PRInt32 td
= textData
.mDecoration
.GetIntValue();
2967 text
->mTextDecoration
= td
;
2968 if (td
& NS_STYLE_TEXT_DECORATION_PREF_ANCHORS
) {
2969 PRBool underlineLinks
=
2970 mPresContext
->GetCachedBoolPref(kPresContext_UnderlineLinks
);
2971 if (underlineLinks
) {
2972 text
->mTextDecoration
|= NS_STYLE_TEXT_DECORATION_UNDERLINE
;
2975 text
->mTextDecoration
&= ~NS_STYLE_TEXT_DECORATION_UNDERLINE
;
2980 SetDiscrete(textData
.mDecoration
, text
->mTextDecoration
, inherited
,
2982 parentText
->mTextDecoration
,
2983 NS_STYLE_TEXT_DECORATION_NONE
, 0,
2984 NS_STYLE_TEXT_DECORATION_NONE
, 0, 0);
2986 // unicode-bidi: enum, normal, inherit, initial
2987 SetDiscrete(textData
.mUnicodeBidi
, text
->mUnicodeBidi
, inherited
,
2988 SETDSC_ENUMERATED
| SETDSC_NORMAL
,
2989 parentText
->mUnicodeBidi
,
2990 NS_STYLE_UNICODE_BIDI_NORMAL
, 0, 0,
2991 NS_STYLE_UNICODE_BIDI_NORMAL
, 0);
2993 COMPUTE_END_RESET(TextReset
, text
)
2997 nsRuleNode::ComputeUserInterfaceData(void* aStartStruct
,
2998 const nsRuleDataStruct
& aData
,
2999 nsStyleContext
* aContext
,
3000 nsRuleNode
* aHighestNode
,
3001 const RuleDetail aRuleDetail
,
3004 COMPUTE_START_INHERITED(UserInterface
, (), ui
, parentUI
,
3005 UserInterface
, uiData
)
3007 // cursor: enum, auto, url, inherit
3008 nsCSSValueList
* list
= uiData
.mCursor
;
3009 if (nsnull
!= list
) {
3010 delete [] ui
->mCursorArray
;
3011 ui
->mCursorArray
= nsnull
;
3012 ui
->mCursorArrayLength
= 0;
3014 if (eCSSUnit_Inherit
== list
->mValue
.GetUnit()) {
3015 inherited
= PR_TRUE
;
3016 ui
->mCursor
= parentUI
->mCursor
;
3017 ui
->CopyCursorArrayFrom(*parentUI
);
3019 else if (eCSSUnit_Initial
== list
->mValue
.GetUnit()) {
3020 ui
->mCursor
= NS_STYLE_CURSOR_AUTO
;
3023 // The parser will never create a list that is *all* URL values --
3025 PRUint32 arrayLength
= 0;
3026 nsCSSValueList
* list2
= list
;
3027 for ( ; list
->mValue
.GetUnit() == eCSSUnit_Array
; list
= list
->mNext
)
3028 if (list
->mValue
.GetArrayValue()->Item(0).GetImageValue())
3031 if (arrayLength
!= 0) {
3032 ui
->mCursorArray
= new nsCursorImage
[arrayLength
];
3033 if (ui
->mCursorArray
) {
3034 ui
->mCursorArrayLength
= arrayLength
;
3036 for (nsCursorImage
*item
= ui
->mCursorArray
;
3037 list2
->mValue
.GetUnit() == eCSSUnit_Array
;
3038 list2
= list2
->mNext
) {
3039 nsCSSValue::Array
*arr
= list2
->mValue
.GetArrayValue();
3040 imgIRequest
*req
= arr
->Item(0).GetImageValue();
3043 if (arr
->Item(1).GetUnit() != eCSSUnit_Null
) {
3044 item
->mHaveHotspot
= PR_TRUE
;
3045 item
->mHotspotX
= arr
->Item(1).GetFloatValue(),
3046 item
->mHotspotY
= arr
->Item(2).GetFloatValue();
3054 NS_ASSERTION(list
, "Must have non-array value at the end");
3055 NS_ASSERTION(list
->mValue
.GetUnit() == eCSSUnit_Enumerated
||
3056 list
->mValue
.GetUnit() == eCSSUnit_Auto
,
3057 "Unexpected fallback value at end of cursor list");
3059 if (eCSSUnit_Enumerated
== list
->mValue
.GetUnit()) {
3060 ui
->mCursor
= list
->mValue
.GetIntValue();
3062 else if (eCSSUnit_Auto
== list
->mValue
.GetUnit()) {
3063 ui
->mCursor
= NS_STYLE_CURSOR_AUTO
;
3068 // user-input: auto, none, enum, inherit, initial
3069 SetDiscrete(uiData
.mUserInput
, ui
->mUserInput
, inherited
,
3070 SETDSC_ENUMERATED
| SETDSC_NONE
| SETDSC_AUTO
,
3071 parentUI
->mUserInput
,
3072 NS_STYLE_USER_INPUT_AUTO
,
3073 NS_STYLE_USER_INPUT_AUTO
,
3074 NS_STYLE_USER_INPUT_NONE
,
3077 // user-modify: enum, inherit, initial
3078 SetDiscrete(uiData
.mUserModify
, ui
->mUserModify
, inherited
,
3080 parentUI
->mUserModify
,
3081 NS_STYLE_USER_MODIFY_READ_ONLY
,
3084 // user-focus: none, normal, enum, inherit, initial
3085 SetDiscrete(uiData
.mUserFocus
, ui
->mUserFocus
, inherited
,
3086 SETDSC_ENUMERATED
| SETDSC_NONE
| SETDSC_NORMAL
,
3087 parentUI
->mUserFocus
,
3088 NS_STYLE_USER_FOCUS_NONE
,
3090 NS_STYLE_USER_FOCUS_NONE
,
3091 NS_STYLE_USER_FOCUS_NORMAL
,
3094 COMPUTE_END_INHERITED(UserInterface
, ui
)
3098 nsRuleNode::ComputeUIResetData(void* aStartStruct
,
3099 const nsRuleDataStruct
& aData
,
3100 nsStyleContext
* aContext
,
3101 nsRuleNode
* aHighestNode
,
3102 const RuleDetail aRuleDetail
, PRBool aInherited
)
3104 COMPUTE_START_RESET(UIReset
, (), ui
, parentUI
, UserInterface
, uiData
)
3106 // user-select: auto, none, enum, inherit, initial
3107 SetDiscrete(uiData
.mUserSelect
, ui
->mUserSelect
, inherited
,
3108 SETDSC_ENUMERATED
| SETDSC_NONE
| SETDSC_AUTO
,
3109 parentUI
->mUserSelect
,
3110 NS_STYLE_USER_SELECT_AUTO
,
3111 NS_STYLE_USER_SELECT_AUTO
,
3112 NS_STYLE_USER_SELECT_NONE
,
3115 // ime-mode: auto, normal, enum, inherit, initial
3116 SetDiscrete(uiData
.mIMEMode
, ui
->mIMEMode
, inherited
,
3117 SETDSC_ENUMERATED
| SETDSC_NORMAL
| SETDSC_AUTO
,
3119 NS_STYLE_IME_MODE_AUTO
,
3120 NS_STYLE_IME_MODE_AUTO
,
3122 NS_STYLE_IME_MODE_NORMAL
,
3125 // force-broken-image-icons: integer, inherit, initial
3126 SetDiscrete(uiData
.mForceBrokenImageIcon
, ui
->mForceBrokenImageIcon
,
3129 parentUI
->mForceBrokenImageIcon
,
3132 // -moz-window-shadow: enum, none, inherit, initial
3133 SetDiscrete(uiData
.mWindowShadow
, ui
->mWindowShadow
, inherited
,
3134 SETDSC_ENUMERATED
| SETDSC_NONE
, parentUI
->mWindowShadow
,
3135 NS_STYLE_WINDOW_SHADOW_DEFAULT
, 0,
3136 NS_STYLE_WINDOW_SHADOW_NONE
, 0, 0);
3138 COMPUTE_END_RESET(UIReset
, ui
)
3141 /* Given a -moz-transform token stream, accumulates them into an
3142 * nsStyleTransformMatrix
3144 * @param aList The nsCSSValueList of arrays to read into transform functions.
3145 * @param aContext The style context to use for unit conversion.
3146 * @param aPresContext The presentation context to use for unit conversion
3147 * @param aInherited If the value is inherited, this is set to PR_TRUE.
3148 * @return An nsStyleTransformMatrix corresponding to the net transform.
3150 static nsStyleTransformMatrix
ReadTransforms(const nsCSSValueList
* aList
,
3151 nsStyleContext
* aContext
,
3152 nsPresContext
* aPresContext
,
3155 nsStyleTransformMatrix result
;
3157 for (const nsCSSValueList
* curr
= aList
; curr
!= nsnull
; curr
= curr
->mNext
) {
3158 const nsCSSValue
&currElem
= curr
->mValue
;
3159 NS_ASSERTION(currElem
.GetUnit() == eCSSUnit_Function
,
3160 "Stream should consist solely of functions!");
3161 NS_ASSERTION(currElem
.GetArrayValue()->Count() >= 1,
3162 "Incoming function is too short!");
3164 /* Read in a single transform matrix, then accumulate it with the total. */
3165 nsStyleTransformMatrix currMatrix
;
3166 currMatrix
.SetToTransformFunction(currElem
.GetArrayValue(), aContext
,
3167 aPresContext
, aInherited
);
3168 result
*= currMatrix
;
3174 nsRuleNode::ComputeDisplayData(void* aStartStruct
,
3175 const nsRuleDataStruct
& aData
,
3176 nsStyleContext
* aContext
,
3177 nsRuleNode
* aHighestNode
,
3178 const RuleDetail aRuleDetail
, PRBool aInherited
)
3180 COMPUTE_START_RESET(Display
, (), display
, parentDisplay
,
3181 Display
, displayData
)
3183 // opacity: factor, inherit, initial
3184 SetFactor(displayData
.mOpacity
, display
->mOpacity
, inherited
,
3185 parentDisplay
->mOpacity
, 1.0f
, SETFCT_OPACITY
);
3187 // display: enum, none, inherit, initial
3188 SetDiscrete(displayData
.mDisplay
, display
->mDisplay
, inherited
,
3189 SETDSC_ENUMERATED
| SETDSC_NONE
, parentDisplay
->mDisplay
,
3190 NS_STYLE_DISPLAY_INLINE
, 0,
3191 NS_STYLE_DISPLAY_NONE
, 0, 0);
3193 // appearance: enum, none, inherit, initial
3194 SetDiscrete(displayData
.mAppearance
, display
->mAppearance
, inherited
,
3195 SETDSC_ENUMERATED
| SETDSC_NONE
, parentDisplay
->mAppearance
,
3197 NS_THEME_NONE
, 0, 0);
3199 // binding: url, none, inherit
3200 if (eCSSUnit_URL
== displayData
.mBinding
.GetUnit()) {
3201 nsCSSValue::URL
* url
= displayData
.mBinding
.GetURLStructValue();
3202 NS_ASSERTION(url
, "What's going on here?");
3204 if (NS_LIKELY(url
->mURI
)) {
3205 display
->mBinding
= url
;
3207 display
->mBinding
= nsnull
;
3210 else if (eCSSUnit_None
== displayData
.mBinding
.GetUnit() ||
3211 eCSSUnit_Initial
== displayData
.mBinding
.GetUnit()) {
3212 display
->mBinding
= nsnull
;
3214 else if (eCSSUnit_Inherit
== displayData
.mBinding
.GetUnit()) {
3215 inherited
= PR_TRUE
;
3216 display
->mBinding
= parentDisplay
->mBinding
;
3219 // position: enum, inherit, initial
3220 SetDiscrete(displayData
.mPosition
, display
->mPosition
, inherited
,
3221 SETDSC_ENUMERATED
, parentDisplay
->mPosition
,
3222 NS_STYLE_POSITION_STATIC
, 0, 0, 0, 0);
3224 // clear: enum, none, inherit, initial
3225 SetDiscrete(displayData
.mClear
, display
->mBreakType
, inherited
,
3226 SETDSC_ENUMERATED
| SETDSC_NONE
, parentDisplay
->mBreakType
,
3227 NS_STYLE_CLEAR_NONE
, 0,
3228 NS_STYLE_CLEAR_NONE
, 0, 0);
3230 // temp fix for bug 24000
3231 // Map 'auto' and 'avoid' to PR_FALSE, and 'always', 'left', and
3232 // 'right' to PR_TRUE.
3233 // "A conforming user agent may interpret the values 'left' and
3234 // 'right' as 'always'." - CSS2.1, section 13.3.1
3235 if (eCSSUnit_Enumerated
== displayData
.mBreakBefore
.GetUnit()) {
3236 display
->mBreakBefore
= (NS_STYLE_PAGE_BREAK_AVOID
!= displayData
.mBreakBefore
.GetIntValue());
3238 else if (eCSSUnit_Auto
== displayData
.mBreakBefore
.GetUnit() ||
3239 eCSSUnit_Initial
== displayData
.mBreakBefore
.GetUnit()) {
3240 display
->mBreakBefore
= PR_FALSE
;
3242 else if (eCSSUnit_Inherit
== displayData
.mBreakBefore
.GetUnit()) {
3243 inherited
= PR_TRUE
;
3244 display
->mBreakBefore
= parentDisplay
->mBreakBefore
;
3247 if (eCSSUnit_Enumerated
== displayData
.mBreakAfter
.GetUnit()) {
3248 display
->mBreakAfter
= (NS_STYLE_PAGE_BREAK_AVOID
!= displayData
.mBreakAfter
.GetIntValue());
3250 else if (eCSSUnit_Auto
== displayData
.mBreakAfter
.GetUnit() ||
3251 eCSSUnit_Initial
== displayData
.mBreakAfter
.GetUnit()) {
3252 display
->mBreakAfter
= PR_FALSE
;
3254 else if (eCSSUnit_Inherit
== displayData
.mBreakAfter
.GetUnit()) {
3255 inherited
= PR_TRUE
;
3256 display
->mBreakAfter
= parentDisplay
->mBreakAfter
;
3260 // float: enum, none, inherit, initial
3261 SetDiscrete(displayData
.mFloat
, display
->mFloats
, inherited
,
3262 SETDSC_ENUMERATED
| SETDSC_NONE
, parentDisplay
->mFloats
,
3263 NS_STYLE_FLOAT_NONE
, 0,
3264 NS_STYLE_FLOAT_NONE
, 0, 0);
3266 // overflow-x: enum, auto, inherit, initial
3267 SetDiscrete(displayData
.mOverflowX
, display
->mOverflowX
, inherited
,
3268 SETDSC_ENUMERATED
| SETDSC_AUTO
,
3269 parentDisplay
->mOverflowX
,
3270 NS_STYLE_OVERFLOW_VISIBLE
,
3271 NS_STYLE_OVERFLOW_AUTO
,
3274 // overflow-y: enum, auto, inherit, initial
3275 SetDiscrete(displayData
.mOverflowY
, display
->mOverflowY
, inherited
,
3276 SETDSC_ENUMERATED
| SETDSC_AUTO
,
3277 parentDisplay
->mOverflowY
,
3278 NS_STYLE_OVERFLOW_VISIBLE
,
3279 NS_STYLE_OVERFLOW_AUTO
,
3282 // CSS3 overflow-x and overflow-y require some fixup as well in some
3283 // cases. NS_STYLE_OVERFLOW_VISIBLE and NS_STYLE_OVERFLOW_CLIP are
3284 // meaningful only when used in both dimensions.
3285 if (display
->mOverflowX
!= display
->mOverflowY
&&
3286 (display
->mOverflowX
== NS_STYLE_OVERFLOW_VISIBLE
||
3287 display
->mOverflowX
== NS_STYLE_OVERFLOW_CLIP
||
3288 display
->mOverflowY
== NS_STYLE_OVERFLOW_VISIBLE
||
3289 display
->mOverflowY
== NS_STYLE_OVERFLOW_CLIP
)) {
3290 // We can't store in the rule tree since a more specific rule might
3291 // change these conditions.
3292 inherited
= PR_TRUE
;
3294 // NS_STYLE_OVERFLOW_CLIP is a deprecated value, so if it's specified
3295 // in only one dimension, convert it to NS_STYLE_OVERFLOW_HIDDEN.
3296 if (display
->mOverflowX
== NS_STYLE_OVERFLOW_CLIP
)
3297 display
->mOverflowX
= NS_STYLE_OVERFLOW_HIDDEN
;
3298 if (display
->mOverflowY
== NS_STYLE_OVERFLOW_CLIP
)
3299 display
->mOverflowY
= NS_STYLE_OVERFLOW_HIDDEN
;
3301 // If 'visible' is specified but doesn't match the other dimension, it
3302 // turns into 'auto'.
3303 if (display
->mOverflowX
== NS_STYLE_OVERFLOW_VISIBLE
)
3304 display
->mOverflowX
= NS_STYLE_OVERFLOW_AUTO
;
3305 if (display
->mOverflowY
== NS_STYLE_OVERFLOW_VISIBLE
)
3306 display
->mOverflowY
= NS_STYLE_OVERFLOW_AUTO
;
3309 // clip property: length, auto, inherit
3310 if (eCSSUnit_Inherit
== displayData
.mClip
.mTop
.GetUnit()) { // if one is inherit, they all are
3311 inherited
= PR_TRUE
;
3312 display
->mClipFlags
= parentDisplay
->mClipFlags
;
3313 display
->mClip
= parentDisplay
->mClip
;
3315 // if one is initial, they all are
3316 else if (eCSSUnit_Initial
== displayData
.mClip
.mTop
.GetUnit()) {
3317 display
->mClipFlags
= NS_STYLE_CLIP_AUTO
;
3318 display
->mClip
.SetRect(0,0,0,0);
3321 PRBool fullAuto
= PR_TRUE
;
3323 display
->mClipFlags
= 0; // clear it
3325 if (eCSSUnit_Auto
== displayData
.mClip
.mTop
.GetUnit()) {
3326 display
->mClip
.y
= 0;
3327 display
->mClipFlags
|= NS_STYLE_CLIP_TOP_AUTO
;
3329 else if (displayData
.mClip
.mTop
.IsLengthUnit()) {
3330 display
->mClip
.y
= CalcLength(displayData
.mClip
.mTop
, aContext
, mPresContext
, inherited
);
3331 fullAuto
= PR_FALSE
;
3333 if (eCSSUnit_Auto
== displayData
.mClip
.mBottom
.GetUnit()) {
3334 // Setting to NS_MAXSIZE for the 'auto' case ensures that
3335 // the clip rect is nonempty. It is important that mClip be
3336 // nonempty if the actual clip rect could be nonempty.
3337 display
->mClip
.height
= NS_MAXSIZE
;
3338 display
->mClipFlags
|= NS_STYLE_CLIP_BOTTOM_AUTO
;
3340 else if (displayData
.mClip
.mBottom
.IsLengthUnit()) {
3341 display
->mClip
.height
= CalcLength(displayData
.mClip
.mBottom
, aContext
, mPresContext
, inherited
) -
3343 fullAuto
= PR_FALSE
;
3345 if (eCSSUnit_Auto
== displayData
.mClip
.mLeft
.GetUnit()) {
3346 display
->mClip
.x
= 0;
3347 display
->mClipFlags
|= NS_STYLE_CLIP_LEFT_AUTO
;
3349 else if (displayData
.mClip
.mLeft
.IsLengthUnit()) {
3350 display
->mClip
.x
= CalcLength(displayData
.mClip
.mLeft
, aContext
, mPresContext
, inherited
);
3351 fullAuto
= PR_FALSE
;
3353 if (eCSSUnit_Auto
== displayData
.mClip
.mRight
.GetUnit()) {
3354 // Setting to NS_MAXSIZE for the 'auto' case ensures that
3355 // the clip rect is nonempty. It is important that mClip be
3356 // nonempty if the actual clip rect could be nonempty.
3357 display
->mClip
.width
= NS_MAXSIZE
;
3358 display
->mClipFlags
|= NS_STYLE_CLIP_RIGHT_AUTO
;
3360 else if (displayData
.mClip
.mRight
.IsLengthUnit()) {
3361 display
->mClip
.width
= CalcLength(displayData
.mClip
.mRight
, aContext
, mPresContext
, inherited
) -
3363 fullAuto
= PR_FALSE
;
3365 display
->mClipFlags
&= ~NS_STYLE_CLIP_TYPE_MASK
;
3367 display
->mClipFlags
|= NS_STYLE_CLIP_AUTO
;
3370 display
->mClipFlags
|= NS_STYLE_CLIP_RECT
;
3374 if (display
->mDisplay
!= NS_STYLE_DISPLAY_NONE
) {
3375 // CSS2 9.7 specifies display type corrections dealing with 'float'
3376 // and 'position'. Since generated content can't be floated or
3377 // positioned, we can deal with it here.
3379 if (nsCSSPseudoElements::firstLetter
== aContext
->GetPseudoType()) {
3380 // a non-floating first-letter must be inline
3381 // XXX this fix can go away once bug 103189 is fixed correctly
3382 display
->mDisplay
= NS_STYLE_DISPLAY_INLINE
;
3384 // We can't cache the data in the rule tree since if a more specific
3385 // rule has 'float: left' we'll end up with the wrong 'display'
3387 inherited
= PR_TRUE
;
3390 if (display
->IsAbsolutelyPositioned()) {
3391 // 1) if position is 'absolute' or 'fixed' then display must be
3392 // block-level and float must be 'none'
3394 // Backup original display value for calculation of a hypothetical
3395 // box (CSS2 10.6.4/10.6.5).
3396 // See nsHTMLReflowState::CalculateHypotheticalBox
3397 display
->mOriginalDisplay
= display
->mDisplay
;
3398 EnsureBlockDisplay(display
->mDisplay
);
3399 display
->mFloats
= NS_STYLE_FLOAT_NONE
;
3401 // We can't cache the data in the rule tree since if a more specific
3402 // rule has 'position: static' we'll end up with problems with the
3403 // 'display' and 'float' properties.
3404 inherited
= PR_TRUE
;
3405 } else if (display
->mFloats
!= NS_STYLE_FLOAT_NONE
) {
3406 // 2) if float is not none, and display is not none, then we must
3407 // set a block-level 'display' type per CSS2.1 section 9.7.
3409 EnsureBlockDisplay(display
->mDisplay
);
3411 // We can't cache the data in the rule tree since if a more specific
3412 // rule has 'float: none' we'll end up with the wrong 'display'
3414 inherited
= PR_TRUE
;
3419 /* Convert the nsCSSValueList into an nsTArray<nsTransformFunction *>. */
3420 const nsCSSValueList
*head
= displayData
.mTransform
;
3422 if (head
!= nsnull
) {
3423 /* There is a chance that we will discover that
3424 * the transform property has been set to 'none,' 'initial,' or 'inherit.'
3425 * If so, process appropriately.
3428 /* If it's 'none,' indicate that there are no transforms. */
3429 if (head
->mValue
.GetUnit() == eCSSUnit_None
)
3430 display
->mTransformPresent
= PR_FALSE
;
3432 /* If we need to inherit, do so by making a full deep-copy. */
3433 else if (head
->mValue
.GetUnit() == eCSSUnit_Inherit
) {
3434 display
->mTransformPresent
= parentDisplay
->mTransformPresent
;
3435 if (parentDisplay
->mTransformPresent
)
3436 display
->mTransform
= parentDisplay
->mTransform
;
3437 inherited
= PR_TRUE
;
3439 /* If it's 'initial', then we reset to empty. */
3440 else if (head
->mValue
.GetUnit() == eCSSUnit_Initial
)
3441 display
->mTransformPresent
= PR_FALSE
;
3443 /* Otherwise, we are looking at a list of CSS tokens. We'll read each of
3444 * them in as an array of nsTransformFunction objects, then will accumulate
3445 * them all together to form the final transform matrix.
3449 display
->mTransform
=
3450 ReadTransforms(head
, aContext
, mPresContext
, inherited
);
3452 /* Make sure to say that this data is valid! */
3453 display
->mTransformPresent
= PR_TRUE
;
3457 /* Convert -moz-transform-origin. */
3458 if (displayData
.mTransformOrigin
.mXValue
.GetUnit() != eCSSUnit_Null
||
3459 displayData
.mTransformOrigin
.mXValue
.GetUnit() != eCSSUnit_Null
) {
3461 /* If X coordinate is an enumerated type, handle it explicitly. */
3462 if (eCSSUnit_Enumerated
== displayData
.mTransformOrigin
.mXValue
.GetUnit())
3463 display
->mTransformOrigin
[0].SetPercentValue
3464 (GetFloatFromBoxPosition
3465 (displayData
.mTransformOrigin
.mXValue
.GetIntValue()));
3467 /* Convert lengths, percents, and inherit. Default value is 50%. */
3471 SetCoord(displayData
.mTransformOrigin
.mXValue
,
3472 display
->mTransformOrigin
[0],
3473 parentDisplay
->mTransformOrigin
[0],
3474 SETCOORD_LPH
| SETCOORD_INITIAL_HALF
,
3475 aContext
, mPresContext
, aInherited
);
3476 NS_ASSERTION(result
, "Malformed -moz-transform-origin parse!");
3479 /* If Y coordinate is an enumerated type, handle it explicitly. */
3480 if (eCSSUnit_Enumerated
== displayData
.mTransformOrigin
.mYValue
.GetUnit())
3481 display
->mTransformOrigin
[1].SetPercentValue
3482 (GetFloatFromBoxPosition
3483 (displayData
.mTransformOrigin
.mYValue
.GetIntValue()));
3485 /* Convert lengths, percents, initial, inherit. */
3489 SetCoord(displayData
.mTransformOrigin
.mYValue
,
3490 display
->mTransformOrigin
[1],
3491 parentDisplay
->mTransformOrigin
[1],
3492 SETCOORD_LPH
| SETCOORD_INITIAL_HALF
,
3493 aContext
, mPresContext
, aInherited
);
3494 NS_ASSERTION(result
, "Malformed -moz-transform-origin parse!");
3498 COMPUTE_END_RESET(Display
, display
)
3502 nsRuleNode::ComputeVisibilityData(void* aStartStruct
,
3503 const nsRuleDataStruct
& aData
,
3504 nsStyleContext
* aContext
,
3505 nsRuleNode
* aHighestNode
,
3506 const RuleDetail aRuleDetail
, PRBool aInherited
)
3508 COMPUTE_START_INHERITED(Visibility
, (mPresContext
),
3509 visibility
, parentVisibility
,
3510 Display
, displayData
)
3512 // direction: enum, inherit, initial
3513 SetDiscrete(displayData
.mDirection
, visibility
->mDirection
, inherited
,
3514 SETDSC_ENUMERATED
, parentVisibility
->mDirection
,
3515 (GET_BIDI_OPTION_DIRECTION(mPresContext
->GetBidi())
3516 == IBMBIDI_TEXTDIRECTION_RTL
)
3517 ? NS_STYLE_DIRECTION_RTL
: NS_STYLE_DIRECTION_LTR
,
3520 // visibility: enum, inherit, initial
3521 SetDiscrete(displayData
.mVisibility
, visibility
->mVisible
, inherited
,
3522 SETDSC_ENUMERATED
, parentVisibility
->mVisible
,
3523 NS_STYLE_VISIBILITY_VISIBLE
, 0, 0, 0, 0);
3525 // lang: string, inherit
3526 // this is not a real CSS property, it is a html attribute mapped to CSS struture
3527 if (eCSSUnit_String
== displayData
.mLang
.GetUnit()) {
3528 if (!gLangService
) {
3529 CallGetService(NS_LANGUAGEATOMSERVICE_CONTRACTID
, &gLangService
);
3534 displayData
.mLang
.GetStringValue(lang
);
3535 visibility
->mLangGroup
= gLangService
->LookupLanguage(lang
);
3539 COMPUTE_END_INHERITED(Visibility
, visibility
)
3543 nsRuleNode::ComputeColorData(void* aStartStruct
,
3544 const nsRuleDataStruct
& aData
,
3545 nsStyleContext
* aContext
,
3546 nsRuleNode
* aHighestNode
,
3547 const RuleDetail aRuleDetail
, PRBool aInherited
)
3549 COMPUTE_START_INHERITED(Color
, (mPresContext
), color
, parentColor
,
3552 // color: color, string, inherit
3553 // Special case for currentColor. According to CSS3, setting color to 'currentColor'
3554 // should behave as if it is inherited
3555 if (colorData
.mColor
.GetUnit() == eCSSUnit_EnumColor
&&
3556 colorData
.mColor
.GetIntValue() == NS_COLOR_CURRENTCOLOR
) {
3557 color
->mColor
= parentColor
->mColor
;
3558 inherited
= PR_TRUE
;
3560 else if (colorData
.mColor
.GetUnit() == eCSSUnit_Initial
) {
3561 color
->mColor
= mPresContext
->DefaultColor();
3564 SetColor(colorData
.mColor
, parentColor
->mColor
, mPresContext
, aContext
, color
->mColor
,
3568 COMPUTE_END_INHERITED(Color
, color
)
3572 nsRuleNode::ComputeBackgroundData(void* aStartStruct
,
3573 const nsRuleDataStruct
& aData
,
3574 nsStyleContext
* aContext
,
3575 nsRuleNode
* aHighestNode
,
3576 const RuleDetail aRuleDetail
,
3579 COMPUTE_START_RESET(Background
, (), bg
, parentBG
, Color
, colorData
)
3581 // save parentFlags in case bg == parentBG and we clobber them later
3582 PRUint8 parentFlags
= parentBG
->mBackgroundFlags
;
3584 // background-color: color, string, inherit
3585 if (eCSSUnit_Initial
== colorData
.mBackColor
.GetUnit()) {
3586 bg
->mBackgroundColor
= NS_RGBA(0, 0, 0, 0);
3587 } else if (!SetColor(colorData
.mBackColor
, parentBG
->mBackgroundColor
,
3588 mPresContext
, aContext
, bg
->mBackgroundColor
,
3590 NS_ASSERTION(eCSSUnit_Null
== colorData
.mBackColor
.GetUnit(),
3591 "unexpected color unit");
3594 // background-image: url (stored as image), none, inherit
3595 if (eCSSUnit_Image
== colorData
.mBackImage
.GetUnit()) {
3596 bg
->mBackgroundImage
= colorData
.mBackImage
.GetImageValue();
3598 else if (eCSSUnit_None
== colorData
.mBackImage
.GetUnit() ||
3599 eCSSUnit_Initial
== colorData
.mBackImage
.GetUnit()) {
3600 bg
->mBackgroundImage
= nsnull
;
3602 else if (eCSSUnit_Inherit
== colorData
.mBackImage
.GetUnit()) {
3603 inherited
= PR_TRUE
;
3604 bg
->mBackgroundImage
= parentBG
->mBackgroundImage
;
3607 if (bg
->mBackgroundImage
) {
3608 bg
->mBackgroundFlags
&= ~NS_STYLE_BG_IMAGE_NONE
;
3610 bg
->mBackgroundFlags
|= NS_STYLE_BG_IMAGE_NONE
;
3613 // background-repeat: enum, inherit, initial
3614 SetDiscrete(colorData
.mBackRepeat
, bg
->mBackgroundRepeat
, inherited
,
3615 SETDSC_ENUMERATED
, parentBG
->mBackgroundRepeat
,
3616 NS_STYLE_BG_REPEAT_XY
, 0, 0, 0, 0);
3618 // background-attachment: enum, inherit, initial
3619 SetDiscrete(colorData
.mBackAttachment
, bg
->mBackgroundAttachment
, inherited
,
3620 SETDSC_ENUMERATED
, parentBG
->mBackgroundAttachment
,
3621 NS_STYLE_BG_ATTACHMENT_SCROLL
, 0, 0, 0, 0);
3623 // background-clip: enum, inherit, initial
3624 SetDiscrete(colorData
.mBackClip
, bg
->mBackgroundClip
, inherited
,
3625 SETDSC_ENUMERATED
, parentBG
->mBackgroundClip
,
3626 NS_STYLE_BG_CLIP_BORDER
, 0, 0, 0, 0);
3628 // background-inline-policy: enum, inherit, initial
3629 SetDiscrete(colorData
.mBackInlinePolicy
, bg
->mBackgroundInlinePolicy
,
3630 inherited
, SETDSC_ENUMERATED
,
3631 parentBG
->mBackgroundInlinePolicy
,
3632 NS_STYLE_BG_INLINE_POLICY_CONTINUOUS
, 0, 0, 0, 0);
3634 // background-origin: enum, inherit, initial
3635 SetDiscrete(colorData
.mBackOrigin
, bg
->mBackgroundOrigin
, inherited
,
3636 SETDSC_ENUMERATED
, parentBG
->mBackgroundOrigin
,
3637 NS_STYLE_BG_ORIGIN_PADDING
, 0, 0, 0, 0);
3639 // background-position: enum, length, percent (flags), inherit
3640 if (eCSSUnit_Percent
== colorData
.mBackPosition
.mXValue
.GetUnit()) {
3641 bg
->mBackgroundXPosition
.mFloat
= colorData
.mBackPosition
.mXValue
.GetPercentValue();
3642 bg
->mBackgroundFlags
|= NS_STYLE_BG_X_POSITION_PERCENT
;
3643 bg
->mBackgroundFlags
&= ~NS_STYLE_BG_X_POSITION_LENGTH
;
3645 else if (colorData
.mBackPosition
.mXValue
.IsLengthUnit()) {
3646 bg
->mBackgroundXPosition
.mCoord
= CalcLength(colorData
.mBackPosition
.mXValue
,
3647 aContext
, mPresContext
, inherited
);
3648 bg
->mBackgroundFlags
|= NS_STYLE_BG_X_POSITION_LENGTH
;
3649 bg
->mBackgroundFlags
&= ~NS_STYLE_BG_X_POSITION_PERCENT
;
3651 else if (eCSSUnit_Enumerated
== colorData
.mBackPosition
.mXValue
.GetUnit()) {
3652 bg
->mBackgroundXPosition
.mFloat
=
3653 GetFloatFromBoxPosition(colorData
.mBackPosition
.mXValue
.GetIntValue());
3655 bg
->mBackgroundFlags
|= NS_STYLE_BG_X_POSITION_PERCENT
;
3656 bg
->mBackgroundFlags
&= ~NS_STYLE_BG_X_POSITION_LENGTH
;
3658 else if (eCSSUnit_Inherit
== colorData
.mBackPosition
.mXValue
.GetUnit()) {
3659 inherited
= PR_TRUE
;
3660 bg
->mBackgroundXPosition
= parentBG
->mBackgroundXPosition
;
3661 bg
->mBackgroundFlags
&= ~(NS_STYLE_BG_X_POSITION_LENGTH
| NS_STYLE_BG_X_POSITION_PERCENT
);
3662 bg
->mBackgroundFlags
|= (parentFlags
& (NS_STYLE_BG_X_POSITION_LENGTH
| NS_STYLE_BG_X_POSITION_PERCENT
));
3664 else if (eCSSUnit_Initial
== colorData
.mBackPosition
.mXValue
.GetUnit()) {
3665 bg
->mBackgroundFlags
&= ~(NS_STYLE_BG_X_POSITION_LENGTH
| NS_STYLE_BG_X_POSITION_PERCENT
);
3668 if (eCSSUnit_Percent
== colorData
.mBackPosition
.mYValue
.GetUnit()) {
3669 bg
->mBackgroundYPosition
.mFloat
= colorData
.mBackPosition
.mYValue
.GetPercentValue();
3670 bg
->mBackgroundFlags
|= NS_STYLE_BG_Y_POSITION_PERCENT
;
3671 bg
->mBackgroundFlags
&= ~NS_STYLE_BG_Y_POSITION_LENGTH
;
3673 else if (colorData
.mBackPosition
.mYValue
.IsLengthUnit()) {
3674 bg
->mBackgroundYPosition
.mCoord
= CalcLength(colorData
.mBackPosition
.mYValue
,
3675 aContext
, mPresContext
, inherited
);
3676 bg
->mBackgroundFlags
|= NS_STYLE_BG_Y_POSITION_LENGTH
;
3677 bg
->mBackgroundFlags
&= ~NS_STYLE_BG_Y_POSITION_PERCENT
;
3679 else if (eCSSUnit_Enumerated
== colorData
.mBackPosition
.mYValue
.GetUnit()) {
3680 bg
->mBackgroundYPosition
.mFloat
=
3681 GetFloatFromBoxPosition(colorData
.mBackPosition
.mYValue
.GetIntValue());
3683 bg
->mBackgroundFlags
|= NS_STYLE_BG_Y_POSITION_PERCENT
;
3684 bg
->mBackgroundFlags
&= ~NS_STYLE_BG_Y_POSITION_LENGTH
;
3686 else if (eCSSUnit_Inherit
== colorData
.mBackPosition
.mYValue
.GetUnit()) {
3687 inherited
= PR_TRUE
;
3688 bg
->mBackgroundYPosition
= parentBG
->mBackgroundYPosition
;
3689 bg
->mBackgroundFlags
&= ~(NS_STYLE_BG_Y_POSITION_LENGTH
| NS_STYLE_BG_Y_POSITION_PERCENT
);
3690 bg
->mBackgroundFlags
|= (parentFlags
& (NS_STYLE_BG_Y_POSITION_LENGTH
| NS_STYLE_BG_Y_POSITION_PERCENT
));
3692 else if (eCSSUnit_Initial
== colorData
.mBackPosition
.mYValue
.GetUnit()) {
3693 bg
->mBackgroundFlags
&= ~(NS_STYLE_BG_Y_POSITION_LENGTH
| NS_STYLE_BG_Y_POSITION_PERCENT
);
3696 COMPUTE_END_RESET(Background
, bg
)
3700 nsRuleNode::ComputeMarginData(void* aStartStruct
,
3701 const nsRuleDataStruct
& aData
,
3702 nsStyleContext
* aContext
,
3703 nsRuleNode
* aHighestNode
,
3704 const RuleDetail aRuleDetail
, PRBool aInherited
)
3706 COMPUTE_START_RESET(Margin
, (), margin
, parentMargin
, Margin
, marginData
)
3708 // margin: length, percent, auto, inherit
3710 nsCSSRect
ourMargin(marginData
.mMargin
);
3711 AdjustLogicalBoxProp(aContext
,
3712 marginData
.mMarginLeftLTRSource
,
3713 marginData
.mMarginLeftRTLSource
,
3714 marginData
.mMarginStart
, marginData
.mMarginEnd
,
3715 NS_SIDE_LEFT
, ourMargin
, inherited
);
3716 AdjustLogicalBoxProp(aContext
,
3717 marginData
.mMarginRightLTRSource
,
3718 marginData
.mMarginRightRTLSource
,
3719 marginData
.mMarginEnd
, marginData
.mMarginStart
,
3720 NS_SIDE_RIGHT
, ourMargin
, inherited
);
3721 NS_FOR_CSS_SIDES(side
) {
3722 nsStyleCoord parentCoord
= parentMargin
->mMargin
.Get(side
);
3723 if (SetCoord(ourMargin
.*(nsCSSRect::sides
[side
]),
3724 coord
, parentCoord
, SETCOORD_LPAH
| SETCOORD_INITIAL_ZERO
,
3725 aContext
, mPresContext
, inherited
)) {
3726 margin
->mMargin
.Set(side
, coord
);
3730 margin
->RecalcData();
3731 COMPUTE_END_RESET(Margin
, margin
)
3735 nsRuleNode::ComputeBorderData(void* aStartStruct
,
3736 const nsRuleDataStruct
& aData
,
3737 nsStyleContext
* aContext
,
3738 nsRuleNode
* aHighestNode
,
3739 const RuleDetail aRuleDetail
, PRBool aInherited
)
3741 COMPUTE_START_RESET(Border
, (mPresContext
), border
, parentBorder
,
3744 // -moz-box-shadow: none, list, inherit, initial
3745 nsCSSValueList
* list
= marginData
.mBoxShadow
;
3747 // This handles 'none' and 'initial'
3748 border
->mBoxShadow
= nsnull
;
3750 if (eCSSUnit_Inherit
== list
->mValue
.GetUnit()) {
3751 inherited
= PR_TRUE
;
3752 border
->mBoxShadow
= parentBorder
->mBoxShadow
;
3753 } else if (eCSSUnit_Array
== list
->mValue
.GetUnit()) {
3755 border
->mBoxShadow
= GetShadowData(list
, aContext
, PR_TRUE
, inherited
);
3759 // border-width, border-*-width: length, enum, inherit
3761 nsCSSRect
ourBorderWidth(marginData
.mBorderWidth
);
3762 AdjustLogicalBoxProp(aContext
,
3763 marginData
.mBorderLeftWidthLTRSource
,
3764 marginData
.mBorderLeftWidthRTLSource
,
3765 marginData
.mBorderStartWidth
,
3766 marginData
.mBorderEndWidth
,
3767 NS_SIDE_LEFT
, ourBorderWidth
, inherited
);
3768 AdjustLogicalBoxProp(aContext
,
3769 marginData
.mBorderRightWidthLTRSource
,
3770 marginData
.mBorderRightWidthRTLSource
,
3771 marginData
.mBorderEndWidth
,
3772 marginData
.mBorderStartWidth
,
3773 NS_SIDE_RIGHT
, ourBorderWidth
, inherited
);
3774 { // scope for compilers with broken |for| loop scoping
3775 NS_FOR_CSS_SIDES(side
) {
3776 const nsCSSValue
&value
= ourBorderWidth
.*(nsCSSRect::sides
[side
]);
3777 NS_ASSERTION(eCSSUnit_Percent
!= value
.GetUnit(),
3778 "Percentage borders not implemented yet "
3779 "If implementing, make sure to fix all consumers of "
3780 "nsStyleBorder, the IsPercentageAwareChild method, "
3781 "the nsAbsoluteContainingBlock::FrameDependsOnContainer "
3783 "nsLineLayout::IsPercentageAwareReplacedElement method "
3784 "and probably some other places");
3785 if (eCSSUnit_Enumerated
== value
.GetUnit()) {
3786 NS_ASSERTION(value
.GetIntValue() == NS_STYLE_BORDER_WIDTH_THIN
||
3787 value
.GetIntValue() == NS_STYLE_BORDER_WIDTH_MEDIUM
||
3788 value
.GetIntValue() == NS_STYLE_BORDER_WIDTH_THICK
,
3789 "Unexpected enum value");
3790 border
->SetBorderWidth(side
,
3791 (mPresContext
->GetBorderWidthTable())[value
.GetIntValue()]);
3793 // OK to pass bad aParentCoord since we're not passing SETCOORD_INHERIT
3794 else if (SetCoord(value
, coord
, nsStyleCoord(), SETCOORD_LENGTH
,
3795 aContext
, mPresContext
, inherited
)) {
3796 NS_ASSERTION(coord
.GetUnit() == eStyleUnit_Coord
, "unexpected unit");
3797 border
->SetBorderWidth(side
, coord
.GetCoordValue());
3799 else if (eCSSUnit_Inherit
== value
.GetUnit()) {
3800 inherited
= PR_TRUE
;
3801 border
->SetBorderWidth(side
,
3802 parentBorder
->GetComputedBorder().side(side
));
3804 else if (eCSSUnit_Initial
== value
.GetUnit()) {
3805 border
->SetBorderWidth(side
,
3806 (mPresContext
->GetBorderWidthTable())[NS_STYLE_BORDER_WIDTH_MEDIUM
]);
3809 NS_ASSERTION(eCSSUnit_Null
== value
.GetUnit(),
3810 "missing case handling border width");
3815 // border-style, border-*-style: enum, none, inherit
3816 nsCSSRect
ourStyle(marginData
.mBorderStyle
);
3817 AdjustLogicalBoxProp(aContext
,
3818 marginData
.mBorderLeftStyleLTRSource
,
3819 marginData
.mBorderLeftStyleRTLSource
,
3820 marginData
.mBorderStartStyle
, marginData
.mBorderEndStyle
,
3821 NS_SIDE_LEFT
, ourStyle
, inherited
);
3822 AdjustLogicalBoxProp(aContext
,
3823 marginData
.mBorderRightStyleLTRSource
,
3824 marginData
.mBorderRightStyleRTLSource
,
3825 marginData
.mBorderEndStyle
, marginData
.mBorderStartStyle
,
3826 NS_SIDE_RIGHT
, ourStyle
, inherited
);
3827 { // scope for compilers with broken |for| loop scoping
3828 NS_FOR_CSS_SIDES(side
) {
3829 const nsCSSValue
&value
= ourStyle
.*(nsCSSRect::sides
[side
]);
3830 nsCSSUnit unit
= value
.GetUnit();
3831 if (eCSSUnit_Enumerated
== unit
) {
3832 border
->SetBorderStyle(side
, value
.GetIntValue());
3834 else if (eCSSUnit_None
== unit
|| eCSSUnit_Initial
== unit
) {
3835 border
->SetBorderStyle(side
, NS_STYLE_BORDER_STYLE_NONE
);
3837 else if (eCSSUnit_Inherit
== unit
) {
3838 inherited
= PR_TRUE
;
3839 border
->SetBorderStyle(side
, parentBorder
->GetBorderStyle(side
));
3844 // -moz-border-*-colors: color, string, enum
3845 nscolor borderColor
;
3846 nscolor unused
= NS_RGB(0,0,0);
3848 { // scope for compilers with broken |for| loop scoping
3849 NS_FOR_CSS_SIDES(side
) {
3850 nsCSSValueList
* list
=
3851 marginData
.mBorderColors
.*(nsCSSValueListRect::sides
[side
]);
3852 // FIXME Bug 389404: Implement inherit and -moz-initial.
3854 // Some composite border color information has been specified for this
3856 border
->EnsureBorderColors();
3857 border
->ClearBorderColors(side
);
3859 if (SetColor(list
->mValue
, unused
, mPresContext
,
3860 aContext
, borderColor
, inherited
))
3861 border
->AppendBorderColor(side
, borderColor
);
3868 // border-color, border-*-color: color, string, enum, inherit
3869 nsCSSRect
ourBorderColor(marginData
.mBorderColor
);
3871 AdjustLogicalBoxProp(aContext
,
3872 marginData
.mBorderLeftColorLTRSource
,
3873 marginData
.mBorderLeftColorRTLSource
,
3874 marginData
.mBorderStartColor
, marginData
.mBorderEndColor
,
3875 NS_SIDE_LEFT
, ourBorderColor
, inherited
);
3876 AdjustLogicalBoxProp(aContext
,
3877 marginData
.mBorderRightColorLTRSource
,
3878 marginData
.mBorderRightColorRTLSource
,
3879 marginData
.mBorderEndColor
, marginData
.mBorderStartColor
,
3880 NS_SIDE_RIGHT
, ourBorderColor
, inherited
);
3881 { // scope for compilers with broken |for| loop scoping
3882 NS_FOR_CSS_SIDES(side
) {
3883 const nsCSSValue
&value
= ourBorderColor
.*(nsCSSRect::sides
[side
]);
3884 if (eCSSUnit_Inherit
== value
.GetUnit()) {
3885 if (parentContext
) {
3886 inherited
= PR_TRUE
;
3887 parentBorder
->GetBorderColor(side
, borderColor
, foreground
);
3889 // We want to inherit the color from the parent, not use the
3890 // color on the element where this chunk of style data will be
3891 // used. We can ensure that the data for the parent are fully
3892 // computed (unlike for the element where this will be used, for
3893 // which the color could be specified on a more specific rule).
3894 border
->SetBorderColor(side
, parentContext
->GetStyleColor()->mColor
);
3896 border
->SetBorderColor(side
, borderColor
);
3899 border
->SetBorderToForeground(side
);
3902 else if (SetColor(value
, unused
, mPresContext
, aContext
, borderColor
, inherited
)) {
3903 border
->SetBorderColor(side
, borderColor
);
3905 else if (eCSSUnit_Enumerated
== value
.GetUnit()) {
3906 switch (value
.GetIntValue()) {
3907 case NS_STYLE_COLOR_MOZ_USE_TEXT_COLOR
:
3908 border
->SetBorderToForeground(side
);
3912 else if (eCSSUnit_Initial
== value
.GetUnit()) {
3913 border
->SetBorderToForeground(side
);
3918 // -moz-border-radius: length, percent, inherit
3920 const nsCSSCornerSizes
& borderRadius
= marginData
.mBorderRadius
;
3921 NS_FOR_CSS_HALF_CORNERS(corner
) {
3922 nsStyleCoord parentCoord
= parentBorder
->mBorderRadius
.Get(corner
);
3923 if (SetCoord(borderRadius
.GetHalfCorner(corner
),
3924 coord
, parentCoord
, SETCOORD_LPH
| SETCOORD_INITIAL_ZERO
,
3925 aContext
, mPresContext
, inherited
))
3926 border
->mBorderRadius
.Set(corner
, coord
);
3930 // float-edge: enum, inherit, initial
3931 SetDiscrete(marginData
.mFloatEdge
, border
->mFloatEdge
, inherited
,
3932 SETDSC_ENUMERATED
, parentBorder
->mFloatEdge
,
3933 NS_STYLE_FLOAT_EDGE_CONTENT
, 0, 0, 0, 0);
3936 if (eCSSUnit_Array
== marginData
.mBorderImage
.GetUnit()) {
3937 nsCSSValue::Array
*arr
= marginData
.mBorderImage
.GetArrayValue();
3940 if (eCSSUnit_Image
== arr
->Item(0).GetUnit()) {
3941 border
->SetBorderImage(arr
->Item(0).GetImageValue());
3944 // the numbers saying where to split the image
3945 NS_FOR_CSS_SIDES(side
) {
3946 // an uninitialized parentCoord is ok because I'm not passing SETCOORD_INHERIT
3947 if (SetCoord(arr
->Item(1 + side
), coord
, nsStyleCoord(),
3948 SETCOORD_FACTOR
| SETCOORD_PERCENT
, aContext
,
3949 mPresContext
, inherited
)) {
3950 border
->mBorderImageSplit
.Set(side
, coord
);
3954 // possible replacement for border-width
3955 // if have one - have all four (see CSSParserImpl::ParseBorderImage())
3956 if (eCSSUnit_Null
!= arr
->Item(5).GetUnit()) {
3957 NS_FOR_CSS_SIDES(side
) {
3958 // an uninitialized parentCoord is ok because I'm not passing SETCOORD_INHERIT
3959 if (!SetCoord(arr
->Item(5 + side
), coord
, nsStyleCoord(),
3960 SETCOORD_LENGTH
, aContext
, mPresContext
, inherited
)) {
3961 NS_NOTREACHED("SetCoord for border-width replacement from border-image failed");
3963 if (coord
.GetUnit() == eStyleUnit_Coord
) {
3964 border
->SetBorderImageWidthOverride(side
, coord
.GetCoordValue());
3966 NS_WARNING("a border-width replacement from border-image "
3967 "has a unit that's not eStyleUnit_Coord");
3968 border
->SetBorderImageWidthOverride(side
, 0);
3971 border
->mHaveBorderImageWidth
= PR_TRUE
;
3973 border
->mHaveBorderImageWidth
= PR_FALSE
;
3976 // stretch/round/repeat keywords
3977 if (eCSSUnit_Null
== arr
->Item(9).GetUnit()) {
3978 // default, both horizontal and vertical are stretch
3979 border
->mBorderImageHFill
= NS_STYLE_BORDER_IMAGE_STRETCH
;
3980 border
->mBorderImageVFill
= NS_STYLE_BORDER_IMAGE_STRETCH
;
3982 // have horizontal value
3983 border
->mBorderImageHFill
= arr
->Item(9).GetIntValue();
3984 if (eCSSUnit_Null
== arr
->Item(10).GetUnit()) {
3985 // vertical same as horizontal
3986 border
->mBorderImageVFill
= border
->mBorderImageHFill
;
3988 // have vertical value
3989 border
->mBorderImageVFill
= arr
->Item(10).GetIntValue();
3992 } else if (eCSSUnit_None
== marginData
.mBorderImage
.GetUnit() ||
3993 eCSSUnit_Initial
== marginData
.mBorderImage
.GetUnit()) {
3994 border
->mHaveBorderImageWidth
= PR_FALSE
;
3995 border
->SetBorderImage(nsnull
);
3996 } else if (eCSSUnit_Inherit
== marginData
.mBorderImage
.GetUnit()) {
3997 NS_FOR_CSS_SIDES(side
) {
3998 border
->SetBorderImageWidthOverride(side
, parentBorder
->mBorderImageWidth
.side(side
));
4000 border
->mBorderImageSplit
= parentBorder
->mBorderImageSplit
;
4001 border
->mBorderImageHFill
= parentBorder
->mBorderImageHFill
;
4002 border
->mBorderImageVFill
= parentBorder
->mBorderImageVFill
;
4003 border
->mHaveBorderImageWidth
= parentBorder
->mHaveBorderImageWidth
;
4004 border
->SetBorderImage(parentBorder
->GetBorderImage());
4007 COMPUTE_END_RESET(Border
, border
)
4011 nsRuleNode::ComputePaddingData(void* aStartStruct
,
4012 const nsRuleDataStruct
& aData
,
4013 nsStyleContext
* aContext
,
4014 nsRuleNode
* aHighestNode
,
4015 const RuleDetail aRuleDetail
, PRBool aInherited
)
4017 COMPUTE_START_RESET(Padding
, (), padding
, parentPadding
, Margin
, marginData
)
4019 // padding: length, percent, inherit
4021 nsCSSRect
ourPadding(marginData
.mPadding
);
4022 AdjustLogicalBoxProp(aContext
,
4023 marginData
.mPaddingLeftLTRSource
,
4024 marginData
.mPaddingLeftRTLSource
,
4025 marginData
.mPaddingStart
, marginData
.mPaddingEnd
,
4026 NS_SIDE_LEFT
, ourPadding
, inherited
);
4027 AdjustLogicalBoxProp(aContext
,
4028 marginData
.mPaddingRightLTRSource
,
4029 marginData
.mPaddingRightRTLSource
,
4030 marginData
.mPaddingEnd
, marginData
.mPaddingStart
,
4031 NS_SIDE_RIGHT
, ourPadding
, inherited
);
4032 NS_FOR_CSS_SIDES(side
) {
4033 nsStyleCoord parentCoord
= parentPadding
->mPadding
.Get(side
);
4034 if (SetCoord(ourPadding
.*(nsCSSRect::sides
[side
]),
4035 coord
, parentCoord
, SETCOORD_LPH
| SETCOORD_INITIAL_ZERO
,
4036 aContext
, mPresContext
, inherited
)) {
4037 padding
->mPadding
.Set(side
, coord
);
4041 padding
->RecalcData();
4042 COMPUTE_END_RESET(Padding
, padding
)
4046 nsRuleNode::ComputeOutlineData(void* aStartStruct
,
4047 const nsRuleDataStruct
& aData
,
4048 nsStyleContext
* aContext
,
4049 nsRuleNode
* aHighestNode
,
4050 const RuleDetail aRuleDetail
, PRBool aInherited
)
4052 COMPUTE_START_RESET(Outline
, (mPresContext
), outline
, parentOutline
,
4055 // outline-width: length, enum, inherit
4056 if (eCSSUnit_Initial
== marginData
.mOutlineWidth
.GetUnit()) {
4057 outline
->mOutlineWidth
=
4058 nsStyleCoord(NS_STYLE_BORDER_WIDTH_MEDIUM
, eStyleUnit_Enumerated
);
4061 SetCoord(marginData
.mOutlineWidth
, outline
->mOutlineWidth
,
4062 parentOutline
->mOutlineWidth
, SETCOORD_LEH
, aContext
,
4063 mPresContext
, inherited
);
4066 // outline-offset: length, inherit
4067 nsStyleCoord tempCoord
;
4068 if (SetCoord(marginData
.mOutlineOffset
, tempCoord
,
4069 parentOutline
->mOutlineOffset
,
4070 SETCOORD_LH
| SETCOORD_INITIAL_ZERO
, aContext
, mPresContext
,
4072 outline
->mOutlineOffset
= tempCoord
.GetCoordValue();
4074 NS_ASSERTION(marginData
.mOutlineOffset
.GetUnit() == eCSSUnit_Null
,
4078 // outline-color: color, string, enum, inherit
4079 nscolor outlineColor
;
4080 nscolor unused
= NS_RGB(0,0,0);
4081 if (eCSSUnit_Inherit
== marginData
.mOutlineColor
.GetUnit()) {
4082 if (parentContext
) {
4083 inherited
= PR_TRUE
;
4084 if (parentOutline
->GetOutlineColor(outlineColor
))
4085 outline
->SetOutlineColor(outlineColor
);
4087 #ifdef GFX_HAS_INVERT
4088 outline
->SetOutlineInitialColor();
4090 // We want to inherit the color from the parent, not use the
4091 // color on the element where this chunk of style data will be
4092 // used. We can ensure that the data for the parent are fully
4093 // computed (unlike for the element where this will be used, for
4094 // which the color could be specified on a more specific rule).
4095 outline
->SetOutlineColor(parentContext
->GetStyleColor()->mColor
);
4099 outline
->SetOutlineInitialColor();
4102 else if (SetColor(marginData
.mOutlineColor
, unused
, mPresContext
, aContext
, outlineColor
, inherited
))
4103 outline
->SetOutlineColor(outlineColor
);
4104 else if (eCSSUnit_Enumerated
== marginData
.mOutlineColor
.GetUnit() ||
4105 eCSSUnit_Initial
== marginData
.mOutlineColor
.GetUnit()) {
4106 outline
->SetOutlineInitialColor();
4109 // -moz-outline-radius: length, percent, inherit
4112 const nsCSSCornerSizes
& outlineRadius
= marginData
.mOutlineRadius
;
4113 NS_FOR_CSS_HALF_CORNERS(corner
) {
4114 nsStyleCoord parentCoord
= parentOutline
->mOutlineRadius
.Get(corner
);
4115 if (SetCoord(outlineRadius
.GetHalfCorner(corner
),
4116 coord
, parentCoord
, SETCOORD_LPH
| SETCOORD_INITIAL_ZERO
,
4117 aContext
, mPresContext
, inherited
))
4118 outline
->mOutlineRadius
.Set(corner
, coord
);
4122 // outline-style: auto, enum, none, inherit, initial
4123 // cannot use SetDiscrete because of SetOutlineStyle
4124 if (eCSSUnit_Enumerated
== marginData
.mOutlineStyle
.GetUnit())
4125 outline
->SetOutlineStyle(marginData
.mOutlineStyle
.GetIntValue());
4126 else if (eCSSUnit_None
== marginData
.mOutlineStyle
.GetUnit() ||
4127 eCSSUnit_Initial
== marginData
.mOutlineStyle
.GetUnit())
4128 outline
->SetOutlineStyle(NS_STYLE_BORDER_STYLE_NONE
);
4129 else if (eCSSUnit_Auto
== marginData
.mOutlineStyle
.GetUnit()) {
4130 outline
->SetOutlineStyle(NS_STYLE_BORDER_STYLE_AUTO
);
4131 } else if (eCSSUnit_Inherit
== marginData
.mOutlineStyle
.GetUnit()) {
4132 inherited
= PR_TRUE
;
4133 outline
->SetOutlineStyle(parentOutline
->GetOutlineStyle());
4136 outline
->RecalcData(mPresContext
);
4137 COMPUTE_END_RESET(Outline
, outline
)
4141 nsRuleNode::ComputeListData(void* aStartStruct
,
4142 const nsRuleDataStruct
& aData
,
4143 nsStyleContext
* aContext
,
4144 nsRuleNode
* aHighestNode
,
4145 const RuleDetail aRuleDetail
, PRBool aInherited
)
4147 COMPUTE_START_INHERITED(List
, (), list
, parentList
, List
, listData
)
4149 // list-style-type: enum, none, inherit, initial
4150 SetDiscrete(listData
.mType
, list
->mListStyleType
, inherited
,
4151 SETDSC_ENUMERATED
| SETDSC_NONE
, parentList
->mListStyleType
,
4152 NS_STYLE_LIST_STYLE_DISC
, 0,
4153 NS_STYLE_LIST_STYLE_NONE
, 0, 0);
4155 // list-style-image: url, none, inherit
4156 if (eCSSUnit_Image
== listData
.mImage
.GetUnit()) {
4157 list
->mListStyleImage
= listData
.mImage
.GetImageValue();
4159 else if (eCSSUnit_None
== listData
.mImage
.GetUnit() ||
4160 eCSSUnit_Initial
== listData
.mImage
.GetUnit()) {
4161 list
->mListStyleImage
= nsnull
;
4163 else if (eCSSUnit_Inherit
== listData
.mImage
.GetUnit()) {
4164 inherited
= PR_TRUE
;
4165 list
->mListStyleImage
= parentList
->mListStyleImage
;
4168 // list-style-position: enum, inherit, initial
4169 SetDiscrete(listData
.mPosition
, list
->mListStylePosition
, inherited
,
4170 SETDSC_ENUMERATED
, parentList
->mListStylePosition
,
4171 NS_STYLE_LIST_STYLE_POSITION_OUTSIDE
, 0, 0, 0, 0);
4173 // image region property: length, auto, inherit
4174 if (eCSSUnit_Inherit
== listData
.mImageRegion
.mTop
.GetUnit()) { // if one is inherit, they all are
4175 inherited
= PR_TRUE
;
4176 list
->mImageRegion
= parentList
->mImageRegion
;
4178 // if one is -moz-initial, they all are
4179 else if (eCSSUnit_Initial
== listData
.mImageRegion
.mTop
.GetUnit()) {
4180 list
->mImageRegion
.Empty();
4183 if (eCSSUnit_Auto
== listData
.mImageRegion
.mTop
.GetUnit())
4184 list
->mImageRegion
.y
= 0;
4185 else if (listData
.mImageRegion
.mTop
.IsLengthUnit())
4186 list
->mImageRegion
.y
= CalcLength(listData
.mImageRegion
.mTop
, aContext
, mPresContext
, inherited
);
4188 if (eCSSUnit_Auto
== listData
.mImageRegion
.mBottom
.GetUnit())
4189 list
->mImageRegion
.height
= 0;
4190 else if (listData
.mImageRegion
.mBottom
.IsLengthUnit())
4191 list
->mImageRegion
.height
= CalcLength(listData
.mImageRegion
.mBottom
, aContext
,
4192 mPresContext
, inherited
) - list
->mImageRegion
.y
;
4194 if (eCSSUnit_Auto
== listData
.mImageRegion
.mLeft
.GetUnit())
4195 list
->mImageRegion
.x
= 0;
4196 else if (listData
.mImageRegion
.mLeft
.IsLengthUnit())
4197 list
->mImageRegion
.x
= CalcLength(listData
.mImageRegion
.mLeft
, aContext
, mPresContext
, inherited
);
4199 if (eCSSUnit_Auto
== listData
.mImageRegion
.mRight
.GetUnit())
4200 list
->mImageRegion
.width
= 0;
4201 else if (listData
.mImageRegion
.mRight
.IsLengthUnit())
4202 list
->mImageRegion
.width
= CalcLength(listData
.mImageRegion
.mRight
, aContext
, mPresContext
, inherited
) -
4203 list
->mImageRegion
.x
;
4206 COMPUTE_END_INHERITED(List
, list
)
4210 nsRuleNode::ComputePositionData(void* aStartStruct
,
4211 const nsRuleDataStruct
& aData
,
4212 nsStyleContext
* aContext
,
4213 nsRuleNode
* aHighestNode
,
4214 const RuleDetail aRuleDetail
, PRBool aInherited
)
4216 COMPUTE_START_RESET(Position
, (), pos
, parentPos
, Position
, posData
)
4218 // box offsets: length, percent, auto, inherit
4220 NS_FOR_CSS_SIDES(side
) {
4221 nsStyleCoord parentCoord
= parentPos
->mOffset
.Get(side
);
4222 if (SetCoord(posData
.mOffset
.*(nsCSSRect::sides
[side
]),
4223 coord
, parentCoord
, SETCOORD_LPAH
| SETCOORD_INITIAL_AUTO
,
4224 aContext
, mPresContext
, inherited
)) {
4225 pos
->mOffset
.Set(side
, coord
);
4229 SetCoord(posData
.mWidth
, pos
->mWidth
, parentPos
->mWidth
,
4230 SETCOORD_LPAEH
| SETCOORD_INITIAL_AUTO
, aContext
,
4231 mPresContext
, inherited
);
4232 SetCoord(posData
.mMinWidth
, pos
->mMinWidth
, parentPos
->mMinWidth
,
4233 SETCOORD_LPEH
| SETCOORD_INITIAL_ZERO
, aContext
,
4234 mPresContext
, inherited
);
4235 SetCoord(posData
.mMaxWidth
, pos
->mMaxWidth
, parentPos
->mMaxWidth
,
4236 SETCOORD_LPOEH
| SETCOORD_INITIAL_NONE
, aContext
,
4237 mPresContext
, inherited
);
4239 SetCoord(posData
.mHeight
, pos
->mHeight
, parentPos
->mHeight
,
4240 SETCOORD_LPAH
| SETCOORD_INITIAL_AUTO
, aContext
,
4241 mPresContext
, inherited
);
4242 SetCoord(posData
.mMinHeight
, pos
->mMinHeight
, parentPos
->mMinHeight
,
4243 SETCOORD_LPH
| SETCOORD_INITIAL_ZERO
, aContext
,
4244 mPresContext
, inherited
);
4245 SetCoord(posData
.mMaxHeight
, pos
->mMaxHeight
, parentPos
->mMaxHeight
,
4246 SETCOORD_LPOH
| SETCOORD_INITIAL_NONE
, aContext
,
4247 mPresContext
, inherited
);
4249 // box-sizing: enum, inherit, initial
4250 SetDiscrete(posData
.mBoxSizing
, pos
->mBoxSizing
, inherited
,
4251 SETDSC_ENUMERATED
, parentPos
->mBoxSizing
,
4252 NS_STYLE_BOX_SIZING_CONTENT
, 0, 0, 0, 0);
4255 if (! SetCoord(posData
.mZIndex
, pos
->mZIndex
, parentPos
->mZIndex
,
4256 SETCOORD_IA
| SETCOORD_INITIAL_AUTO
, aContext
,
4257 nsnull
, inherited
)) {
4258 if (eCSSUnit_Inherit
== posData
.mZIndex
.GetUnit()) {
4259 // handle inherit, because it's ok to inherit 'auto' here
4260 inherited
= PR_TRUE
;
4261 pos
->mZIndex
= parentPos
->mZIndex
;
4265 COMPUTE_END_RESET(Position
, pos
)
4269 nsRuleNode::ComputeTableData(void* aStartStruct
,
4270 const nsRuleDataStruct
& aData
,
4271 nsStyleContext
* aContext
,
4272 nsRuleNode
* aHighestNode
,
4273 const RuleDetail aRuleDetail
, PRBool aInherited
)
4275 COMPUTE_START_RESET(Table
, (), table
, parentTable
, Table
, tableData
)
4277 // table-layout: auto, enum, inherit, initial
4278 SetDiscrete(tableData
.mLayout
, table
->mLayoutStrategy
, inherited
,
4279 SETDSC_ENUMERATED
| SETDSC_AUTO
,
4280 parentTable
->mLayoutStrategy
,
4281 NS_STYLE_TABLE_LAYOUT_AUTO
,
4282 NS_STYLE_TABLE_LAYOUT_AUTO
, 0, 0, 0);
4284 // rules: enum (not a real CSS prop)
4285 if (eCSSUnit_Enumerated
== tableData
.mRules
.GetUnit())
4286 table
->mRules
= tableData
.mRules
.GetIntValue();
4288 // frame: enum (not a real CSS prop)
4289 if (eCSSUnit_Enumerated
== tableData
.mFrame
.GetUnit())
4290 table
->mFrame
= tableData
.mFrame
.GetIntValue();
4292 // cols: enum, int (not a real CSS prop)
4293 if (eCSSUnit_Enumerated
== tableData
.mCols
.GetUnit() ||
4294 eCSSUnit_Integer
== tableData
.mCols
.GetUnit())
4295 table
->mCols
= tableData
.mCols
.GetIntValue();
4297 // span: pixels (not a real CSS prop)
4298 if (eCSSUnit_Enumerated
== tableData
.mSpan
.GetUnit() ||
4299 eCSSUnit_Integer
== tableData
.mSpan
.GetUnit())
4300 table
->mSpan
= tableData
.mSpan
.GetIntValue();
4302 COMPUTE_END_RESET(Table
, table
)
4306 nsRuleNode::ComputeTableBorderData(void* aStartStruct
,
4307 const nsRuleDataStruct
& aData
,
4308 nsStyleContext
* aContext
,
4309 nsRuleNode
* aHighestNode
,
4310 const RuleDetail aRuleDetail
, PRBool aInherited
)
4312 COMPUTE_START_INHERITED(TableBorder
, (mPresContext
), table
, parentTable
,
4315 // border-collapse: enum, inherit, initial
4316 SetDiscrete(tableData
.mBorderCollapse
, table
->mBorderCollapse
, inherited
,
4317 SETDSC_ENUMERATED
, parentTable
->mBorderCollapse
,
4318 NS_STYLE_BORDER_SEPARATE
, 0, 0, 0, 0);
4320 // border-spacing-x: length, inherit
4321 nsStyleCoord tempCoord
;
4322 if (SetCoord(tableData
.mBorderSpacing
.mXValue
, tempCoord
,
4323 parentTable
->mBorderSpacingX
,
4324 SETCOORD_LH
| SETCOORD_INITIAL_ZERO
,
4325 aContext
, mPresContext
, inherited
)) {
4326 table
->mBorderSpacingX
= tempCoord
.GetCoordValue();
4328 NS_ASSERTION(tableData
.mBorderSpacing
.mXValue
.GetUnit() == eCSSUnit_Null
,
4332 // border-spacing-y: length, inherit
4333 if (SetCoord(tableData
.mBorderSpacing
.mYValue
, tempCoord
,
4334 parentTable
->mBorderSpacingY
,
4335 SETCOORD_LH
| SETCOORD_INITIAL_ZERO
,
4336 aContext
, mPresContext
, inherited
)) {
4337 table
->mBorderSpacingY
= tempCoord
.GetCoordValue();
4339 NS_ASSERTION(tableData
.mBorderSpacing
.mYValue
.GetUnit() == eCSSUnit_Null
,
4343 // caption-side: enum, inherit, initial
4344 SetDiscrete(tableData
.mCaptionSide
, table
->mCaptionSide
, inherited
,
4345 SETDSC_ENUMERATED
, parentTable
->mCaptionSide
,
4346 NS_STYLE_CAPTION_SIDE_TOP
, 0, 0, 0, 0);
4348 // empty-cells: enum, inherit, initial
4349 SetDiscrete(tableData
.mEmptyCells
, table
->mEmptyCells
, inherited
,
4350 SETDSC_ENUMERATED
, parentTable
->mEmptyCells
,
4351 (mPresContext
->CompatibilityMode() == eCompatibility_NavQuirks
)
4352 ? NS_STYLE_TABLE_EMPTY_CELLS_SHOW_BACKGROUND
4353 : NS_STYLE_TABLE_EMPTY_CELLS_SHOW
,
4356 COMPUTE_END_INHERITED(TableBorder
, table
)
4360 nsRuleNode::ComputeContentData(void* aStartStruct
,
4361 const nsRuleDataStruct
& aData
,
4362 nsStyleContext
* aContext
,
4363 nsRuleNode
* aHighestNode
,
4364 const RuleDetail aRuleDetail
, PRBool aInherited
)
4366 COMPUTE_START_RESET(Content
, (), content
, parentContent
,
4367 Content
, contentData
)
4369 // content: [string, url, counter, attr, enum]+, normal, none, inherit
4371 nsAutoString buffer
;
4372 nsCSSValueList
* contentValue
= contentData
.mContent
;
4374 if (eCSSUnit_Normal
== contentValue
->mValue
.GetUnit() ||
4375 eCSSUnit_None
== contentValue
->mValue
.GetUnit() ||
4376 eCSSUnit_Initial
== contentValue
->mValue
.GetUnit()) {
4377 // "normal", "none", and "initial" all mean no content
4378 content
->AllocateContents(0);
4380 else if (eCSSUnit_Inherit
== contentValue
->mValue
.GetUnit()) {
4381 inherited
= PR_TRUE
;
4382 count
= parentContent
->ContentCount();
4383 if (NS_SUCCEEDED(content
->AllocateContents(count
))) {
4384 while (0 < count
--) {
4385 content
->ContentAt(count
) = parentContent
->ContentAt(count
);
4391 while (contentValue
) {
4393 contentValue
= contentValue
->mNext
;
4395 if (NS_SUCCEEDED(content
->AllocateContents(count
))) {
4396 const nsAutoString nullStr
;
4398 contentValue
= contentData
.mContent
;
4399 while (contentValue
) {
4400 const nsCSSValue
& value
= contentValue
->mValue
;
4401 nsCSSUnit unit
= value
.GetUnit();
4402 nsStyleContentType type
;
4403 nsStyleContentData
&data
= content
->ContentAt(count
++);
4405 case eCSSUnit_String
: type
= eStyleContentType_String
; break;
4406 case eCSSUnit_Image
: type
= eStyleContentType_Image
; break;
4407 case eCSSUnit_Attr
: type
= eStyleContentType_Attr
; break;
4408 case eCSSUnit_Counter
: type
= eStyleContentType_Counter
; break;
4409 case eCSSUnit_Counters
: type
= eStyleContentType_Counters
; break;
4410 case eCSSUnit_Enumerated
:
4411 switch (value
.GetIntValue()) {
4412 case NS_STYLE_CONTENT_OPEN_QUOTE
:
4413 type
= eStyleContentType_OpenQuote
; break;
4414 case NS_STYLE_CONTENT_CLOSE_QUOTE
:
4415 type
= eStyleContentType_CloseQuote
; break;
4416 case NS_STYLE_CONTENT_NO_OPEN_QUOTE
:
4417 type
= eStyleContentType_NoOpenQuote
; break;
4418 case NS_STYLE_CONTENT_NO_CLOSE_QUOTE
:
4419 type
= eStyleContentType_NoCloseQuote
; break;
4420 case NS_STYLE_CONTENT_ALT_CONTENT
:
4421 type
= eStyleContentType_AltContent
; break;
4423 NS_ERROR("bad content value");
4427 NS_ERROR("bad content type");
4430 if (type
== eStyleContentType_Image
) {
4431 data
.mContent
.mImage
= value
.GetImageValue();
4432 NS_IF_ADDREF(data
.mContent
.mImage
);
4434 else if (type
<= eStyleContentType_Attr
) {
4435 value
.GetStringValue(buffer
);
4437 data
.mContent
.mString
= NS_strdup(buffer
.get());
4439 else if (type
<= eStyleContentType_Counters
) {
4440 data
.mContent
.mCounters
= value
.GetArrayValue();
4441 data
.mContent
.mCounters
->AddRef();
4444 data
.mContent
.mString
= nsnull
;
4446 contentValue
= contentValue
->mNext
;
4452 // counter-increment: [string [int]]+, none, inherit
4453 nsCSSValuePairList
* ourIncrement
= contentData
.mCounterIncrement
;
4455 if (eCSSUnit_None
== ourIncrement
->mXValue
.GetUnit() ||
4456 eCSSUnit_Initial
== ourIncrement
->mXValue
.GetUnit()) {
4457 content
->AllocateCounterIncrements(0);
4459 else if (eCSSUnit_Inherit
== ourIncrement
->mXValue
.GetUnit()) {
4460 inherited
= PR_TRUE
;
4461 count
= parentContent
->CounterIncrementCount();
4462 if (NS_SUCCEEDED(content
->AllocateCounterIncrements(count
))) {
4463 while (0 < count
--) {
4464 const nsStyleCounterData
*data
=
4465 parentContent
->GetCounterIncrementAt(count
);
4466 content
->SetCounterIncrementAt(count
, data
->mCounter
, data
->mValue
);
4470 else if (eCSSUnit_String
== ourIncrement
->mXValue
.GetUnit()) {
4472 while (ourIncrement
) {
4474 ourIncrement
= ourIncrement
->mNext
;
4476 if (NS_SUCCEEDED(content
->AllocateCounterIncrements(count
))) {
4478 ourIncrement
= contentData
.mCounterIncrement
;
4479 while (ourIncrement
) {
4481 if (eCSSUnit_Integer
== ourIncrement
->mYValue
.GetUnit()) {
4482 increment
= ourIncrement
->mYValue
.GetIntValue();
4487 ourIncrement
->mXValue
.GetStringValue(buffer
);
4488 content
->SetCounterIncrementAt(count
++, buffer
, increment
);
4489 ourIncrement
= ourIncrement
->mNext
;
4495 // counter-reset: [string [int]]+, none, inherit
4496 nsCSSValuePairList
* ourReset
= contentData
.mCounterReset
;
4498 if (eCSSUnit_None
== ourReset
->mXValue
.GetUnit() ||
4499 eCSSUnit_Initial
== ourReset
->mXValue
.GetUnit()) {
4500 content
->AllocateCounterResets(0);
4502 else if (eCSSUnit_Inherit
== ourReset
->mXValue
.GetUnit()) {
4503 inherited
= PR_TRUE
;
4504 count
= parentContent
->CounterResetCount();
4505 if (NS_SUCCEEDED(content
->AllocateCounterResets(count
))) {
4506 while (0 < count
--) {
4507 const nsStyleCounterData
*data
=
4508 parentContent
->GetCounterResetAt(count
);
4509 content
->SetCounterResetAt(count
, data
->mCounter
, data
->mValue
);
4513 else if (eCSSUnit_String
== ourReset
->mXValue
.GetUnit()) {
4517 ourReset
= ourReset
->mNext
;
4519 if (NS_SUCCEEDED(content
->AllocateCounterResets(count
))) {
4521 ourReset
= contentData
.mCounterReset
;
4524 if (eCSSUnit_Integer
== ourReset
->mYValue
.GetUnit()) {
4525 reset
= ourReset
->mYValue
.GetIntValue();
4530 ourReset
->mXValue
.GetStringValue(buffer
);
4531 content
->SetCounterResetAt(count
++, buffer
, reset
);
4532 ourReset
= ourReset
->mNext
;
4538 // marker-offset: length, auto, inherit
4539 SetCoord(contentData
.mMarkerOffset
, content
->mMarkerOffset
, parentContent
->mMarkerOffset
,
4540 SETCOORD_LH
| SETCOORD_AUTO
| SETCOORD_INITIAL_AUTO
, aContext
,
4541 mPresContext
, inherited
);
4543 COMPUTE_END_RESET(Content
, content
)
4547 nsRuleNode::ComputeQuotesData(void* aStartStruct
,
4548 const nsRuleDataStruct
& aData
,
4549 nsStyleContext
* aContext
,
4550 nsRuleNode
* aHighestNode
,
4551 const RuleDetail aRuleDetail
, PRBool aInherited
)
4553 COMPUTE_START_INHERITED(Quotes
, (), quotes
, parentQuotes
,
4554 Content
, contentData
)
4556 // quotes: inherit, initial, none, [string string]+
4557 nsCSSValuePairList
* ourQuotes
= contentData
.mQuotes
;
4559 if (eCSSUnit_Inherit
== ourQuotes
->mXValue
.GetUnit()) {
4560 inherited
= PR_TRUE
;
4561 quotes
->CopyFrom(*parentQuotes
);
4563 else if (eCSSUnit_Initial
== ourQuotes
->mXValue
.GetUnit()) {
4564 quotes
->SetInitial();
4566 else if (eCSSUnit_None
== ourQuotes
->mXValue
.GetUnit()) {
4567 quotes
->AllocateQuotes(0);
4569 else if (eCSSUnit_String
== ourQuotes
->mXValue
.GetUnit()) {
4570 nsAutoString buffer
;
4571 nsAutoString closeBuffer
;
4576 ourQuotes
= ourQuotes
->mNext
;
4578 if (NS_SUCCEEDED(quotes
->AllocateQuotes(count
))) {
4580 ourQuotes
= contentData
.mQuotes
;
4582 ourQuotes
->mXValue
.GetStringValue(buffer
);
4583 ourQuotes
->mYValue
.GetStringValue(closeBuffer
);
4585 Unquote(closeBuffer
);
4586 quotes
->SetQuotesAt(count
++, buffer
, closeBuffer
);
4587 ourQuotes
= ourQuotes
->mNext
;
4593 COMPUTE_END_INHERITED(Quotes
, quotes
)
4597 nsRuleNode::ComputeXULData(void* aStartStruct
,
4598 const nsRuleDataStruct
& aData
,
4599 nsStyleContext
* aContext
,
4600 nsRuleNode
* aHighestNode
,
4601 const RuleDetail aRuleDetail
, PRBool aInherited
)
4603 COMPUTE_START_RESET(XUL
, (), xul
, parentXUL
, XUL
, xulData
)
4605 // box-align: enum, inherit, initial
4606 SetDiscrete(xulData
.mBoxAlign
, xul
->mBoxAlign
, inherited
,
4607 SETDSC_ENUMERATED
, parentXUL
->mBoxAlign
,
4608 NS_STYLE_BOX_ALIGN_STRETCH
, 0, 0, 0, 0);
4610 // box-direction: enum, inherit, initial
4611 SetDiscrete(xulData
.mBoxDirection
, xul
->mBoxDirection
, inherited
,
4612 SETDSC_ENUMERATED
, parentXUL
->mBoxDirection
,
4613 NS_STYLE_BOX_DIRECTION_NORMAL
, 0, 0, 0, 0);
4615 // box-flex: factor, inherit
4616 SetFactor(xulData
.mBoxFlex
, xul
->mBoxFlex
, inherited
,
4617 parentXUL
->mBoxFlex
, 0.0f
);
4619 // box-orient: enum, inherit, initial
4620 SetDiscrete(xulData
.mBoxOrient
, xul
->mBoxOrient
, inherited
,
4621 SETDSC_ENUMERATED
, parentXUL
->mBoxOrient
,
4622 NS_STYLE_BOX_ORIENT_HORIZONTAL
, 0, 0, 0, 0);
4624 // box-pack: enum, inherit, initial
4625 SetDiscrete(xulData
.mBoxPack
, xul
->mBoxPack
, inherited
,
4626 SETDSC_ENUMERATED
, parentXUL
->mBoxPack
,
4627 NS_STYLE_BOX_PACK_START
, 0, 0, 0, 0);
4629 // box-ordinal-group: integer, inherit, initial
4630 SetDiscrete(xulData
.mBoxOrdinal
, xul
->mBoxOrdinal
, inherited
,
4631 SETDSC_INTEGER
, parentXUL
->mBoxOrdinal
, 1,
4634 if (eCSSUnit_Inherit
== xulData
.mStackSizing
.GetUnit()) {
4635 inherited
= PR_TRUE
;
4636 xul
->mStretchStack
= parentXUL
->mStretchStack
;
4637 } else if (eCSSUnit_Initial
== xulData
.mStackSizing
.GetUnit()) {
4638 xul
->mStretchStack
= PR_TRUE
;
4639 } else if (eCSSUnit_Enumerated
== xulData
.mStackSizing
.GetUnit()) {
4640 xul
->mStretchStack
= xulData
.mStackSizing
.GetIntValue() ==
4641 NS_STYLE_STACK_SIZING_STRETCH_TO_FIT
;
4644 COMPUTE_END_RESET(XUL
, xul
)
4648 nsRuleNode::ComputeColumnData(void* aStartStruct
,
4649 const nsRuleDataStruct
& aData
,
4650 nsStyleContext
* aContext
,
4651 nsRuleNode
* aHighestNode
,
4652 const RuleDetail aRuleDetail
, PRBool aInherited
)
4654 COMPUTE_START_RESET(Column
, (mPresContext
), column
, parent
, Column
, columnData
)
4656 // column-width: length, auto, inherit
4657 SetCoord(columnData
.mColumnWidth
,
4658 column
->mColumnWidth
, parent
->mColumnWidth
,
4659 SETCOORD_LAH
| SETCOORD_INITIAL_AUTO
,
4660 aContext
, mPresContext
, inherited
);
4662 // column-gap: length, percentage, inherit, normal
4663 SetCoord(columnData
.mColumnGap
,
4664 column
->mColumnGap
, parent
->mColumnGap
,
4665 SETCOORD_LPH
| SETCOORD_NORMAL
| SETCOORD_INITIAL_NORMAL
,
4666 aContext
, mPresContext
, inherited
);
4668 // column-count: auto, integer, inherit
4669 if (eCSSUnit_Auto
== columnData
.mColumnCount
.GetUnit() ||
4670 eCSSUnit_Initial
== columnData
.mColumnCount
.GetUnit()) {
4671 column
->mColumnCount
= NS_STYLE_COLUMN_COUNT_AUTO
;
4672 } else if (eCSSUnit_Integer
== columnData
.mColumnCount
.GetUnit()) {
4673 column
->mColumnCount
= columnData
.mColumnCount
.GetIntValue();
4674 // Max 1000 columns - wallpaper for bug 345583.
4675 column
->mColumnCount
= PR_MIN(column
->mColumnCount
, 1000);
4676 } else if (eCSSUnit_Inherit
== columnData
.mColumnCount
.GetUnit()) {
4677 inherited
= PR_TRUE
;
4678 column
->mColumnCount
= parent
->mColumnCount
;
4681 // column-rule-width: length, enum, inherit
4682 const nsCSSValue
& widthValue
= columnData
.mColumnRuleWidth
;
4683 if (eCSSUnit_Initial
== widthValue
.GetUnit()) {
4684 column
->SetColumnRuleWidth(
4685 (mPresContext
->GetBorderWidthTable())[NS_STYLE_BORDER_WIDTH_MEDIUM
]);
4687 else if (eCSSUnit_Enumerated
== widthValue
.GetUnit()) {
4688 NS_ASSERTION(widthValue
.GetIntValue() == NS_STYLE_BORDER_WIDTH_THIN
||
4689 widthValue
.GetIntValue() == NS_STYLE_BORDER_WIDTH_MEDIUM
||
4690 widthValue
.GetIntValue() == NS_STYLE_BORDER_WIDTH_THICK
,
4691 "Unexpected enum value");
4692 column
->SetColumnRuleWidth(
4693 (mPresContext
->GetBorderWidthTable())[widthValue
.GetIntValue()]);
4695 else if (eCSSUnit_Inherit
== widthValue
.GetUnit()) {
4696 column
->SetColumnRuleWidth(parent
->GetComputedColumnRuleWidth());
4697 inherited
= PR_TRUE
;
4699 else if (widthValue
.IsLengthUnit()) {
4700 column
->SetColumnRuleWidth(CalcLength(widthValue
, aContext
,
4701 mPresContext
, inherited
));
4704 // column-rule-style: enum, none, inherit
4705 const nsCSSValue
& styleValue
= columnData
.mColumnRuleStyle
;
4706 if (eCSSUnit_Enumerated
== styleValue
.GetUnit()) {
4707 column
->mColumnRuleStyle
= styleValue
.GetIntValue();
4709 else if (eCSSUnit_None
== styleValue
.GetUnit() ||
4710 eCSSUnit_Initial
== styleValue
.GetUnit()) {
4711 column
->mColumnRuleStyle
= NS_STYLE_BORDER_STYLE_NONE
;
4713 else if (eCSSUnit_Inherit
== styleValue
.GetUnit()) {
4714 inherited
= PR_TRUE
;
4715 column
->mColumnRuleStyle
= parent
->mColumnRuleStyle
;
4718 // column-rule-color: color, inherit
4719 const nsCSSValue
& colorValue
= columnData
.mColumnRuleColor
;
4720 if (eCSSUnit_Inherit
== colorValue
.GetUnit()) {
4721 inherited
= PR_TRUE
;
4722 column
->mColumnRuleColorIsForeground
= PR_FALSE
;
4723 if (parent
->mColumnRuleColorIsForeground
) {
4724 column
->mColumnRuleColor
= parentContext
->GetStyleColor()->mColor
;
4726 column
->mColumnRuleColor
= parent
->mColumnRuleColor
;
4729 else if (eCSSUnit_Initial
== colorValue
.GetUnit()) {
4730 column
->mColumnRuleColorIsForeground
= PR_TRUE
;
4732 else if (SetColor(colorValue
, 0, mPresContext
, aContext
, column
->mColumnRuleColor
, inherited
)) {
4733 column
->mColumnRuleColorIsForeground
= PR_FALSE
;
4736 COMPUTE_END_RESET(Column
, column
)
4741 SetSVGPaint(const nsCSSValuePair
& aValue
, const nsStyleSVGPaint
& parentPaint
,
4742 nsPresContext
* aPresContext
, nsStyleContext
*aContext
,
4743 nsStyleSVGPaint
& aResult
, nsStyleSVGPaintType aInitialPaintType
,
4748 if (aValue
.mXValue
.GetUnit() == eCSSUnit_Inherit
) {
4749 aResult
= parentPaint
;
4750 aInherited
= PR_TRUE
;
4751 } else if (aValue
.mXValue
.GetUnit() == eCSSUnit_None
) {
4752 aResult
.SetType(eStyleSVGPaintType_None
);
4753 } else if (aValue
.mXValue
.GetUnit() == eCSSUnit_Initial
) {
4754 aResult
.SetType(aInitialPaintType
);
4755 aResult
.mPaint
.mColor
= NS_RGB(0, 0, 0);
4756 aResult
.mFallbackColor
= NS_RGB(0, 0, 0);
4757 } else if (aValue
.mXValue
.GetUnit() == eCSSUnit_URL
) {
4758 aResult
.SetType(eStyleSVGPaintType_Server
);
4759 aResult
.mPaint
.mPaintServer
= aValue
.mXValue
.GetURLValue();
4760 NS_IF_ADDREF(aResult
.mPaint
.mPaintServer
);
4761 if (aValue
.mYValue
.GetUnit() == eCSSUnit_None
) {
4762 aResult
.mFallbackColor
= NS_RGBA(0, 0, 0, 0);
4764 NS_ASSERTION(aValue
.mYValue
.GetUnit() != eCSSUnit_Inherit
, "cannot inherit fallback colour");
4765 SetColor(aValue
.mYValue
, NS_RGB(0, 0, 0), aPresContext
, aContext
, aResult
.mFallbackColor
, aInherited
);
4767 } else if (SetColor(aValue
.mXValue
, parentPaint
.mPaint
.mColor
, aPresContext
, aContext
, color
, aInherited
)) {
4768 aResult
.SetType(eStyleSVGPaintType_Color
);
4769 aResult
.mPaint
.mColor
= color
;
4774 nsRuleNode::ComputeSVGData(void* aStartStruct
,
4775 const nsRuleDataStruct
& aData
,
4776 nsStyleContext
* aContext
,
4777 nsRuleNode
* aHighestNode
,
4778 const RuleDetail aRuleDetail
, PRBool aInherited
)
4780 COMPUTE_START_INHERITED(SVG
, (), svg
, parentSVG
, SVG
, SVGData
)
4782 // clip-rule: enum, inherit, initial
4783 SetDiscrete(SVGData
.mClipRule
, svg
->mClipRule
, inherited
,
4784 SETDSC_ENUMERATED
, parentSVG
->mClipRule
,
4785 NS_STYLE_FILL_RULE_NONZERO
, 0, 0, 0, 0);
4787 // color-interpolation: enum, auto, inherit, initial
4788 SetDiscrete(SVGData
.mColorInterpolation
, svg
->mColorInterpolation
, inherited
,
4789 SETDSC_ENUMERATED
| SETDSC_AUTO
,
4790 parentSVG
->mColorInterpolation
,
4791 NS_STYLE_COLOR_INTERPOLATION_SRGB
,
4792 NS_STYLE_COLOR_INTERPOLATION_AUTO
, 0, 0, 0);
4794 // color-interpolation-filters: enum, auto, inherit, initial
4795 SetDiscrete(SVGData
.mColorInterpolationFilters
,
4796 svg
->mColorInterpolationFilters
, inherited
,
4797 SETDSC_ENUMERATED
| SETDSC_AUTO
,
4798 parentSVG
->mColorInterpolationFilters
,
4799 NS_STYLE_COLOR_INTERPOLATION_LINEARRGB
,
4800 NS_STYLE_COLOR_INTERPOLATION_AUTO
, 0, 0, 0);
4803 SetSVGPaint(SVGData
.mFill
, parentSVG
->mFill
, mPresContext
, aContext
,
4804 svg
->mFill
, eStyleSVGPaintType_Color
, inherited
);
4806 // fill-opacity: factor, inherit, initial
4807 SetFactor(SVGData
.mFillOpacity
, svg
->mFillOpacity
, inherited
,
4808 parentSVG
->mFillOpacity
, 1.0f
, SETFCT_OPACITY
);
4810 // fill-rule: enum, inherit, initial
4811 SetDiscrete(SVGData
.mFillRule
, svg
->mFillRule
, inherited
,
4812 SETDSC_ENUMERATED
, parentSVG
->mFillRule
,
4813 NS_STYLE_FILL_RULE_NONZERO
, 0, 0, 0, 0);
4815 // marker-end: url, none, inherit
4816 if (eCSSUnit_URL
== SVGData
.mMarkerEnd
.GetUnit()) {
4817 svg
->mMarkerEnd
= SVGData
.mMarkerEnd
.GetURLValue();
4818 } else if (eCSSUnit_None
== SVGData
.mMarkerEnd
.GetUnit() ||
4819 eCSSUnit_Initial
== SVGData
.mMarkerEnd
.GetUnit()) {
4820 svg
->mMarkerEnd
= nsnull
;
4821 } else if (eCSSUnit_Inherit
== SVGData
.mMarkerEnd
.GetUnit()) {
4822 inherited
= PR_TRUE
;
4823 svg
->mMarkerEnd
= parentSVG
->mMarkerEnd
;
4826 // marker-mid: url, none, inherit
4827 if (eCSSUnit_URL
== SVGData
.mMarkerMid
.GetUnit()) {
4828 svg
->mMarkerMid
= SVGData
.mMarkerMid
.GetURLValue();
4829 } else if (eCSSUnit_None
== SVGData
.mMarkerMid
.GetUnit() ||
4830 eCSSUnit_Initial
== SVGData
.mMarkerMid
.GetUnit()) {
4831 svg
->mMarkerMid
= nsnull
;
4832 } else if (eCSSUnit_Inherit
== SVGData
.mMarkerMid
.GetUnit()) {
4833 inherited
= PR_TRUE
;
4834 svg
->mMarkerMid
= parentSVG
->mMarkerMid
;
4837 // marker-start: url, none, inherit
4838 if (eCSSUnit_URL
== SVGData
.mMarkerStart
.GetUnit()) {
4839 svg
->mMarkerStart
= SVGData
.mMarkerStart
.GetURLValue();
4840 } else if (eCSSUnit_None
== SVGData
.mMarkerStart
.GetUnit() ||
4841 eCSSUnit_Initial
== SVGData
.mMarkerStart
.GetUnit()) {
4842 svg
->mMarkerStart
= nsnull
;
4843 } else if (eCSSUnit_Inherit
== SVGData
.mMarkerStart
.GetUnit()) {
4844 inherited
= PR_TRUE
;
4845 svg
->mMarkerStart
= parentSVG
->mMarkerStart
;
4848 // pointer-events: enum, none, inherit, initial
4849 SetDiscrete(SVGData
.mPointerEvents
, svg
->mPointerEvents
, inherited
,
4850 SETDSC_ENUMERATED
| SETDSC_NONE
, parentSVG
->mPointerEvents
,
4851 NS_STYLE_POINTER_EVENTS_VISIBLEPAINTED
, 0,
4852 NS_STYLE_POINTER_EVENTS_NONE
, 0, 0);
4854 // shape-rendering: enum, auto, inherit
4855 SetDiscrete(SVGData
.mShapeRendering
, svg
->mShapeRendering
, inherited
,
4856 SETDSC_ENUMERATED
| SETDSC_AUTO
,
4857 parentSVG
->mShapeRendering
,
4858 NS_STYLE_SHAPE_RENDERING_AUTO
,
4859 NS_STYLE_SHAPE_RENDERING_AUTO
, 0, 0, 0);
4862 SetSVGPaint(SVGData
.mStroke
, parentSVG
->mStroke
, mPresContext
, aContext
,
4863 svg
->mStroke
, eStyleSVGPaintType_None
, inherited
);
4865 // stroke-dasharray: <dasharray>, none, inherit
4866 nsCSSValueList
*list
= SVGData
.mStrokeDasharray
;
4868 if (eCSSUnit_Inherit
== list
->mValue
.GetUnit()) {
4869 // only do the copy if weren't already set up by the copy constructor
4870 // FIXME Bug 389408: This is broken when aStartStruct is non-null!
4871 if (!svg
->mStrokeDasharray
) {
4872 inherited
= PR_TRUE
;
4873 svg
->mStrokeDasharrayLength
= parentSVG
->mStrokeDasharrayLength
;
4874 if (svg
->mStrokeDasharrayLength
) {
4875 svg
->mStrokeDasharray
= new nsStyleCoord
[svg
->mStrokeDasharrayLength
];
4876 if (svg
->mStrokeDasharray
)
4877 memcpy(svg
->mStrokeDasharray
,
4878 parentSVG
->mStrokeDasharray
,
4879 svg
->mStrokeDasharrayLength
* sizeof(nsStyleCoord
));
4881 svg
->mStrokeDasharrayLength
= 0;
4885 delete [] svg
->mStrokeDasharray
;
4886 svg
->mStrokeDasharray
= nsnull
;
4887 svg
->mStrokeDasharrayLength
= 0;
4889 if (eCSSUnit_Initial
!= list
->mValue
.GetUnit() &&
4890 eCSSUnit_None
!= list
->mValue
.GetUnit()) {
4891 // count number of values
4892 nsCSSValueList
*value
= SVGData
.mStrokeDasharray
;
4893 while (nsnull
!= value
) {
4894 ++svg
->mStrokeDasharrayLength
;
4895 value
= value
->mNext
;
4898 NS_ASSERTION(svg
->mStrokeDasharrayLength
!= 0, "no dasharray items");
4900 svg
->mStrokeDasharray
= new nsStyleCoord
[svg
->mStrokeDasharrayLength
];
4902 if (svg
->mStrokeDasharray
) {
4903 value
= SVGData
.mStrokeDasharray
;
4905 while (nsnull
!= value
) {
4906 SetCoord(value
->mValue
,
4907 svg
->mStrokeDasharray
[i
++], nsnull
,
4908 SETCOORD_LP
| SETCOORD_FACTOR
,
4909 aContext
, mPresContext
, inherited
);
4910 value
= value
->mNext
;
4913 svg
->mStrokeDasharrayLength
= 0;
4918 // stroke-dashoffset: <dashoffset>, inherit
4919 SetCoord(SVGData
.mStrokeDashoffset
,
4920 svg
->mStrokeDashoffset
, parentSVG
->mStrokeDashoffset
,
4921 SETCOORD_LPH
| SETCOORD_FACTOR
| SETCOORD_INITIAL_ZERO
,
4922 aContext
, mPresContext
, inherited
);
4924 // stroke-linecap: enum, inherit, initial
4925 SetDiscrete(SVGData
.mStrokeLinecap
, svg
->mStrokeLinecap
, inherited
,
4926 SETDSC_ENUMERATED
, parentSVG
->mStrokeLinecap
,
4927 NS_STYLE_STROKE_LINECAP_BUTT
, 0, 0, 0, 0);
4929 // stroke-linejoin: enum, inherit, initial
4930 SetDiscrete(SVGData
.mStrokeLinejoin
, svg
->mStrokeLinejoin
, inherited
,
4931 SETDSC_ENUMERATED
, parentSVG
->mStrokeLinejoin
,
4932 NS_STYLE_STROKE_LINEJOIN_MITER
, 0, 0, 0, 0);
4934 // stroke-miterlimit: <miterlimit>, inherit
4935 SetFactor(SVGData
.mStrokeMiterlimit
, svg
->mStrokeMiterlimit
, inherited
,
4936 parentSVG
->mStrokeMiterlimit
, 4.0f
);
4939 SetFactor(SVGData
.mStrokeOpacity
, svg
->mStrokeOpacity
, inherited
,
4940 parentSVG
->mStrokeOpacity
, 1.0f
, SETFCT_OPACITY
);
4943 if (eCSSUnit_Initial
== SVGData
.mStrokeWidth
.GetUnit()) {
4944 svg
->mStrokeWidth
.SetCoordValue(nsPresContext::CSSPixelsToAppUnits(1));
4946 SetCoord(SVGData
.mStrokeWidth
,
4947 svg
->mStrokeWidth
, parentSVG
->mStrokeWidth
,
4948 SETCOORD_LPH
| SETCOORD_FACTOR
,
4949 aContext
, mPresContext
, inherited
);
4952 // text-anchor: enum, inherit, initial
4953 SetDiscrete(SVGData
.mTextAnchor
, svg
->mTextAnchor
, inherited
,
4954 SETDSC_ENUMERATED
, parentSVG
->mTextAnchor
,
4955 NS_STYLE_TEXT_ANCHOR_START
, 0, 0, 0, 0);
4957 // text-rendering: enum, auto, inherit, initial
4958 SetDiscrete(SVGData
.mTextRendering
, svg
->mTextRendering
, inherited
,
4959 SETDSC_ENUMERATED
| SETDSC_AUTO
,
4960 parentSVG
->mTextRendering
,
4961 NS_STYLE_TEXT_RENDERING_AUTO
,
4962 NS_STYLE_TEXT_RENDERING_AUTO
, 0, 0, 0);
4964 COMPUTE_END_INHERITED(SVG
, svg
)
4968 nsRuleNode::ComputeSVGResetData(void* aStartStruct
,
4969 const nsRuleDataStruct
& aData
,
4970 nsStyleContext
* aContext
,
4971 nsRuleNode
* aHighestNode
,
4972 const RuleDetail aRuleDetail
, PRBool aInherited
)
4974 COMPUTE_START_RESET(SVGReset
, (), svgReset
, parentSVGReset
, SVG
, SVGData
)
4977 if (eCSSUnit_Initial
== SVGData
.mStopColor
.GetUnit()) {
4978 svgReset
->mStopColor
= NS_RGB(0, 0, 0);
4980 SetColor(SVGData
.mStopColor
, parentSVGReset
->mStopColor
,
4981 mPresContext
, aContext
, svgReset
->mStopColor
, inherited
);
4985 if (eCSSUnit_Initial
== SVGData
.mFloodColor
.GetUnit()) {
4986 svgReset
->mFloodColor
= NS_RGB(0, 0, 0);
4988 SetColor(SVGData
.mFloodColor
, parentSVGReset
->mFloodColor
,
4989 mPresContext
, aContext
, svgReset
->mFloodColor
, inherited
);
4993 if (eCSSUnit_Initial
== SVGData
.mLightingColor
.GetUnit()) {
4994 svgReset
->mLightingColor
= NS_RGB(255, 255, 255);
4996 SetColor(SVGData
.mLightingColor
, parentSVGReset
->mLightingColor
,
4997 mPresContext
, aContext
, svgReset
->mLightingColor
, inherited
);
5000 // clip-path: url, none, inherit
5001 if (eCSSUnit_URL
== SVGData
.mClipPath
.GetUnit()) {
5002 svgReset
->mClipPath
= SVGData
.mClipPath
.GetURLValue();
5003 } else if (eCSSUnit_None
== SVGData
.mClipPath
.GetUnit() ||
5004 eCSSUnit_Initial
== SVGData
.mClipPath
.GetUnit()) {
5005 svgReset
->mClipPath
= nsnull
;
5006 } else if (eCSSUnit_Inherit
== SVGData
.mClipPath
.GetUnit()) {
5007 inherited
= PR_TRUE
;
5008 svgReset
->mClipPath
= parentSVGReset
->mClipPath
;
5012 SetFactor(SVGData
.mStopOpacity
, svgReset
->mStopOpacity
, inherited
,
5013 parentSVGReset
->mStopOpacity
, 1.0f
, SETFCT_OPACITY
);
5016 SetFactor(SVGData
.mFloodOpacity
, svgReset
->mFloodOpacity
, inherited
,
5017 parentSVGReset
->mFloodOpacity
, 1.0f
, SETFCT_OPACITY
);
5019 // dominant-baseline: enum, auto, inherit, initial
5020 SetDiscrete(SVGData
.mDominantBaseline
, svgReset
->mDominantBaseline
,
5022 SETDSC_ENUMERATED
| SETDSC_AUTO
,
5023 parentSVGReset
->mDominantBaseline
,
5024 NS_STYLE_DOMINANT_BASELINE_AUTO
,
5025 NS_STYLE_DOMINANT_BASELINE_AUTO
, 0, 0, 0);
5027 // filter: url, none, inherit
5028 if (eCSSUnit_URL
== SVGData
.mFilter
.GetUnit()) {
5029 svgReset
->mFilter
= SVGData
.mFilter
.GetURLValue();
5030 } else if (eCSSUnit_None
== SVGData
.mFilter
.GetUnit() ||
5031 eCSSUnit_Initial
== SVGData
.mFilter
.GetUnit()) {
5032 svgReset
->mFilter
= nsnull
;
5033 } else if (eCSSUnit_Inherit
== SVGData
.mFilter
.GetUnit()) {
5034 inherited
= PR_TRUE
;
5035 svgReset
->mFilter
= parentSVGReset
->mFilter
;
5038 // mask: url, none, inherit
5039 if (eCSSUnit_URL
== SVGData
.mMask
.GetUnit()) {
5040 svgReset
->mMask
= SVGData
.mMask
.GetURLValue();
5041 } else if (eCSSUnit_None
== SVGData
.mMask
.GetUnit() ||
5042 eCSSUnit_Initial
== SVGData
.mMask
.GetUnit()) {
5043 svgReset
->mMask
= nsnull
;
5044 } else if (eCSSUnit_Inherit
== SVGData
.mMask
.GetUnit()) {
5045 inherited
= PR_TRUE
;
5046 svgReset
->mMask
= parentSVGReset
->mMask
;
5049 COMPUTE_END_RESET(SVGReset
, svgReset
)
5054 nsRuleNode::GetParentData(const nsStyleStructID aSID
)
5056 NS_PRECONDITION(mDependentBits
& nsCachedStyleData::GetBitForSID(aSID
),
5057 "should be called when node depends on parent data");
5058 NS_ASSERTION(mStyleData
.GetStyleData(aSID
) == nsnull
,
5059 "both struct and dependent bits present");
5060 // Walk up the rule tree from this rule node (towards less specific
5062 PRUint32 bit
= nsCachedStyleData::GetBitForSID(aSID
);
5063 nsRuleNode
*ruleNode
= mParent
;
5064 while (ruleNode
->mDependentBits
& bit
) {
5065 NS_ASSERTION(ruleNode
->mStyleData
.GetStyleData(aSID
) == nsnull
,
5066 "both struct and dependent bits present");
5067 ruleNode
= ruleNode
->mParent
;
5070 return ruleNode
->mStyleData
.GetStyleData(aSID
);
5073 #define STYLE_STRUCT(name_, checkdata_cb_, ctor_args_) \
5074 inline const nsStyle##name_ * \
5075 nsRuleNode::GetParent##name_() \
5077 NS_PRECONDITION(mDependentBits & \
5078 nsCachedStyleData::GetBitForSID(eStyleStruct_##name_), \
5079 "should be called when node depends on parent data"); \
5080 NS_ASSERTION(mStyleData.GetStyle##name_() == nsnull, \
5081 "both struct and dependent bits present"); \
5082 /* Walk up the rule tree from this rule node (towards less specific */ \
5084 PRUint32 bit = nsCachedStyleData::GetBitForSID(eStyleStruct_##name_); \
5085 nsRuleNode *ruleNode = mParent; \
5086 while (ruleNode->mDependentBits & bit) { \
5087 NS_ASSERTION(ruleNode->mStyleData.GetStyle##name_() == nsnull, \
5088 "both struct and dependent bits present"); \
5089 ruleNode = ruleNode->mParent; \
5092 return ruleNode->mStyleData.GetStyle##name_(); \
5094 #include "nsStyleStructList.h"
5098 nsRuleNode::GetStyleData(nsStyleStructID aSID
,
5099 nsStyleContext
* aContext
,
5100 PRBool aComputeData
)
5103 if (mDependentBits
& nsCachedStyleData::GetBitForSID(aSID
)) {
5104 // We depend on an ancestor for this struct since the cached struct
5105 // it has is also appropriate for this rule node. Just go up the
5106 // rule tree and return the first cached struct we find.
5107 data
= GetParentData(aSID
);
5108 NS_ASSERTION(data
, "dependent bits set but no cached struct present");
5112 data
= mStyleData
.GetStyleData(aSID
);
5113 if (NS_LIKELY(data
!= nsnull
))
5114 return data
; // We have a fully specified struct. Just return it.
5116 if (NS_UNLIKELY(!aComputeData
))
5119 // Nothing is cached. We'll have to delve further and examine our rules.
5120 #define STYLE_STRUCT_TEST aSID
5121 #define STYLE_STRUCT(name, checkdata_cb, ctor_args) \
5122 data = Get##name##Data(aContext);
5123 #include "nsStyleStructList.h"
5125 #undef STYLE_STRUCT_TEST
5127 if (NS_LIKELY(data
!= nsnull
))
5130 NS_NOTREACHED("could not create style struct");
5131 // To ensure that |GetStyleData| never returns null (even when we're
5132 // out of memory), we'll get the style set and get a copy of the
5133 // default values for the given style struct from the set. Note that
5134 // this works fine even if |this| is a rule node that has been
5135 // destroyed (leftover from a previous rule tree) but is somehow still
5137 return mPresContext
->PresShell()->StyleSet()->
5138 DefaultStyleData()->GetStyleData(aSID
);
5141 // See comments above in GetStyleData for an explanation of what the
5143 #define STYLE_STRUCT(name_, checkdata_cb_, ctor_args_) \
5144 const nsStyle##name_* \
5145 nsRuleNode::GetStyle##name_(nsStyleContext* aContext, PRBool aComputeData) \
5147 const nsStyle##name_ *data; \
5148 if (mDependentBits & \
5149 nsCachedStyleData::GetBitForSID(eStyleStruct_##name_)) { \
5150 data = GetParent##name_(); \
5151 NS_ASSERTION(data, "dependent bits set but no cached struct present"); \
5155 data = mStyleData.GetStyle##name_(); \
5156 if (NS_LIKELY(data != nsnull)) \
5159 if (NS_UNLIKELY(!aComputeData)) \
5163 static_cast<const nsStyle##name_ *>(Get##name_##Data(aContext)); \
5165 if (NS_LIKELY(data != nsnull)) \
5168 NS_NOTREACHED("could not create style struct"); \
5170 static_cast<const nsStyle##name_ *>( \
5171 mPresContext->PresShell()->StyleSet()-> \
5172 DefaultStyleData()->GetStyleData(eStyleStruct_##name_)); \
5174 #include "nsStyleStructList.h"
5180 for (nsRuleNode
*node
= this;
5181 node
&& !(node
->mDependentBits
& NS_RULE_NODE_GC_MARK
);
5182 node
= node
->mParent
)
5183 node
->mDependentBits
|= NS_RULE_NODE_GC_MARK
;
5186 static PLDHashOperator
5187 SweepRuleNodeChildren(PLDHashTable
*table
, PLDHashEntryHdr
*hdr
,
5188 PRUint32 number
, void *arg
)
5190 ChildrenHashEntry
*entry
= static_cast<ChildrenHashEntry
*>(hdr
);
5191 if (entry
->mRuleNode
->Sweep())
5192 return PL_DHASH_REMOVE
; // implies NEXT, unless |ed with STOP
5193 return PL_DHASH_NEXT
;
5199 // If we're not marked, then we have to delete ourself.
5200 // However, we never allow the root node to GC itself, because nsStyleSet
5201 // wants to hold onto the root node and not worry about re-creating a
5202 // rule walker if the root node is deleted.
5203 if (!(mDependentBits
& NS_RULE_NODE_GC_MARK
) && !IsRoot()) {
5208 // Clear our mark, for the next time around.
5209 mDependentBits
&= ~NS_RULE_NODE_GC_MARK
;
5211 // Call sweep on the children, since some may not be marked, and
5212 // remove any deleted children from the child lists.
5213 if (HaveChildren()) {
5214 if (ChildrenAreHashed()) {
5215 PLDHashTable
*children
= ChildrenHash();
5216 PL_DHashTableEnumerate(children
, SweepRuleNodeChildren
, nsnull
);
5218 for (nsRuleNode
**children
= ChildrenListPtr(); *children
; ) {
5219 nsRuleNode
*next
= (*children
)->mNextSibling
;
5220 if ((*children
)->Sweep()) {
5221 // This rule node was destroyed, so implicitly advance by
5222 // making *children point to the next entry.
5226 children
= &(*children
)->mNextSibling
;
5235 nsRuleNode::HasAuthorSpecifiedRules(nsStyleContext
* aStyleContext
,
5236 PRUint32 ruleTypeMask
)
5238 nsRuleDataColor colorData
;
5239 nsRuleDataMargin marginData
;
5240 PRUint32 nValues
= 0;
5242 PRUint32 inheritBits
= 0;
5243 if (ruleTypeMask
& NS_AUTHOR_SPECIFIED_BACKGROUND
)
5244 inheritBits
|= NS_STYLE_INHERIT_BIT(Background
);
5246 if (ruleTypeMask
& NS_AUTHOR_SPECIFIED_BORDER
)
5247 inheritBits
|= NS_STYLE_INHERIT_BIT(Border
);
5249 if (ruleTypeMask
& NS_AUTHOR_SPECIFIED_PADDING
)
5250 inheritBits
|= NS_STYLE_INHERIT_BIT(Padding
);
5252 /* We're relying on the use of |aStyleContext| not mutating it! */
5253 nsRuleData
ruleData(inheritBits
,
5254 aStyleContext
->PresContext(), aStyleContext
);
5255 ruleData
.mColorData
= &colorData
;
5256 ruleData
.mMarginData
= &marginData
;
5258 nsCSSValue
* backgroundValues
[] = {
5259 &colorData
.mBackColor
,
5260 &colorData
.mBackImage
5263 nsCSSValue
* borderValues
[] = {
5264 &marginData
.mBorderColor
.mTop
,
5265 &marginData
.mBorderStyle
.mTop
,
5266 &marginData
.mBorderWidth
.mTop
,
5267 &marginData
.mBorderColor
.mRight
,
5268 &marginData
.mBorderStyle
.mRight
,
5269 &marginData
.mBorderWidth
.mRight
,
5270 &marginData
.mBorderColor
.mBottom
,
5271 &marginData
.mBorderStyle
.mBottom
,
5272 &marginData
.mBorderWidth
.mBottom
,
5273 &marginData
.mBorderColor
.mLeft
,
5274 &marginData
.mBorderStyle
.mLeft
,
5275 &marginData
.mBorderWidth
.mLeft
5276 // XXX add &marginData.mBorder{Start,End}{Width,Color,Style}
5279 nsCSSValue
* paddingValues
[] = {
5280 &marginData
.mPadding
.mTop
,
5281 &marginData
.mPadding
.mRight
,
5282 &marginData
.mPadding
.mBottom
,
5283 &marginData
.mPadding
.mLeft
,
5284 &marginData
.mPaddingStart
,
5285 &marginData
.mPaddingEnd
5288 nsCSSValue
* values
[NS_ARRAY_LENGTH(backgroundValues
) +
5289 NS_ARRAY_LENGTH(borderValues
) +
5290 NS_ARRAY_LENGTH(paddingValues
)];
5292 if (ruleTypeMask
& NS_AUTHOR_SPECIFIED_BACKGROUND
) {
5293 memcpy(&values
[nValues
], backgroundValues
, NS_ARRAY_LENGTH(backgroundValues
) * sizeof(nsCSSValue
*));
5294 nValues
+= NS_ARRAY_LENGTH(backgroundValues
);
5297 if (ruleTypeMask
& NS_AUTHOR_SPECIFIED_BORDER
) {
5298 memcpy(&values
[nValues
], borderValues
, NS_ARRAY_LENGTH(borderValues
) * sizeof(nsCSSValue
*));
5299 nValues
+= NS_ARRAY_LENGTH(borderValues
);
5302 if (ruleTypeMask
& NS_AUTHOR_SPECIFIED_PADDING
) {
5303 memcpy(&values
[nValues
], paddingValues
, NS_ARRAY_LENGTH(paddingValues
) * sizeof(nsCSSValue
*));
5304 nValues
+= NS_ARRAY_LENGTH(paddingValues
);
5307 nsStyleContext
* styleContext
= aStyleContext
;
5309 // We need to be careful not to count styles covered up by user-important or
5310 // UA-important declarations. But we do want to catch explicit inherit
5311 // styling in those and check our parent style context to see whether we have
5312 // user styling for those properties. Note that we don't care here about
5313 // inheritance due to lack of a specified value, since all the properties we
5314 // care about are reset properties.
5315 PRBool haveExplicitUAInherit
;
5317 haveExplicitUAInherit
= PR_FALSE
;
5318 for (nsRuleNode
* ruleNode
= styleContext
->GetRuleNode(); ruleNode
;
5319 ruleNode
= ruleNode
->GetParent()) {
5320 nsIStyleRule
*rule
= ruleNode
->GetRule();
5322 ruleData
.mLevel
= ruleNode
->GetLevel();
5323 ruleData
.mIsImportantRule
= ruleNode
->IsImportantRule();
5324 rule
->MapRuleInfoInto(&ruleData
);
5325 // Do the same nulling out as in GetBorderData, GetBackgroundData
5326 // or GetPaddingData.
5327 // We are sharing with some style rule. It really owns the data.
5328 marginData
.mBoxShadow
= nsnull
;
5330 if (ruleData
.mLevel
== nsStyleSet::eAgentSheet
||
5331 ruleData
.mLevel
== nsStyleSet::eUserSheet
) {
5332 // This is a rule whose effect we want to ignore, so if any of
5333 // the properties we care about were set, set them to the dummy
5334 // value that they'll never otherwise get.
5335 for (PRUint32 i
= 0; i
< nValues
; ++i
) {
5336 nsCSSUnit unit
= values
[i
]->GetUnit();
5337 if (unit
!= eCSSUnit_Null
&&
5338 unit
!= eCSSUnit_Dummy
&&
5339 unit
!= eCSSUnit_DummyInherit
) {
5340 if (unit
== eCSSUnit_Inherit
) {
5341 haveExplicitUAInherit
= PR_TRUE
;
5342 values
[i
]->SetDummyInheritValue();
5344 values
[i
]->SetDummyValue();
5349 // If any of the values we care about was set by the above rule,
5350 // we have author style.
5351 for (PRUint32 i
= 0; i
< nValues
; ++i
)
5352 if (values
[i
]->GetUnit() != eCSSUnit_Null
&&
5353 values
[i
]->GetUnit() != eCSSUnit_Dummy
&& // see above
5354 values
[i
]->GetUnit() != eCSSUnit_DummyInherit
)
5360 if (haveExplicitUAInherit
) {
5361 // reset all the eCSSUnit_Null values to eCSSUnit_Dummy (since they're
5362 // not styled by the author, or by anyone else), and then reset all the
5363 // eCSSUnit_DummyInherit values to eCSSUnit_Null (so we will be able to
5364 // detect them being styled by the author) and move up to our parent
5366 for (PRUint32 i
= 0; i
< nValues
; ++i
)
5367 if (values
[i
]->GetUnit() == eCSSUnit_Null
)
5368 values
[i
]->SetDummyValue();
5369 for (PRUint32 i
= 0; i
< nValues
; ++i
)
5370 if (values
[i
]->GetUnit() == eCSSUnit_DummyInherit
)
5372 styleContext
= styleContext
->GetParent();
5374 } while (haveExplicitUAInherit
&& styleContext
);