1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=78: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
8 * a node in the lexicographic tree of rules that match an element,
9 * responsible for converting the rules' information into computed style
14 #include "mozilla/ArrayUtils.h"
15 #include "mozilla/Assertions.h"
16 #include "mozilla/DebugOnly.h"
17 #include "mozilla/Likely.h"
18 #include "mozilla/LookAndFeel.h"
20 #include "nsRuleNode.h"
22 #include "nsIWidget.h"
23 #include "nsIPresShell.h"
24 #include "nsFontMetrics.h"
26 #include "nsCSSPseudoElements.h"
27 #include "nsThemeConstants.h"
29 #include "nsStyleContext.h"
30 #include "nsStyleSet.h"
31 #include "nsStyleStruct.h"
33 #include "nsRuleData.h"
34 #include "nsIStyleRule.h"
35 #include "nsBidiUtils.h"
36 #include "nsStyleStructInlines.h"
37 #include "nsCSSProps.h"
39 #include "nsContentUtils.h"
41 #include "nsPrintfCString.h"
42 #include "nsRenderingContext.h"
43 #include "nsStyleUtil.h"
44 #include "nsIDocument.h"
46 #include "CSSVariableResolver.h"
47 #include "nsCSSParser.h"
48 #include "CounterStyleManager.h"
50 #if defined(_MSC_VER) || defined(__MINGW32__)
53 #define alloca _alloca
62 using namespace mozilla
;
63 using namespace mozilla::dom
;
65 #define NS_SET_IMAGE_REQUEST(method_, context_, request_) \
66 if ((context_)->PresContext()->IsDynamic()) { \
69 nsRefPtr<imgRequestProxy> req = nsContentUtils::GetStaticRequest(request_); \
73 #define NS_SET_IMAGE_REQUEST_WITH_DOC(method_, context_, requestgetter_) \
75 nsIDocument* doc = (context_)->PresContext()->Document(); \
76 NS_SET_IMAGE_REQUEST(method_, context_, requestgetter_(doc)) \
80 * For storage of an |nsRuleNode|'s children in a PLDHashTable.
83 struct ChildrenHashEntry
: public PLDHashEntryHdr
{
84 // key is |mRuleNode->GetKey()|
85 nsRuleNode
*mRuleNode
;
88 /* static */ PLDHashNumber
89 nsRuleNode::ChildrenHashHashKey(PLDHashTable
*aTable
, const void *aKey
)
91 const nsRuleNode::Key
*key
=
92 static_cast<const nsRuleNode::Key
*>(aKey
);
93 // Disagreement on importance and level for the same rule is extremely
94 // rare, so hash just on the rule.
95 return PL_DHashVoidPtrKeyStub(aTable
, key
->mRule
);
99 nsRuleNode::ChildrenHashMatchEntry(PLDHashTable
*aTable
,
100 const PLDHashEntryHdr
*aHdr
,
103 const ChildrenHashEntry
*entry
=
104 static_cast<const ChildrenHashEntry
*>(aHdr
);
105 const nsRuleNode::Key
*key
=
106 static_cast<const nsRuleNode::Key
*>(aKey
);
107 return entry
->mRuleNode
->GetKey() == *key
;
110 /* static */ const PLDHashTableOps
111 nsRuleNode::ChildrenHashOps
= {
112 // It's probably better to allocate the table itself using malloc and
113 // free rather than the pres shell's arena because the table doesn't
114 // grow very often and the pres shell's arena doesn't recycle very
115 // large size allocations.
119 ChildrenHashMatchEntry
,
120 PL_DHashMoveEntryStub
,
121 PL_DHashClearEntryStub
,
122 PL_DHashFinalizeStub
,
127 // EnsureBlockDisplay:
128 // - if the display value (argument) is not a block-type
129 // then we set it to a valid block display value
130 // - For enforcing the floated/positioned element CSS2 rules
131 // - We allow the behavior of "list-item" to be customized.
132 // CSS21 says that position/float do not convert 'list-item' to 'block',
133 // but it explicitly does not define whether 'list-item' should be
134 // converted to block *on the root node*. To allow for flexibility
135 // (so that we don't have to support a list-item root node), this method
136 // lets the caller pick either behavior, using the 'aConvertListItem' arg.
137 // Reference: http://www.w3.org/TR/CSS21/visuren.html#dis-pos-flo
140 nsRuleNode::EnsureBlockDisplay(uint8_t& display
,
141 bool aConvertListItem
/* = false */)
143 // see if the display value is already a block
145 case NS_STYLE_DISPLAY_LIST_ITEM
:
146 if (aConvertListItem
) {
147 display
= NS_STYLE_DISPLAY_BLOCK
;
149 } // else, fall through to share the 'break' for non-changing display vals
150 case NS_STYLE_DISPLAY_NONE
:
151 // never change display:none *ever*
152 case NS_STYLE_DISPLAY_TABLE
:
153 case NS_STYLE_DISPLAY_BLOCK
:
154 case NS_STYLE_DISPLAY_FLEX
:
155 case NS_STYLE_DISPLAY_GRID
:
156 // do not muck with these at all - already blocks
157 // This is equivalent to nsStyleDisplay::IsBlockOutside. (XXX Maybe we
158 // should just call that?)
159 // This needs to match the check done in
160 // nsCSSFrameConstructor::FindMathMLData for <math>.
163 case NS_STYLE_DISPLAY_INLINE_TABLE
:
164 // make inline tables into tables
165 display
= NS_STYLE_DISPLAY_TABLE
;
168 case NS_STYLE_DISPLAY_INLINE_FLEX
:
169 // make inline flex containers into flex containers
170 display
= NS_STYLE_DISPLAY_FLEX
;
173 case NS_STYLE_DISPLAY_INLINE_GRID
:
174 // make inline grid containers into grid containers
175 display
= NS_STYLE_DISPLAY_GRID
;
180 display
= NS_STYLE_DISPLAY_BLOCK
;
184 // EnsureInlineDisplay:
185 // - if the display value (argument) is not an inline type
186 // then we set it to a valid inline display value
189 nsRuleNode::EnsureInlineDisplay(uint8_t& display
)
191 // see if the display value is already inline
193 case NS_STYLE_DISPLAY_BLOCK
:
194 display
= NS_STYLE_DISPLAY_INLINE_BLOCK
;
196 case NS_STYLE_DISPLAY_TABLE
:
197 display
= NS_STYLE_DISPLAY_INLINE_TABLE
;
199 case NS_STYLE_DISPLAY_FLEX
:
200 display
= NS_STYLE_DISPLAY_INLINE_FLEX
;
202 case NS_STYLE_DISPLAY_GRID
:
203 display
= NS_STYLE_DISPLAY_INLINE_GRID
;
205 case NS_STYLE_DISPLAY_BOX
:
206 display
= NS_STYLE_DISPLAY_INLINE_BOX
;
208 case NS_STYLE_DISPLAY_STACK
:
209 display
= NS_STYLE_DISPLAY_INLINE_STACK
;
214 static nscoord
CalcLengthWith(const nsCSSValue
& aValue
,
216 const nsStyleFont
* aStyleFont
,
217 nsStyleContext
* aStyleContext
,
218 nsPresContext
* aPresContext
,
219 bool aUseProvidedRootEmSize
,
220 bool aUseUserFontSet
,
221 bool& aCanStoreInRuleTree
);
223 struct CalcLengthCalcOps
: public css::BasicCoordCalcOps
,
224 public css::NumbersAlreadyNormalizedOps
226 // All of the parameters to CalcLengthWith except aValue.
227 const nscoord mFontSize
;
228 const nsStyleFont
* const mStyleFont
;
229 nsStyleContext
* const mStyleContext
;
230 nsPresContext
* const mPresContext
;
231 const bool mUseProvidedRootEmSize
;
232 const bool mUseUserFontSet
;
233 bool& mCanStoreInRuleTree
;
235 CalcLengthCalcOps(nscoord aFontSize
, const nsStyleFont
* aStyleFont
,
236 nsStyleContext
* aStyleContext
, nsPresContext
* aPresContext
,
237 bool aUseProvidedRootEmSize
, bool aUseUserFontSet
,
238 bool& aCanStoreInRuleTree
)
239 : mFontSize(aFontSize
),
240 mStyleFont(aStyleFont
),
241 mStyleContext(aStyleContext
),
242 mPresContext(aPresContext
),
243 mUseProvidedRootEmSize(aUseProvidedRootEmSize
),
244 mUseUserFontSet(aUseUserFontSet
),
245 mCanStoreInRuleTree(aCanStoreInRuleTree
)
249 result_type
ComputeLeafValue(const nsCSSValue
& aValue
)
251 return CalcLengthWith(aValue
, mFontSize
, mStyleFont
,
252 mStyleContext
, mPresContext
, mUseProvidedRootEmSize
,
253 mUseUserFontSet
, mCanStoreInRuleTree
);
257 static inline nscoord
ScaleCoordRound(const nsCSSValue
& aValue
, float aFactor
)
259 return NSToCoordRoundWithClamp(aValue
.GetFloatValue() * aFactor
);
262 static inline nscoord
ScaleViewportCoordTrunc(const nsCSSValue
& aValue
,
263 nscoord aViewportSize
)
265 // For units (like percentages and viewport units) where authors might
266 // repeatedly use a value and expect some multiple of the value to be
267 // smaller than a container, we need to use floor rather than round.
268 // We need to use division by 100.0 rather than multiplication by 0.1f
269 // to avoid introducing error.
270 return NSToCoordTruncClamped(aValue
.GetFloatValue() *
271 aViewportSize
/ 100.0f
);
274 already_AddRefed
<nsFontMetrics
>
275 GetMetricsFor(nsPresContext
* aPresContext
,
276 nsStyleContext
* aStyleContext
,
277 const nsStyleFont
* aStyleFont
,
278 nscoord aFontSize
, // overrides value from aStyleFont
279 bool aUseUserFontSet
)
281 nsFont font
= aStyleFont
->mFont
;
282 font
.size
= aFontSize
;
283 gfxUserFontSet
*fs
= nullptr;
284 if (aUseUserFontSet
) {
285 fs
= aPresContext
->GetUserFontSet();
287 gfxTextPerfMetrics
*tp
= aPresContext
->GetTextPerfMetrics();
288 nsRefPtr
<nsFontMetrics
> fm
;
289 aPresContext
->DeviceContext()->GetMetricsFor(font
,
290 aStyleFont
->mLanguage
,
291 fs
, tp
, *getter_AddRefs(fm
));
296 static nsSize
CalcViewportUnitsScale(nsPresContext
* aPresContext
)
298 // The caller is making use of viewport units, so notify the pres context
299 // that it will need to rebuild the rule tree if the size of the viewport
301 aPresContext
->SetUsesViewportUnits(true);
303 // The default (when we have 'overflow: auto' on the root element, or
304 // trivially for 'overflow: hidden' since we never have scrollbars in that
305 // case) is to define the scale of the viewport units without considering
307 nsSize
viewportSize(aPresContext
->GetVisibleArea().Size());
309 // Check for 'overflow: scroll' styles on the root scroll frame. If we find
310 // any, the standard requires us to take scrollbars into account.
311 nsIScrollableFrame
* scrollFrame
=
312 aPresContext
->PresShell()->GetRootScrollFrameAsScrollable();
314 ScrollbarStyles
styles(scrollFrame
->GetScrollbarStyles());
316 if (styles
.mHorizontal
== NS_STYLE_OVERFLOW_SCROLL
||
317 styles
.mVertical
== NS_STYLE_OVERFLOW_SCROLL
) {
318 // Gather scrollbar size information.
319 nsRefPtr
<nsRenderingContext
> context
=
320 aPresContext
->PresShell()->CreateReferenceRenderingContext();
321 nsMargin
sizes(scrollFrame
->GetDesiredScrollbarSizes(aPresContext
, context
));
323 if (styles
.mHorizontal
== NS_STYLE_OVERFLOW_SCROLL
) {
324 // 'overflow-x: scroll' means we must consider the horizontal scrollbar,
325 // which affects the scale of viewport height units.
326 viewportSize
.height
-= sizes
.TopBottom();
329 if (styles
.mVertical
== NS_STYLE_OVERFLOW_SCROLL
) {
330 // 'overflow-y: scroll' means we must consider the vertical scrollbar,
331 // which affects the scale of viewport width units.
332 viewportSize
.width
-= sizes
.LeftRight();
340 static nscoord
CalcLengthWith(const nsCSSValue
& aValue
,
342 const nsStyleFont
* aStyleFont
,
343 nsStyleContext
* aStyleContext
,
344 nsPresContext
* aPresContext
,
345 bool aUseProvidedRootEmSize
,
346 // aUseUserFontSet should always be true
347 // except when called from
348 // CalcLengthWithInitialFont.
349 bool aUseUserFontSet
,
350 bool& aCanStoreInRuleTree
)
352 NS_ASSERTION(aValue
.IsLengthUnit() || aValue
.IsCalcUnit(),
353 "not a length or calc unit");
354 NS_ASSERTION(aStyleFont
|| aStyleContext
,
355 "Must have style data");
356 NS_ASSERTION(!aStyleFont
|| !aStyleContext
,
357 "Duplicate sources of data");
358 NS_ASSERTION(aPresContext
, "Must have prescontext");
360 if (aValue
.IsFixedLengthUnit()) {
361 return aValue
.GetFixedLength(aPresContext
);
363 if (aValue
.IsPixelLengthUnit()) {
364 return aValue
.GetPixelLength();
366 if (aValue
.IsCalcUnit()) {
367 // For properties for which lengths are the *only* units accepted in
368 // calc(), we can handle calc() here and just compute a final
369 // result. We ensure that we don't get to this code for other
370 // properties by not calling CalcLength in those cases: SetCoord
371 // only calls CalcLength for a calc when it is appropriate to do so.
372 CalcLengthCalcOps
ops(aFontSize
, aStyleFont
,
373 aStyleContext
, aPresContext
,
374 aUseProvidedRootEmSize
, aUseUserFontSet
,
375 aCanStoreInRuleTree
);
376 return css::ComputeCalc(aValue
, ops
);
378 switch (aValue
.GetUnit()) {
379 // nsPresContext::SetVisibleArea and
380 // nsPresContext::MediaFeatureValuesChanged handle dynamic changes
381 // of the basis for viewport units by rebuilding the rule tree and
382 // style context tree. Not caching them in the rule tree wouldn't
383 // be sufficient to handle these changes because we also need a way
384 // to get rid of cached values in the style context tree without any
385 // changes in specified style. We can either do this by not caching
386 // in the rule tree and then throwing away the style context tree
387 // for dynamic viewport size changes, or by allowing caching in the
388 // rule tree and using the existing rebuild style data path that
389 // throws away the style context and the rule tree.
390 // Thus we do cache viewport units in the rule tree. This allows us
391 // to benefit from the performance advantages of the rule tree
392 // (e.g., faster dynamic changes on other things, like transforms)
393 // and allows us not to need an additional code path, in exchange
394 // for an increased cost to dynamic changes to the viewport size
395 // when viewport units are in use.
396 case eCSSUnit_ViewportWidth
: {
397 nscoord viewportWidth
= CalcViewportUnitsScale(aPresContext
).width
;
398 return ScaleViewportCoordTrunc(aValue
, viewportWidth
);
400 case eCSSUnit_ViewportHeight
: {
401 nscoord viewportHeight
= CalcViewportUnitsScale(aPresContext
).height
;
402 return ScaleViewportCoordTrunc(aValue
, viewportHeight
);
404 case eCSSUnit_ViewportMin
: {
405 nsSize
vuScale(CalcViewportUnitsScale(aPresContext
));
406 nscoord viewportMin
= min(vuScale
.width
, vuScale
.height
);
407 return ScaleViewportCoordTrunc(aValue
, viewportMin
);
409 case eCSSUnit_ViewportMax
: {
410 nsSize
vuScale(CalcViewportUnitsScale(aPresContext
));
411 nscoord viewportMax
= max(vuScale
.width
, vuScale
.height
);
412 return ScaleViewportCoordTrunc(aValue
, viewportMax
);
414 // While we could deal with 'rem' units correctly by simply not
415 // caching any data that uses them in the rule tree, it's valuable
416 // to store them in the rule tree (for faster dynamic changes of
417 // other things). And since the font size of the root element
418 // changes rarely, we instead handle dynamic changes to the root
419 // element's font size by rebuilding all style data in
420 // nsCSSFrameConstructor::RestyleElement.
421 case eCSSUnit_RootEM
: {
422 aPresContext
->SetUsesRootEMUnits(true);
423 nscoord rootFontSize
;
425 // NOTE: Be very careful with |styleFont|, since we haven't set
426 // aCanStoreInRuleTree to false yet, so we don't want to introduce
427 // any dependencies on aStyleContext's data here.
428 const nsStyleFont
*styleFont
=
429 aStyleFont
? aStyleFont
: aStyleContext
->StyleFont();
431 if (aUseProvidedRootEmSize
) {
432 // We should use the provided aFontSize as the reference length to
433 // scale. This only happens when we are calculating font-size or
434 // an equivalent (scriptminsize or CalcLengthWithInitialFont) on
435 // the root element, in which case aFontSize is already the
437 if (aFontSize
== -1) {
438 // XXX Should this be styleFont->mSize instead to avoid taking
439 // minfontsize prefs into account?
440 aFontSize
= styleFont
->mFont
.size
;
442 rootFontSize
= aFontSize
;
443 } else if (aStyleContext
&& !aStyleContext
->GetParent()) {
444 // This is the root element (XXX we don't really know this, but
445 // nsRuleNode::SetFont makes the same assumption!), so we should
446 // use StyleFont on this context to get the root element's
448 rootFontSize
= styleFont
->mFont
.size
;
450 // This is not the root element or we are calculating something other
451 // than font size, so rem is relative to the root element's font size.
452 nsRefPtr
<nsStyleContext
> rootStyle
;
453 const nsStyleFont
*rootStyleFont
= styleFont
;
454 Element
* docElement
= aPresContext
->Document()->GetRootElement();
457 nsIFrame
* rootFrame
= docElement
->GetPrimaryFrame();
459 rootStyle
= rootFrame
->StyleContext();
461 rootStyle
= aPresContext
->StyleSet()->ResolveStyleFor(docElement
,
464 rootStyleFont
= rootStyle
->StyleFont();
467 rootFontSize
= rootStyleFont
->mFont
.size
;
470 return ScaleCoordRound(aValue
, float(rootFontSize
));
473 // Fall through to the code for units that can't be stored in the
474 // rule tree because they depend on font data.
477 // Common code for units that depend on the element's font data and
478 // thus can't be stored in the rule tree:
479 aCanStoreInRuleTree
= false;
480 const nsStyleFont
*styleFont
=
481 aStyleFont
? aStyleFont
: aStyleContext
->StyleFont();
482 if (aFontSize
== -1) {
483 // XXX Should this be styleFont->mSize instead to avoid taking minfontsize
484 // prefs into account?
485 aFontSize
= styleFont
->mFont
.size
;
487 switch (aValue
.GetUnit()) {
489 // CSS2.1 specifies that this unit scales to the computed font
490 // size, not the em-width in the font metrics, despite the name.
491 return ScaleCoordRound(aValue
, float(aFontSize
));
493 case eCSSUnit_XHeight
: {
494 nsRefPtr
<nsFontMetrics
> fm
=
495 GetMetricsFor(aPresContext
, aStyleContext
, styleFont
,
496 aFontSize
, aUseUserFontSet
);
497 return ScaleCoordRound(aValue
, float(fm
->XHeight()));
499 case eCSSUnit_Char
: {
500 nsRefPtr
<nsFontMetrics
> fm
=
501 GetMetricsFor(aPresContext
, aStyleContext
, styleFont
,
502 aFontSize
, aUseUserFontSet
);
503 gfxFloat zeroWidth
= (fm
->GetThebesFontGroup()->GetFontAt(0)
504 ->GetMetrics().zeroOrAveCharWidth
);
506 return ScaleCoordRound(aValue
, ceil(aPresContext
->AppUnitsPerDevPixel() *
510 NS_NOTREACHED("unexpected unit");
517 nsRuleNode::CalcLength(const nsCSSValue
& aValue
,
518 nsStyleContext
* aStyleContext
,
519 nsPresContext
* aPresContext
,
520 bool& aCanStoreInRuleTree
)
522 NS_ASSERTION(aStyleContext
, "Must have style data");
524 return CalcLengthWith(aValue
, -1, nullptr,
525 aStyleContext
, aPresContext
,
526 false, true, aCanStoreInRuleTree
);
529 /* Inline helper function to redirect requests to CalcLength. */
530 static inline nscoord
CalcLength(const nsCSSValue
& aValue
,
531 nsStyleContext
* aStyleContext
,
532 nsPresContext
* aPresContext
,
533 bool& aCanStoreInRuleTree
)
535 return nsRuleNode::CalcLength(aValue
, aStyleContext
,
536 aPresContext
, aCanStoreInRuleTree
);
540 nsRuleNode::CalcLengthWithInitialFont(nsPresContext
* aPresContext
,
541 const nsCSSValue
& aValue
)
543 nsStyleFont
defaultFont(aPresContext
); // FIXME: best language?
544 bool canStoreInRuleTree
;
545 return CalcLengthWith(aValue
, -1, &defaultFont
,
546 nullptr, aPresContext
,
547 true, false, canStoreInRuleTree
);
550 struct LengthPercentPairCalcOps
: public css::NumbersAlreadyNormalizedOps
552 typedef nsRuleNode::ComputedCalc result_type
;
554 LengthPercentPairCalcOps(nsStyleContext
* aContext
,
555 nsPresContext
* aPresContext
,
556 bool& aCanStoreInRuleTree
)
557 : mContext(aContext
),
558 mPresContext(aPresContext
),
559 mCanStoreInRuleTree(aCanStoreInRuleTree
),
560 mHasPercent(false) {}
562 nsStyleContext
* mContext
;
563 nsPresContext
* mPresContext
;
564 bool& mCanStoreInRuleTree
;
567 result_type
ComputeLeafValue(const nsCSSValue
& aValue
)
569 if (aValue
.GetUnit() == eCSSUnit_Percent
) {
571 return result_type(0, aValue
.GetPercentValue());
573 return result_type(CalcLength(aValue
, mContext
, mPresContext
,
574 mCanStoreInRuleTree
),
579 MergeAdditive(nsCSSUnit aCalcFunction
,
580 result_type aValue1
, result_type aValue2
)
582 if (aCalcFunction
== eCSSUnit_Calc_Plus
) {
583 return result_type(NSCoordSaturatingAdd(aValue1
.mLength
,
585 aValue1
.mPercent
+ aValue2
.mPercent
);
587 NS_ABORT_IF_FALSE(aCalcFunction
== eCSSUnit_Calc_Minus
,
588 "min() and max() are not allowed in calc() on "
590 return result_type(NSCoordSaturatingSubtract(aValue1
.mLength
,
592 aValue1
.mPercent
- aValue2
.mPercent
);
596 MergeMultiplicativeL(nsCSSUnit aCalcFunction
,
597 float aValue1
, result_type aValue2
)
599 NS_ABORT_IF_FALSE(aCalcFunction
== eCSSUnit_Calc_Times_L
,
601 return result_type(NSCoordSaturatingMultiply(aValue2
.mLength
, aValue1
),
602 aValue1
* aValue2
.mPercent
);
606 MergeMultiplicativeR(nsCSSUnit aCalcFunction
,
607 result_type aValue1
, float aValue2
)
609 NS_ABORT_IF_FALSE(aCalcFunction
== eCSSUnit_Calc_Times_R
||
610 aCalcFunction
== eCSSUnit_Calc_Divided
,
612 if (aCalcFunction
== eCSSUnit_Calc_Divided
) {
613 aValue2
= 1.0f
/ aValue2
;
615 return result_type(NSCoordSaturatingMultiply(aValue1
.mLength
, aValue2
),
616 aValue1
.mPercent
* aValue2
);
622 SpecifiedCalcToComputedCalc(const nsCSSValue
& aValue
, nsStyleCoord
& aCoord
,
623 nsStyleContext
* aStyleContext
,
624 bool& aCanStoreInRuleTree
)
626 LengthPercentPairCalcOps
ops(aStyleContext
, aStyleContext
->PresContext(),
627 aCanStoreInRuleTree
);
628 nsRuleNode::ComputedCalc vals
= ComputeCalc(aValue
, ops
);
630 nsStyleCoord::Calc
* calcObj
= new nsStyleCoord::Calc
;
632 calcObj
->mLength
= vals
.mLength
;
633 calcObj
->mPercent
= vals
.mPercent
;
634 calcObj
->mHasPercent
= ops
.mHasPercent
;
636 aCoord
.SetCalcValue(calcObj
);
639 /* static */ nsRuleNode::ComputedCalc
640 nsRuleNode::SpecifiedCalcToComputedCalc(const nsCSSValue
& aValue
,
641 nsStyleContext
* aStyleContext
,
642 nsPresContext
* aPresContext
,
643 bool& aCanStoreInRuleTree
)
645 LengthPercentPairCalcOps
ops(aStyleContext
, aPresContext
,
646 aCanStoreInRuleTree
);
647 return ComputeCalc(aValue
, ops
);
650 // This is our public API for handling calc() expressions that involve
653 nsRuleNode::ComputeComputedCalc(const nsStyleCoord
& aValue
,
654 nscoord aPercentageBasis
)
656 nsStyleCoord::Calc
* calc
= aValue
.GetCalcValue();
657 return calc
->mLength
+
658 NSToCoordFloorClamped(aPercentageBasis
* calc
->mPercent
);
662 nsRuleNode::ComputeCoordPercentCalc(const nsStyleCoord
& aCoord
,
663 nscoord aPercentageBasis
)
665 switch (aCoord
.GetUnit()) {
666 case eStyleUnit_Coord
:
667 return aCoord
.GetCoordValue();
668 case eStyleUnit_Percent
:
669 return NSToCoordFloorClamped(aPercentageBasis
* aCoord
.GetPercentValue());
670 case eStyleUnit_Calc
:
671 return ComputeComputedCalc(aCoord
, aPercentageBasis
);
673 NS_ABORT_IF_FALSE(false, "unexpected unit");
678 /* Given an enumerated value that represents a box position, converts it to
679 * a float representing the percentage of the box it corresponds to. For
680 * example, "center" becomes 0.5f.
682 * @param aEnumValue The enumerated value.
683 * @return The float percent it corresponds to.
686 GetFloatFromBoxPosition(int32_t aEnumValue
)
688 switch (aEnumValue
) {
689 case NS_STYLE_BG_POSITION_LEFT
:
690 case NS_STYLE_BG_POSITION_TOP
:
692 case NS_STYLE_BG_POSITION_RIGHT
:
693 case NS_STYLE_BG_POSITION_BOTTOM
:
696 NS_NOTREACHED("unexpected value");
698 case NS_STYLE_BG_POSITION_CENTER
:
703 #define SETCOORD_NORMAL 0x01 // N
704 #define SETCOORD_AUTO 0x02 // A
705 #define SETCOORD_INHERIT 0x04 // H
706 #define SETCOORD_PERCENT 0x08 // P
707 #define SETCOORD_FACTOR 0x10 // F
708 #define SETCOORD_LENGTH 0x20 // L
709 #define SETCOORD_INTEGER 0x40 // I
710 #define SETCOORD_ENUMERATED 0x80 // E
711 #define SETCOORD_NONE 0x100 // O
712 #define SETCOORD_INITIAL_ZERO 0x200
713 #define SETCOORD_INITIAL_AUTO 0x400
714 #define SETCOORD_INITIAL_NONE 0x800
715 #define SETCOORD_INITIAL_NORMAL 0x1000
716 #define SETCOORD_INITIAL_HALF 0x2000
717 #define SETCOORD_INITIAL_HUNDRED_PCT 0x00004000
718 #define SETCOORD_INITIAL_FACTOR_ONE 0x00008000
719 #define SETCOORD_INITIAL_FACTOR_ZERO 0x00010000
720 #define SETCOORD_CALC_LENGTH_ONLY 0x00020000
721 #define SETCOORD_CALC_CLAMP_NONNEGATIVE 0x00040000 // modifier for CALC_LENGTH_ONLY
722 #define SETCOORD_STORE_CALC 0x00080000
723 #define SETCOORD_BOX_POSITION 0x00100000 // exclusive with _ENUMERATED
724 #define SETCOORD_ANGLE 0x00200000
725 #define SETCOORD_UNSET_INHERIT 0x00400000
726 #define SETCOORD_UNSET_INITIAL 0x00800000
728 #define SETCOORD_LP (SETCOORD_LENGTH | SETCOORD_PERCENT)
729 #define SETCOORD_LH (SETCOORD_LENGTH | SETCOORD_INHERIT)
730 #define SETCOORD_AH (SETCOORD_AUTO | SETCOORD_INHERIT)
731 #define SETCOORD_LAH (SETCOORD_AUTO | SETCOORD_LENGTH | SETCOORD_INHERIT)
732 #define SETCOORD_LPH (SETCOORD_LP | SETCOORD_INHERIT)
733 #define SETCOORD_LPAH (SETCOORD_LP | SETCOORD_AH)
734 #define SETCOORD_LPE (SETCOORD_LP | SETCOORD_ENUMERATED)
735 #define SETCOORD_LPEH (SETCOORD_LPE | SETCOORD_INHERIT)
736 #define SETCOORD_LPAEH (SETCOORD_LPAH | SETCOORD_ENUMERATED)
737 #define SETCOORD_LPO (SETCOORD_LP | SETCOORD_NONE)
738 #define SETCOORD_LPOH (SETCOORD_LPH | SETCOORD_NONE)
739 #define SETCOORD_LPOEH (SETCOORD_LPOH | SETCOORD_ENUMERATED)
740 #define SETCOORD_LE (SETCOORD_LENGTH | SETCOORD_ENUMERATED)
741 #define SETCOORD_LEH (SETCOORD_LE | SETCOORD_INHERIT)
742 #define SETCOORD_IA (SETCOORD_INTEGER | SETCOORD_AUTO)
743 #define SETCOORD_LAE (SETCOORD_LENGTH | SETCOORD_AUTO | SETCOORD_ENUMERATED)
745 // changes aCoord iff it returns true
746 static bool SetCoord(const nsCSSValue
& aValue
, nsStyleCoord
& aCoord
,
747 const nsStyleCoord
& aParentCoord
,
748 int32_t aMask
, nsStyleContext
* aStyleContext
,
749 nsPresContext
* aPresContext
,
750 bool& aCanStoreInRuleTree
)
753 if (aValue
.GetUnit() == eCSSUnit_Null
) {
756 else if ((((aMask
& SETCOORD_LENGTH
) != 0) &&
757 aValue
.IsLengthUnit()) ||
758 (((aMask
& SETCOORD_CALC_LENGTH_ONLY
) != 0) &&
759 aValue
.IsCalcUnit())) {
760 nscoord len
= CalcLength(aValue
, aStyleContext
, aPresContext
,
761 aCanStoreInRuleTree
);
762 if ((aMask
& SETCOORD_CALC_CLAMP_NONNEGATIVE
) && len
< 0) {
763 NS_ASSERTION(aValue
.IsCalcUnit(),
764 "parser should have ensured no nonnegative lengths");
767 aCoord
.SetCoordValue(len
);
769 else if (((aMask
& SETCOORD_PERCENT
) != 0) &&
770 (aValue
.GetUnit() == eCSSUnit_Percent
)) {
771 aCoord
.SetPercentValue(aValue
.GetPercentValue());
773 else if (((aMask
& SETCOORD_INTEGER
) != 0) &&
774 (aValue
.GetUnit() == eCSSUnit_Integer
)) {
775 aCoord
.SetIntValue(aValue
.GetIntValue(), eStyleUnit_Integer
);
777 else if (((aMask
& SETCOORD_ENUMERATED
) != 0) &&
778 (aValue
.GetUnit() == eCSSUnit_Enumerated
)) {
779 aCoord
.SetIntValue(aValue
.GetIntValue(), eStyleUnit_Enumerated
);
781 else if (((aMask
& SETCOORD_BOX_POSITION
) != 0) &&
782 (aValue
.GetUnit() == eCSSUnit_Enumerated
)) {
783 aCoord
.SetPercentValue(GetFloatFromBoxPosition(aValue
.GetIntValue()));
785 else if (((aMask
& SETCOORD_AUTO
) != 0) &&
786 (aValue
.GetUnit() == eCSSUnit_Auto
)) {
787 aCoord
.SetAutoValue();
789 else if ((((aMask
& SETCOORD_INHERIT
) != 0) &&
790 aValue
.GetUnit() == eCSSUnit_Inherit
) ||
791 (((aMask
& SETCOORD_UNSET_INHERIT
) != 0) &&
792 aValue
.GetUnit() == eCSSUnit_Unset
)) {
793 aCoord
= aParentCoord
; // just inherit value from parent
794 aCanStoreInRuleTree
= false;
796 else if (((aMask
& SETCOORD_NORMAL
) != 0) &&
797 (aValue
.GetUnit() == eCSSUnit_Normal
)) {
798 aCoord
.SetNormalValue();
800 else if (((aMask
& SETCOORD_NONE
) != 0) &&
801 (aValue
.GetUnit() == eCSSUnit_None
)) {
802 aCoord
.SetNoneValue();
804 else if (((aMask
& SETCOORD_FACTOR
) != 0) &&
805 (aValue
.GetUnit() == eCSSUnit_Number
)) {
806 aCoord
.SetFactorValue(aValue
.GetFloatValue());
808 else if (((aMask
& SETCOORD_STORE_CALC
) != 0) &&
809 (aValue
.IsCalcUnit())) {
810 SpecifiedCalcToComputedCalc(aValue
, aCoord
, aStyleContext
,
811 aCanStoreInRuleTree
);
813 else if (aValue
.GetUnit() == eCSSUnit_Initial
||
814 (aValue
.GetUnit() == eCSSUnit_Unset
&&
815 ((aMask
& SETCOORD_UNSET_INITIAL
) != 0))) {
816 if ((aMask
& SETCOORD_INITIAL_AUTO
) != 0) {
817 aCoord
.SetAutoValue();
819 else if ((aMask
& SETCOORD_INITIAL_ZERO
) != 0) {
820 aCoord
.SetCoordValue(0);
822 else if ((aMask
& SETCOORD_INITIAL_FACTOR_ZERO
) != 0) {
823 aCoord
.SetFactorValue(0.0f
);
825 else if ((aMask
& SETCOORD_INITIAL_NONE
) != 0) {
826 aCoord
.SetNoneValue();
828 else if ((aMask
& SETCOORD_INITIAL_NORMAL
) != 0) {
829 aCoord
.SetNormalValue();
831 else if ((aMask
& SETCOORD_INITIAL_HALF
) != 0) {
832 aCoord
.SetPercentValue(0.5f
);
834 else if ((aMask
& SETCOORD_INITIAL_HUNDRED_PCT
) != 0) {
835 aCoord
.SetPercentValue(1.0f
);
837 else if ((aMask
& SETCOORD_INITIAL_FACTOR_ONE
) != 0) {
838 aCoord
.SetFactorValue(1.0f
);
841 result
= false; // didn't set anything
844 else if ((aMask
& SETCOORD_ANGLE
) != 0 &&
845 (aValue
.IsAngularUnit())) {
847 switch (aValue
.GetUnit()) {
848 case eCSSUnit_Degree
: unit
= eStyleUnit_Degree
; break;
849 case eCSSUnit_Grad
: unit
= eStyleUnit_Grad
; break;
850 case eCSSUnit_Radian
: unit
= eStyleUnit_Radian
; break;
851 case eCSSUnit_Turn
: unit
= eStyleUnit_Turn
; break;
852 default: NS_NOTREACHED("unrecognized angular unit");
853 unit
= eStyleUnit_Degree
;
855 aCoord
.SetAngleValue(aValue
.GetAngleValue(), unit
);
858 result
= false; // didn't set anything
863 // This inline function offers a shortcut for SetCoord() by refusing to accept
864 // SETCOORD_LENGTH, SETCOORD_INHERIT and SETCOORD_UNSET_* masks.
865 static inline bool SetAbsCoord(const nsCSSValue
& aValue
,
866 nsStyleCoord
& aCoord
,
869 NS_ABORT_IF_FALSE((aMask
& (SETCOORD_LH
| SETCOORD_UNSET_INHERIT
|
870 SETCOORD_UNSET_INITIAL
)) == 0,
871 "does not handle SETCOORD_LENGTH, SETCOORD_INHERIT and "
874 // The values of the following variables will never be used; so it does not
875 // matter what to set.
876 const nsStyleCoord dummyParentCoord
;
877 nsStyleContext
* dummyStyleContext
= nullptr;
878 nsPresContext
* dummyPresContext
= nullptr;
879 bool dummyCanStoreInRuleTree
= true;
881 bool rv
= SetCoord(aValue
, aCoord
, dummyParentCoord
, aMask
,
882 dummyStyleContext
, dummyPresContext
,
883 dummyCanStoreInRuleTree
);
884 NS_ABORT_IF_FALSE(dummyCanStoreInRuleTree
,
885 "SetCoord() should not modify dummyCanStoreInRuleTree.");
890 /* Given a specified value that might be a pair value, call SetCoord twice,
891 * either using each member of the pair, or using the unpaired value twice.
894 SetPairCoords(const nsCSSValue
& aValue
,
895 nsStyleCoord
& aCoordX
, nsStyleCoord
& aCoordY
,
896 const nsStyleCoord
& aParentX
, const nsStyleCoord
& aParentY
,
897 int32_t aMask
, nsStyleContext
* aStyleContext
,
898 nsPresContext
* aPresContext
, bool& aCanStoreInRuleTree
)
900 const nsCSSValue
& valX
=
901 aValue
.GetUnit() == eCSSUnit_Pair
? aValue
.GetPairValue().mXValue
: aValue
;
902 const nsCSSValue
& valY
=
903 aValue
.GetUnit() == eCSSUnit_Pair
? aValue
.GetPairValue().mYValue
: aValue
;
905 bool cX
= SetCoord(valX
, aCoordX
, aParentX
, aMask
, aStyleContext
,
906 aPresContext
, aCanStoreInRuleTree
);
907 mozilla::DebugOnly
<bool> cY
= SetCoord(valY
, aCoordY
, aParentY
, aMask
,
908 aStyleContext
, aPresContext
, aCanStoreInRuleTree
);
909 NS_ABORT_IF_FALSE(cX
== cY
, "changed one but not the other");
913 static bool SetColor(const nsCSSValue
& aValue
, const nscolor aParentColor
,
914 nsPresContext
* aPresContext
, nsStyleContext
*aContext
,
915 nscolor
& aResult
, bool& aCanStoreInRuleTree
)
918 nsCSSUnit unit
= aValue
.GetUnit();
920 if (aValue
.IsNumericColorUnit()) {
921 aResult
= aValue
.GetColorValue();
924 else if (eCSSUnit_Ident
== unit
) {
926 aValue
.GetStringValue(value
);
928 if (NS_ColorNameToRGB(value
, &rgba
)) {
933 else if (eCSSUnit_EnumColor
== unit
) {
934 int32_t intValue
= aValue
.GetIntValue();
936 LookAndFeel::ColorID colorID
= (LookAndFeel::ColorID
) intValue
;
937 if (NS_SUCCEEDED(LookAndFeel::GetColor(colorID
, &aResult
))) {
942 aResult
= NS_RGB(0, 0, 0);
945 case NS_COLOR_MOZ_HYPERLINKTEXT
:
947 aResult
= aPresContext
->DefaultLinkColor();
951 case NS_COLOR_MOZ_VISITEDHYPERLINKTEXT
:
953 aResult
= aPresContext
->DefaultVisitedLinkColor();
957 case NS_COLOR_MOZ_ACTIVEHYPERLINKTEXT
:
959 aResult
= aPresContext
->DefaultActiveLinkColor();
963 case NS_COLOR_CURRENTCOLOR
:
964 // The data computed from this can't be shared in the rule tree
965 // because they could be used on a node with a different color
966 aCanStoreInRuleTree
= false;
968 aResult
= aContext
->StyleColor()->mColor
;
972 case NS_COLOR_MOZ_DEFAULT_COLOR
:
974 aResult
= aPresContext
->DefaultColor();
978 case NS_COLOR_MOZ_DEFAULT_BACKGROUND_COLOR
:
980 aResult
= aPresContext
->DefaultBackgroundColor();
985 NS_NOTREACHED("Should never have an unknown negative colorID.");
990 else if (eCSSUnit_Inherit
== unit
) {
991 aResult
= aParentColor
;
993 aCanStoreInRuleTree
= false;
995 else if (eCSSUnit_Enumerated
== unit
&&
996 aValue
.GetIntValue() == NS_STYLE_COLOR_INHERIT_FROM_BODY
) {
997 NS_ASSERTION(aPresContext
->CompatibilityMode() == eCompatibility_NavQuirks
,
998 "Should only get this value in quirks mode");
999 // We just grab the color from the prescontext, and rely on the fact that
1000 // if the body color ever changes all its descendants will get new style
1001 // contexts (but NOT necessarily new rulenodes).
1002 aResult
= aPresContext
->BodyTextColor();
1004 aCanStoreInRuleTree
= false;
1009 static void SetGradientCoord(const nsCSSValue
& aValue
, nsPresContext
* aPresContext
,
1010 nsStyleContext
* aContext
, nsStyleCoord
& aResult
,
1011 bool& aCanStoreInRuleTree
)
1013 // OK to pass bad aParentCoord since we're not passing SETCOORD_INHERIT
1014 if (!SetCoord(aValue
, aResult
, nsStyleCoord(),
1015 SETCOORD_LPO
| SETCOORD_BOX_POSITION
| SETCOORD_STORE_CALC
,
1016 aContext
, aPresContext
, aCanStoreInRuleTree
)) {
1017 NS_NOTREACHED("unexpected unit for gradient anchor point");
1018 aResult
.SetNoneValue();
1022 static void SetGradient(const nsCSSValue
& aValue
, nsPresContext
* aPresContext
,
1023 nsStyleContext
* aContext
, nsStyleGradient
& aResult
,
1024 bool& aCanStoreInRuleTree
)
1026 NS_ABORT_IF_FALSE(aValue
.GetUnit() == eCSSUnit_Gradient
,
1027 "The given data is not a gradient");
1029 const nsCSSValueGradient
* gradient
= aValue
.GetGradientValue();
1031 if (gradient
->mIsExplicitSize
) {
1032 SetCoord(gradient
->GetRadiusX(), aResult
.mRadiusX
, nsStyleCoord(),
1033 SETCOORD_LP
| SETCOORD_STORE_CALC
,
1034 aContext
, aPresContext
, aCanStoreInRuleTree
);
1035 if (gradient
->GetRadiusY().GetUnit() != eCSSUnit_None
) {
1036 SetCoord(gradient
->GetRadiusY(), aResult
.mRadiusY
, nsStyleCoord(),
1037 SETCOORD_LP
| SETCOORD_STORE_CALC
,
1038 aContext
, aPresContext
, aCanStoreInRuleTree
);
1039 aResult
.mShape
= NS_STYLE_GRADIENT_SHAPE_ELLIPTICAL
;
1041 aResult
.mRadiusY
= aResult
.mRadiusX
;
1042 aResult
.mShape
= NS_STYLE_GRADIENT_SHAPE_CIRCULAR
;
1044 aResult
.mSize
= NS_STYLE_GRADIENT_SIZE_EXPLICIT_SIZE
;
1045 } else if (gradient
->mIsRadial
) {
1046 if (gradient
->GetRadialShape().GetUnit() == eCSSUnit_Enumerated
) {
1047 aResult
.mShape
= gradient
->GetRadialShape().GetIntValue();
1049 NS_ASSERTION(gradient
->GetRadialShape().GetUnit() == eCSSUnit_None
,
1050 "bad unit for radial shape");
1051 aResult
.mShape
= NS_STYLE_GRADIENT_SHAPE_ELLIPTICAL
;
1053 if (gradient
->GetRadialSize().GetUnit() == eCSSUnit_Enumerated
) {
1054 aResult
.mSize
= gradient
->GetRadialSize().GetIntValue();
1056 NS_ASSERTION(gradient
->GetRadialSize().GetUnit() == eCSSUnit_None
,
1057 "bad unit for radial shape");
1058 aResult
.mSize
= NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER
;
1061 NS_ASSERTION(gradient
->GetRadialShape().GetUnit() == eCSSUnit_None
,
1062 "bad unit for linear shape");
1063 NS_ASSERTION(gradient
->GetRadialSize().GetUnit() == eCSSUnit_None
,
1064 "bad unit for linear size");
1065 aResult
.mShape
= NS_STYLE_GRADIENT_SHAPE_LINEAR
;
1066 aResult
.mSize
= NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER
;
1069 aResult
.mLegacySyntax
= gradient
->mIsLegacySyntax
;
1072 SetGradientCoord(gradient
->mBgPos
.mXValue
, aPresContext
, aContext
,
1073 aResult
.mBgPosX
, aCanStoreInRuleTree
);
1075 SetGradientCoord(gradient
->mBgPos
.mYValue
, aPresContext
, aContext
,
1076 aResult
.mBgPosY
, aCanStoreInRuleTree
);
1078 aResult
.mRepeating
= gradient
->mIsRepeating
;
1081 const nsStyleCoord dummyParentCoord
;
1082 if (!SetCoord(gradient
->mAngle
, aResult
.mAngle
, dummyParentCoord
, SETCOORD_ANGLE
,
1083 aContext
, aPresContext
, aCanStoreInRuleTree
)) {
1084 NS_ASSERTION(gradient
->mAngle
.GetUnit() == eCSSUnit_None
,
1085 "bad unit for gradient angle");
1086 aResult
.mAngle
.SetNoneValue();
1090 for (uint32_t i
= 0; i
< gradient
->mStops
.Length(); i
++) {
1091 nsStyleGradientStop stop
;
1092 const nsCSSValueGradientStop
&valueStop
= gradient
->mStops
[i
];
1094 if (!SetCoord(valueStop
.mLocation
, stop
.mLocation
,
1095 nsStyleCoord(), SETCOORD_LPO
| SETCOORD_STORE_CALC
,
1096 aContext
, aPresContext
, aCanStoreInRuleTree
)) {
1097 NS_NOTREACHED("unexpected unit for gradient stop location");
1100 // inherit is not a valid color for stops, so we pass in a dummy
1102 NS_ASSERTION(valueStop
.mColor
.GetUnit() != eCSSUnit_Inherit
,
1103 "inherit is not a valid color for gradient stops");
1104 SetColor(valueStop
.mColor
, NS_RGB(0, 0, 0), aPresContext
,
1105 aContext
, stop
.mColor
, aCanStoreInRuleTree
);
1107 aResult
.mStops
.AppendElement(stop
);
1111 // -moz-image-rect(<uri>, <top>, <right>, <bottom>, <left>)
1112 static void SetStyleImageToImageRect(nsStyleContext
* aStyleContext
,
1113 const nsCSSValue
& aValue
,
1114 nsStyleImage
& aResult
)
1116 NS_ABORT_IF_FALSE(aValue
.GetUnit() == eCSSUnit_Function
&&
1117 aValue
.EqualsFunction(eCSSKeyword__moz_image_rect
),
1118 "the value is not valid -moz-image-rect()");
1120 nsCSSValue::Array
* arr
= aValue
.GetArrayValue();
1121 NS_ABORT_IF_FALSE(arr
&& arr
->Count() == 6, "invalid number of arguments");
1124 if (arr
->Item(1).GetUnit() == eCSSUnit_Image
) {
1125 NS_SET_IMAGE_REQUEST_WITH_DOC(aResult
.SetImageData
,
1127 arr
->Item(1).GetImageValue
)
1129 NS_WARNING("nsCSSValue::Image::Image() failed?");
1132 // <top>, <right>, <bottom>, <left>
1133 nsStyleSides cropRect
;
1134 NS_FOR_CSS_SIDES(side
) {
1136 const nsCSSValue
& val
= arr
->Item(2 + side
);
1141 SetAbsCoord(val
, coord
, SETCOORD_FACTOR
| SETCOORD_PERCENT
);
1142 NS_ABORT_IF_FALSE(unitOk
, "Incorrect data structure created by CSS parser");
1143 cropRect
.Set(side
, coord
);
1145 aResult
.SetCropRect(&cropRect
);
1148 static void SetStyleImage(nsStyleContext
* aStyleContext
,
1149 const nsCSSValue
& aValue
,
1150 nsStyleImage
& aResult
,
1151 bool& aCanStoreInRuleTree
)
1153 if (aValue
.GetUnit() == eCSSUnit_Null
) {
1159 switch (aValue
.GetUnit()) {
1160 case eCSSUnit_Image
:
1161 NS_SET_IMAGE_REQUEST_WITH_DOC(aResult
.SetImageData
,
1163 aValue
.GetImageValue
)
1165 case eCSSUnit_Function
:
1166 if (aValue
.EqualsFunction(eCSSKeyword__moz_image_rect
)) {
1167 SetStyleImageToImageRect(aStyleContext
, aValue
, aResult
);
1169 NS_NOTREACHED("-moz-image-rect() is the only expected function");
1172 case eCSSUnit_Gradient
:
1174 nsStyleGradient
* gradient
= new nsStyleGradient();
1176 SetGradient(aValue
, aStyleContext
->PresContext(), aStyleContext
,
1177 *gradient
, aCanStoreInRuleTree
);
1178 aResult
.SetGradientData(gradient
);
1182 case eCSSUnit_Element
:
1183 aResult
.SetElementId(aValue
.GetStringBufferValue());
1185 case eCSSUnit_Initial
:
1186 case eCSSUnit_Unset
:
1190 // We might have eCSSUnit_URL values for if-visited style
1191 // contexts, which we can safely treat like 'none'. Otherwise
1192 // this is an unexpected unit.
1193 NS_ASSERTION(aStyleContext
->IsStyleIfVisited() &&
1194 aValue
.GetUnit() == eCSSUnit_URL
,
1195 "unexpected unit; maybe nsCSSValue::Image::Image() failed?");
1200 // flags for SetDiscrete - align values with SETCOORD_* constants
1203 #define SETDSC_NORMAL 0x01 // N
1204 #define SETDSC_AUTO 0x02 // A
1205 #define SETDSC_INTEGER 0x40 // I
1206 #define SETDSC_ENUMERATED 0x80 // E
1207 #define SETDSC_NONE 0x100 // O
1208 #define SETDSC_SYSTEM_FONT 0x2000
1209 #define SETDSC_UNSET_INHERIT 0x00400000
1210 #define SETDSC_UNSET_INITIAL 0x00800000
1212 // no caller cares whether aField was changed or not
1213 template <typename FieldT
,
1214 typename T1
, typename T2
, typename T3
, typename T4
, typename T5
>
1216 SetDiscrete(const nsCSSValue
& aValue
, FieldT
& aField
,
1217 bool& aCanStoreInRuleTree
, uint32_t aMask
,
1218 FieldT aParentValue
,
1223 T5 aSystemFontValue
)
1225 switch (aValue
.GetUnit()) {
1229 // every caller of SetDiscrete provides inherit and initial
1230 // alternatives, so we don't require them to say so in the mask
1231 case eCSSUnit_Inherit
:
1232 aCanStoreInRuleTree
= false;
1233 aField
= aParentValue
;
1236 case eCSSUnit_Initial
:
1237 aField
= aInitialValue
;
1240 // every caller provides one or other of these alternatives,
1241 // but they have to say which
1242 case eCSSUnit_Enumerated
:
1243 if (aMask
& SETDSC_ENUMERATED
) {
1244 aField
= aValue
.GetIntValue();
1249 case eCSSUnit_Integer
:
1250 if (aMask
& SETDSC_INTEGER
) {
1251 aField
= aValue
.GetIntValue();
1256 // remaining possibilities in descending order of frequency of use
1258 if (aMask
& SETDSC_AUTO
) {
1259 aField
= aAutoValue
;
1265 if (aMask
& SETDSC_NONE
) {
1266 aField
= aNoneValue
;
1271 case eCSSUnit_Normal
:
1272 if (aMask
& SETDSC_NORMAL
) {
1273 aField
= aNormalValue
;
1278 case eCSSUnit_System_Font
:
1279 if (aMask
& SETDSC_SYSTEM_FONT
) {
1280 aField
= aSystemFontValue
;
1285 case eCSSUnit_Unset
:
1286 if (aMask
& SETDSC_UNSET_INHERIT
) {
1287 aCanStoreInRuleTree
= false;
1288 aField
= aParentValue
;
1291 if (aMask
& SETDSC_UNSET_INITIAL
) {
1292 aField
= aInitialValue
;
1301 NS_NOTREACHED("SetDiscrete: inappropriate unit");
1304 // flags for SetFactor
1305 #define SETFCT_POSITIVE 0x01 // assert value is >= 0.0f
1306 #define SETFCT_OPACITY 0x02 // clamp value to [0.0f .. 1.0f]
1307 #define SETFCT_NONE 0x04 // allow _None (uses aInitialValue).
1308 #define SETFCT_UNSET_INHERIT 0x00400000
1309 #define SETFCT_UNSET_INITIAL 0x00800000
1312 SetFactor(const nsCSSValue
& aValue
, float& aField
, bool& aCanStoreInRuleTree
,
1313 float aParentValue
, float aInitialValue
, uint32_t aFlags
= 0)
1315 switch (aValue
.GetUnit()) {
1319 case eCSSUnit_Number
:
1320 aField
= aValue
.GetFloatValue();
1321 if (aFlags
& SETFCT_POSITIVE
) {
1322 NS_ASSERTION(aField
>= 0.0f
, "negative value for positive-only property");
1326 if (aFlags
& SETFCT_OPACITY
) {
1334 case eCSSUnit_Inherit
:
1335 aCanStoreInRuleTree
= false;
1336 aField
= aParentValue
;
1339 case eCSSUnit_Initial
:
1340 aField
= aInitialValue
;
1344 if (aFlags
& SETFCT_NONE
) {
1345 aField
= aInitialValue
;
1350 case eCSSUnit_Unset
:
1351 if (aFlags
& SETFCT_UNSET_INHERIT
) {
1352 aCanStoreInRuleTree
= false;
1353 aField
= aParentValue
;
1356 if (aFlags
& SETFCT_UNSET_INITIAL
) {
1357 aField
= aInitialValue
;
1366 NS_NOTREACHED("SetFactor: inappropriate unit");
1369 // Overloaded new operator that allocates from a presShell arena.
1371 nsRuleNode::operator new(size_t sz
, nsPresContext
* aPresContext
) CPP_THROW_NEW
1373 // Check the recycle list first.
1374 return aPresContext
->PresShell()->AllocateByObjectID(nsPresArena::nsRuleNode_id
, sz
);
1377 /* static */ PLDHashOperator
1378 nsRuleNode::EnqueueRuleNodeChildren(PLDHashTable
*table
, PLDHashEntryHdr
*hdr
,
1379 uint32_t number
, void *arg
)
1381 ChildrenHashEntry
*entry
= static_cast<ChildrenHashEntry
*>(hdr
);
1382 nsRuleNode
***destroyQueueTail
= static_cast<nsRuleNode
***>(arg
);
1383 **destroyQueueTail
= entry
->mRuleNode
;
1384 *destroyQueueTail
= &entry
->mRuleNode
->mNextSibling
;
1385 return PL_DHASH_NEXT
;
1388 // Overridden to prevent the global delete from being called, since the memory
1389 // came out of an nsIArena instead of the global delete operator's heap.
1391 nsRuleNode::DestroyInternal(nsRuleNode
***aDestroyQueueTail
)
1393 nsRuleNode
*destroyQueue
, **destroyQueueTail
;
1394 if (aDestroyQueueTail
) {
1395 destroyQueueTail
= *aDestroyQueueTail
;
1397 destroyQueue
= nullptr;
1398 destroyQueueTail
= &destroyQueue
;
1401 if (ChildrenAreHashed()) {
1402 PLDHashTable
*children
= ChildrenHash();
1403 PL_DHashTableEnumerate(children
, EnqueueRuleNodeChildren
,
1405 *destroyQueueTail
= nullptr; // ensure null-termination
1406 PL_DHashTableDestroy(children
);
1407 } else if (HaveChildren()) {
1408 *destroyQueueTail
= ChildrenList();
1410 destroyQueueTail
= &(*destroyQueueTail
)->mNextSibling
;
1411 } while (*destroyQueueTail
);
1413 mChildren
.asVoid
= nullptr;
1415 if (aDestroyQueueTail
) {
1416 // Our caller destroys the queue.
1417 *aDestroyQueueTail
= destroyQueueTail
;
1419 // We have to do destroy the queue. When we destroy each node, it
1420 // will add its children to the queue.
1421 while (destroyQueue
) {
1422 nsRuleNode
*cur
= destroyQueue
;
1423 destroyQueue
= destroyQueue
->mNextSibling
;
1424 if (!destroyQueue
) {
1425 NS_ASSERTION(destroyQueueTail
== &cur
->mNextSibling
, "mangled list");
1426 destroyQueueTail
= &destroyQueue
;
1428 cur
->DestroyInternal(&destroyQueueTail
);
1432 // Destroy ourselves.
1433 this->~nsRuleNode();
1435 // Don't let the memory be freed, since it will be recycled
1436 // instead. Don't call the global operator delete.
1437 mPresContext
->PresShell()->FreeByObjectID(nsPresArena::nsRuleNode_id
, this);
1440 nsRuleNode
* nsRuleNode::CreateRootNode(nsPresContext
* aPresContext
)
1442 return new (aPresContext
)
1443 nsRuleNode(aPresContext
, nullptr, nullptr, 0xff, false);
1446 nsRuleNode::nsRuleNode(nsPresContext
* aContext
, nsRuleNode
* aParent
,
1447 nsIStyleRule
* aRule
, uint8_t aLevel
,
1449 : mPresContext(aContext
),
1452 mNextSibling(nullptr),
1453 mDependentBits((uint32_t(aLevel
) << NS_RULE_NODE_LEVEL_SHIFT
) |
1454 (aIsImportant
? NS_RULE_NODE_IS_IMPORTANT
: 0)),
1458 MOZ_ASSERT(aContext
);
1459 NS_ABORT_IF_FALSE(IsRoot() == !aRule
,
1460 "non-root rule nodes must have a rule");
1462 mChildren
.asVoid
= nullptr;
1463 MOZ_COUNT_CTOR(nsRuleNode
);
1469 NS_ASSERTION(IsRoot() || GetLevel() == aLevel
, "not enough bits");
1470 NS_ASSERTION(IsRoot() || IsImportantRule() == aIsImportant
, "yikes");
1471 /* If IsRoot(), then aContext->StyleSet() is typically null at this
1472 point. In any case, we don't want to treat the root rulenode as
1476 aContext
->StyleSet()->RuleNodeUnused();
1479 // nsStyleSet::GetContext depends on there being only one animation
1481 NS_ABORT_IF_FALSE(IsRoot() || GetLevel() != nsStyleSet::eAnimationSheet
||
1482 mParent
->IsRoot() ||
1483 mParent
->GetLevel() != nsStyleSet::eAnimationSheet
,
1484 "must be only one rule at animation level");
1487 nsRuleNode::~nsRuleNode()
1489 MOZ_COUNT_DTOR(nsRuleNode
);
1490 if (mStyleData
.mResetData
|| mStyleData
.mInheritedData
)
1491 mStyleData
.Destroy(mDependentBits
, mPresContext
);
1498 nsRuleNode::Transition(nsIStyleRule
* aRule
, uint8_t aLevel
,
1499 bool aIsImportantRule
)
1501 nsRuleNode
* next
= nullptr;
1502 nsRuleNode::Key
key(aRule
, aLevel
, aIsImportantRule
);
1504 if (HaveChildren() && !ChildrenAreHashed()) {
1505 int32_t numKids
= 0;
1506 nsRuleNode
* curr
= ChildrenList();
1507 while (curr
&& curr
->GetKey() != key
) {
1508 curr
= curr
->mNextSibling
;
1513 else if (numKids
>= kMaxChildrenInList
)
1514 ConvertChildrenToHash(numKids
);
1517 if (ChildrenAreHashed()) {
1518 ChildrenHashEntry
*entry
= static_cast<ChildrenHashEntry
*>
1519 (PL_DHashTableOperate(ChildrenHash(), &key
, PL_DHASH_ADD
));
1521 NS_WARNING("out of memory");
1524 if (entry
->mRuleNode
)
1525 next
= entry
->mRuleNode
;
1527 next
= entry
->mRuleNode
= new (mPresContext
)
1528 nsRuleNode(mPresContext
, this, aRule
, aLevel
, aIsImportantRule
);
1530 PL_DHashTableRawRemove(ChildrenHash(), entry
);
1531 NS_WARNING("out of memory");
1536 // Create the new entry in our list.
1537 next
= new (mPresContext
)
1538 nsRuleNode(mPresContext
, this, aRule
, aLevel
, aIsImportantRule
);
1540 NS_WARNING("out of memory");
1543 next
->mNextSibling
= ChildrenList();
1544 SetChildrenList(next
);
1550 void nsRuleNode::SetUsedDirectly()
1552 mDependentBits
|= NS_RULE_NODE_USED_DIRECTLY
;
1554 // Maintain the invariant that any rule node that is used directly has
1555 // all structs that live in the rule tree cached (which
1556 // nsRuleNode::GetStyleData depends on for speed).
1557 if (mDependentBits
& NS_STYLE_INHERIT_MASK
) {
1558 for (nsStyleStructID sid
= nsStyleStructID(0); sid
< nsStyleStructID_Length
;
1559 sid
= nsStyleStructID(sid
+ 1)) {
1560 uint32_t bit
= nsCachedStyleData::GetBitForSID(sid
);
1561 if (mDependentBits
& bit
) {
1562 nsRuleNode
*source
= mParent
;
1563 while ((source
->mDependentBits
& bit
) && !source
->IsUsedDirectly()) {
1564 source
= source
->mParent
;
1566 void *data
= source
->mStyleData
.GetStyleData(sid
);
1567 NS_ASSERTION(data
, "unexpected null struct");
1568 mStyleData
.SetStyleData(sid
, mPresContext
, data
);
1575 nsRuleNode::ConvertChildrenToHash(int32_t aNumKids
)
1577 NS_ASSERTION(!ChildrenAreHashed() && HaveChildren(),
1578 "must have a non-empty list of children");
1579 PLDHashTable
*hash
= PL_NewDHashTable(&ChildrenHashOps
, nullptr,
1580 sizeof(ChildrenHashEntry
),
1584 for (nsRuleNode
* curr
= ChildrenList(); curr
; curr
= curr
->mNextSibling
) {
1585 // This will never fail because of the initial size we gave the table.
1586 ChildrenHashEntry
*entry
= static_cast<ChildrenHashEntry
*>(
1587 PL_DHashTableOperate(hash
, curr
->mRule
, PL_DHASH_ADD
));
1588 NS_ASSERTION(!entry
->mRuleNode
, "duplicate entries in list");
1589 entry
->mRuleNode
= curr
;
1591 SetChildrenHash(hash
);
1595 nsRuleNode::PropagateNoneBit(uint32_t aBit
, nsRuleNode
* aHighestNode
)
1597 nsRuleNode
* curr
= this;
1599 NS_ASSERTION(!(curr
->mNoneBits
& aBit
), "propagating too far");
1600 curr
->mNoneBits
|= aBit
;
1601 if (curr
== aHighestNode
)
1603 curr
= curr
->mParent
;
1608 nsRuleNode::PropagateDependentBit(nsStyleStructID aSID
, nsRuleNode
* aHighestNode
,
1611 NS_ASSERTION(aStruct
, "expected struct");
1613 uint32_t bit
= nsCachedStyleData::GetBitForSID(aSID
);
1614 for (nsRuleNode
* curr
= this; curr
!= aHighestNode
; curr
= curr
->mParent
) {
1615 if (curr
->mDependentBits
& bit
) {
1617 while (curr
!= aHighestNode
) {
1618 NS_ASSERTION(curr
->mDependentBits
& bit
, "bit not set");
1619 curr
= curr
->mParent
;
1625 curr
->mDependentBits
|= bit
;
1627 if (curr
->IsUsedDirectly()) {
1628 curr
->mStyleData
.SetStyleData(aSID
, mPresContext
, aStruct
);
1634 * The following "Check" functions are used for determining what type of
1635 * sharing can be used for the data on this rule node. MORE HERE...
1639 * a callback function that that can revise the result of
1640 * CheckSpecifiedProperties before finishing; aResult is the current
1641 * result, and it returns the revised one.
1643 typedef nsRuleNode::RuleDetail
1644 (* CheckCallbackFn
)(const nsRuleData
* aRuleData
,
1645 nsRuleNode::RuleDetail aResult
);
1648 * @param aValue the value being examined
1649 * @param aSpecifiedCount to be incremented by one if the value is specified
1650 * @param aInheritedCount to be incremented by one if the value is set to inherit
1651 * @param aUnsetCount to be incremented by one if the value is set to unset
1654 ExamineCSSValue(const nsCSSValue
& aValue
,
1655 uint32_t& aSpecifiedCount
,
1656 uint32_t& aInheritedCount
,
1657 uint32_t& aUnsetCount
)
1659 if (aValue
.GetUnit() != eCSSUnit_Null
) {
1661 if (aValue
.GetUnit() == eCSSUnit_Inherit
) {
1663 } else if (aValue
.GetUnit() == eCSSUnit_Unset
) {
1669 static nsRuleNode::RuleDetail
1670 CheckFontCallback(const nsRuleData
* aRuleData
,
1671 nsRuleNode::RuleDetail aResult
)
1673 // em, ex, percent, 'larger', and 'smaller' values on font-size depend
1674 // on the parent context's font-size
1675 // Likewise, 'lighter' and 'bolder' values of 'font-weight', and 'wider'
1676 // and 'narrower' values of 'font-stretch' depend on the parent.
1677 const nsCSSValue
& size
= *aRuleData
->ValueForFontSize();
1678 const nsCSSValue
& weight
= *aRuleData
->ValueForFontWeight();
1679 if ((size
.IsRelativeLengthUnit() && size
.GetUnit() != eCSSUnit_RootEM
) ||
1680 size
.GetUnit() == eCSSUnit_Percent
||
1681 (size
.GetUnit() == eCSSUnit_Enumerated
&&
1682 (size
.GetIntValue() == NS_STYLE_FONT_SIZE_SMALLER
||
1683 size
.GetIntValue() == NS_STYLE_FONT_SIZE_LARGER
)) ||
1684 aRuleData
->ValueForScriptLevel()->GetUnit() == eCSSUnit_Integer
||
1685 (weight
.GetUnit() == eCSSUnit_Enumerated
&&
1686 (weight
.GetIntValue() == NS_STYLE_FONT_WEIGHT_BOLDER
||
1687 weight
.GetIntValue() == NS_STYLE_FONT_WEIGHT_LIGHTER
))) {
1688 NS_ASSERTION(aResult
== nsRuleNode::eRulePartialReset
||
1689 aResult
== nsRuleNode::eRuleFullReset
||
1690 aResult
== nsRuleNode::eRulePartialMixed
||
1691 aResult
== nsRuleNode::eRuleFullMixed
,
1692 "we know we already have a reset-counted property");
1693 // Promote reset to mixed since we have something that depends on
1694 // the parent. But never promote to inherited since that could
1695 // cause inheritance of the exact value.
1696 if (aResult
== nsRuleNode::eRulePartialReset
)
1697 aResult
= nsRuleNode::eRulePartialMixed
;
1698 else if (aResult
== nsRuleNode::eRuleFullReset
)
1699 aResult
= nsRuleNode::eRuleFullMixed
;
1705 static nsRuleNode::RuleDetail
1706 CheckColorCallback(const nsRuleData
* aRuleData
,
1707 nsRuleNode::RuleDetail aResult
)
1709 // currentColor values for color require inheritance
1710 const nsCSSValue
* colorValue
= aRuleData
->ValueForColor();
1711 if (colorValue
->GetUnit() == eCSSUnit_EnumColor
&&
1712 colorValue
->GetIntValue() == NS_COLOR_CURRENTCOLOR
) {
1713 NS_ASSERTION(aResult
== nsRuleNode::eRuleFullReset
,
1714 "we should already be counted as full-reset");
1715 aResult
= nsRuleNode::eRuleFullInherited
;
1721 static nsRuleNode::RuleDetail
1722 CheckTextCallback(const nsRuleData
* aRuleData
,
1723 nsRuleNode::RuleDetail aResult
)
1725 const nsCSSValue
* textAlignValue
= aRuleData
->ValueForTextAlign();
1726 if (textAlignValue
->GetUnit() == eCSSUnit_Enumerated
&&
1727 textAlignValue
->GetIntValue() ==
1728 NS_STYLE_TEXT_ALIGN_MOZ_CENTER_OR_INHERIT
) {
1729 // Promote reset to mixed since we have something that depends on
1731 if (aResult
== nsRuleNode::eRulePartialReset
)
1732 aResult
= nsRuleNode::eRulePartialMixed
;
1733 else if (aResult
== nsRuleNode::eRuleFullReset
)
1734 aResult
= nsRuleNode::eRuleFullMixed
;
1740 static nsRuleNode::RuleDetail
1741 CheckVariablesCallback(const nsRuleData
* aRuleData
,
1742 nsRuleNode::RuleDetail aResult
)
1744 // We don't actually have any properties on nsStyleVariables, so we do
1745 // all of the RuleDetail calculation in here.
1746 if (aRuleData
->mVariables
) {
1747 return nsRuleNode::eRulePartialMixed
;
1749 return nsRuleNode::eRuleNone
;
1752 #define FLAG_DATA_FOR_PROPERTY(name_, id_, method_, flags_, pref_, \
1753 parsevariant_, kwtable_, stylestructoffset_, \
1757 // The order here must match the enums in *CheckCounter in nsCSSProps.cpp.
1759 static const uint32_t gFontFlags
[] = {
1760 #define CSS_PROP_FONT FLAG_DATA_FOR_PROPERTY
1761 #include "nsCSSPropList.h"
1762 #undef CSS_PROP_FONT
1765 static const uint32_t gDisplayFlags
[] = {
1766 #define CSS_PROP_DISPLAY FLAG_DATA_FOR_PROPERTY
1767 #include "nsCSSPropList.h"
1768 #undef CSS_PROP_DISPLAY
1771 static const uint32_t gVisibilityFlags
[] = {
1772 #define CSS_PROP_VISIBILITY FLAG_DATA_FOR_PROPERTY
1773 #include "nsCSSPropList.h"
1774 #undef CSS_PROP_VISIBILITY
1777 static const uint32_t gMarginFlags
[] = {
1778 #define CSS_PROP_MARGIN FLAG_DATA_FOR_PROPERTY
1779 #include "nsCSSPropList.h"
1780 #undef CSS_PROP_MARGIN
1783 static const uint32_t gBorderFlags
[] = {
1784 #define CSS_PROP_BORDER FLAG_DATA_FOR_PROPERTY
1785 #include "nsCSSPropList.h"
1786 #undef CSS_PROP_BORDER
1789 static const uint32_t gPaddingFlags
[] = {
1790 #define CSS_PROP_PADDING FLAG_DATA_FOR_PROPERTY
1791 #include "nsCSSPropList.h"
1792 #undef CSS_PROP_PADDING
1795 static const uint32_t gOutlineFlags
[] = {
1796 #define CSS_PROP_OUTLINE FLAG_DATA_FOR_PROPERTY
1797 #include "nsCSSPropList.h"
1798 #undef CSS_PROP_OUTLINE
1801 static const uint32_t gListFlags
[] = {
1802 #define CSS_PROP_LIST FLAG_DATA_FOR_PROPERTY
1803 #include "nsCSSPropList.h"
1804 #undef CSS_PROP_LIST
1807 static const uint32_t gColorFlags
[] = {
1808 #define CSS_PROP_COLOR FLAG_DATA_FOR_PROPERTY
1809 #include "nsCSSPropList.h"
1810 #undef CSS_PROP_COLOR
1813 static const uint32_t gBackgroundFlags
[] = {
1814 #define CSS_PROP_BACKGROUND FLAG_DATA_FOR_PROPERTY
1815 #include "nsCSSPropList.h"
1816 #undef CSS_PROP_BACKGROUND
1819 static const uint32_t gPositionFlags
[] = {
1820 #define CSS_PROP_POSITION FLAG_DATA_FOR_PROPERTY
1821 #include "nsCSSPropList.h"
1822 #undef CSS_PROP_POSITION
1825 static const uint32_t gTableFlags
[] = {
1826 #define CSS_PROP_TABLE FLAG_DATA_FOR_PROPERTY
1827 #include "nsCSSPropList.h"
1828 #undef CSS_PROP_TABLE
1831 static const uint32_t gTableBorderFlags
[] = {
1832 #define CSS_PROP_TABLEBORDER FLAG_DATA_FOR_PROPERTY
1833 #include "nsCSSPropList.h"
1834 #undef CSS_PROP_TABLEBORDER
1837 static const uint32_t gContentFlags
[] = {
1838 #define CSS_PROP_CONTENT FLAG_DATA_FOR_PROPERTY
1839 #include "nsCSSPropList.h"
1840 #undef CSS_PROP_CONTENT
1843 static const uint32_t gQuotesFlags
[] = {
1844 #define CSS_PROP_QUOTES FLAG_DATA_FOR_PROPERTY
1845 #include "nsCSSPropList.h"
1846 #undef CSS_PROP_QUOTES
1849 static const uint32_t gTextFlags
[] = {
1850 #define CSS_PROP_TEXT FLAG_DATA_FOR_PROPERTY
1851 #include "nsCSSPropList.h"
1852 #undef CSS_PROP_TEXT
1855 static const uint32_t gTextResetFlags
[] = {
1856 #define CSS_PROP_TEXTRESET FLAG_DATA_FOR_PROPERTY
1857 #include "nsCSSPropList.h"
1858 #undef CSS_PROP_TEXTRESET
1861 static const uint32_t gUserInterfaceFlags
[] = {
1862 #define CSS_PROP_USERINTERFACE FLAG_DATA_FOR_PROPERTY
1863 #include "nsCSSPropList.h"
1864 #undef CSS_PROP_USERINTERFACE
1867 static const uint32_t gUIResetFlags
[] = {
1868 #define CSS_PROP_UIRESET FLAG_DATA_FOR_PROPERTY
1869 #include "nsCSSPropList.h"
1870 #undef CSS_PROP_UIRESET
1873 static const uint32_t gXULFlags
[] = {
1874 #define CSS_PROP_XUL FLAG_DATA_FOR_PROPERTY
1875 #include "nsCSSPropList.h"
1879 static const uint32_t gSVGFlags
[] = {
1880 #define CSS_PROP_SVG FLAG_DATA_FOR_PROPERTY
1881 #include "nsCSSPropList.h"
1885 static const uint32_t gSVGResetFlags
[] = {
1886 #define CSS_PROP_SVGRESET FLAG_DATA_FOR_PROPERTY
1887 #include "nsCSSPropList.h"
1888 #undef CSS_PROP_SVGRESET
1891 static const uint32_t gColumnFlags
[] = {
1892 #define CSS_PROP_COLUMN FLAG_DATA_FOR_PROPERTY
1893 #include "nsCSSPropList.h"
1894 #undef CSS_PROP_COLUMN
1897 // There are no properties in nsStyleVariables, but we can't have a
1898 // zero length array.
1899 static const uint32_t gVariablesFlags
[] = {
1901 #define CSS_PROP_VARIABLES FLAG_DATA_FOR_PROPERTY
1902 #include "nsCSSPropList.h"
1903 #undef CSS_PROP_VARIABLES
1905 static_assert(sizeof(gVariablesFlags
) == sizeof(uint32_t),
1906 "if nsStyleVariables has properties now you can remove the dummy "
1907 "gVariablesFlags entry");
1909 #undef FLAG_DATA_FOR_PROPERTY
1911 static const uint32_t* gFlagsByStruct
[] = {
1913 #define STYLE_STRUCT(name, checkdata_cb) \
1915 #include "nsStyleStructList.h"
1920 static const CheckCallbackFn gCheckCallbacks
[] = {
1922 #define STYLE_STRUCT(name, checkdata_cb) \
1924 #include "nsStyleStructList.h"
1931 AreAllMathMLPropertiesUndefined(const nsRuleData
* aRuleData
)
1934 aRuleData
->ValueForScriptLevel()->GetUnit() == eCSSUnit_Null
&&
1935 aRuleData
->ValueForScriptSizeMultiplier()->GetUnit() == eCSSUnit_Null
&&
1936 aRuleData
->ValueForScriptMinSize()->GetUnit() == eCSSUnit_Null
&&
1937 aRuleData
->ValueForMathVariant()->GetUnit() == eCSSUnit_Null
&&
1938 aRuleData
->ValueForMathDisplay()->GetUnit() == eCSSUnit_Null
;
1942 inline nsRuleNode::RuleDetail
1943 nsRuleNode::CheckSpecifiedProperties(const nsStyleStructID aSID
,
1944 const nsRuleData
* aRuleData
)
1946 // Build a count of the:
1947 uint32_t total
= 0, // total number of props in the struct
1948 specified
= 0, // number that were specified for this node
1949 inherited
= 0, // number that were 'inherit' (and not
1950 // eCSSUnit_Inherit) for this node
1951 unset
= 0; // number that were 'unset'
1953 // See comment in nsRuleData.h above mValueOffsets.
1954 NS_ABORT_IF_FALSE(aRuleData
->mValueOffsets
[aSID
] == 0,
1955 "we assume the value offset is zero instead of adding it");
1956 for (nsCSSValue
*values
= aRuleData
->mValueStorage
,
1957 *values_end
= values
+ nsCSSProps::PropertyCountInStruct(aSID
);
1958 values
!= values_end
; ++values
) {
1960 ExamineCSSValue(*values
, specified
, inherited
, unset
);
1963 if (!nsCachedStyleData::IsReset(aSID
)) {
1964 // For inherited properties, 'unset' means the same as 'inherit'.
1970 printf("CheckSpecifiedProperties: SID=%d total=%d spec=%d inh=%d.\n",
1971 aSID
, total
, specified
, inherited
);
1974 NS_ASSERTION(aSID
!= eStyleStruct_Font
||
1975 mPresContext
->Document()->GetMathMLEnabled() ||
1976 AreAllMathMLPropertiesUndefined(aRuleData
),
1977 "MathML style property was defined even though MathML is disabled");
1980 * Return the most specific information we can: prefer None or Full
1981 * over Partial, and Reset or Inherited over Mixed, since we can
1982 * optimize based on the edge cases and not the in-between cases.
1984 nsRuleNode::RuleDetail result
;
1985 if (inherited
== total
)
1986 result
= eRuleFullInherited
;
1987 else if (specified
== total
1988 // MathML defines 5 properties in Font that will never be set when
1989 // MathML is not in use. Therefore if all but five
1990 // properties have been set, and MathML is not enabled, we can treat
1991 // this as fully specified. Code in nsMathMLElementFactory will
1992 // rebuild the rule tree and style data when MathML is first enabled
1993 // (see nsMathMLElement::BindToTree).
1994 || (aSID
== eStyleStruct_Font
&& specified
+ 5 == total
&&
1995 !mPresContext
->Document()->GetMathMLEnabled())
1998 result
= eRuleFullReset
;
2000 result
= eRuleFullMixed
;
2001 } else if (specified
== 0)
2003 else if (specified
== inherited
)
2004 result
= eRulePartialInherited
;
2005 else if (inherited
== 0)
2006 result
= eRulePartialReset
;
2008 result
= eRulePartialMixed
;
2010 CheckCallbackFn cb
= gCheckCallbacks
[aSID
];
2012 result
= (*cb
)(aRuleData
, result
);
2018 // If we need to restrict which properties apply to the style context,
2019 // return the bit to check in nsCSSProp's flags table. Otherwise,
2022 GetPseudoRestriction(nsStyleContext
*aContext
)
2024 // This needs to match nsStyleSet::WalkRestrictionRule.
2025 uint32_t pseudoRestriction
= 0;
2026 nsIAtom
*pseudoType
= aContext
->GetPseudo();
2028 if (pseudoType
== nsCSSPseudoElements::firstLetter
) {
2029 pseudoRestriction
= CSS_PROPERTY_APPLIES_TO_FIRST_LETTER
;
2030 } else if (pseudoType
== nsCSSPseudoElements::firstLine
) {
2031 pseudoRestriction
= CSS_PROPERTY_APPLIES_TO_FIRST_LINE
;
2032 } else if (pseudoType
== nsCSSPseudoElements::mozPlaceholder
) {
2033 pseudoRestriction
= CSS_PROPERTY_APPLIES_TO_PLACEHOLDER
;
2036 return pseudoRestriction
;
2040 UnsetPropertiesWithoutFlags(const nsStyleStructID aSID
,
2041 nsRuleData
* aRuleData
,
2044 NS_ASSERTION(aFlags
!= 0, "aFlags must be nonzero");
2046 const uint32_t *flagData
= gFlagsByStruct
[aSID
];
2048 // See comment in nsRuleData.h above mValueOffsets.
2049 NS_ABORT_IF_FALSE(aRuleData
->mValueOffsets
[aSID
] == 0,
2050 "we assume the value offset is zero instead of adding it");
2051 nsCSSValue
*values
= aRuleData
->mValueStorage
;
2053 for (size_t i
= 0, i_end
= nsCSSProps::PropertyCountInStruct(aSID
);
2055 if ((flagData
[i
] & aFlags
) != aFlags
)
2061 * We allocate arrays of CSS values with alloca. (These arrays are a
2062 * fixed size per style struct, but we don't want to waste the
2063 * allocation and construction/destruction costs of the big structs when
2064 * we're handling much smaller ones.) Since the lifetime of an alloca
2065 * allocation is the life of the calling function, the caller must call
2066 * alloca. However, to ensure that constructors and destructors are
2067 * balanced, we do the constructor and destructor calling from this RAII
2068 * class, AutoCSSValueArray.
2070 struct AutoCSSValueArray
{
2072 * aStorage must be the result of alloca(aCount * sizeof(nsCSSValue))
2074 AutoCSSValueArray(void* aStorage
, size_t aCount
) {
2075 NS_ABORT_IF_FALSE(size_t(aStorage
) % NS_ALIGNMENT_OF(nsCSSValue
) == 0,
2076 "bad alignment from alloca");
2078 // Don't use placement new[], since it might store extra data
2079 // for the count (on Windows!).
2080 mArray
= static_cast<nsCSSValue
*>(aStorage
);
2081 for (size_t i
= 0; i
< mCount
; ++i
) {
2082 new (mArray
+ i
) nsCSSValue();
2086 ~AutoCSSValueArray() {
2087 for (size_t i
= 0; i
< mCount
; ++i
) {
2088 mArray
[i
].~nsCSSValue();
2092 nsCSSValue
* get() { return mArray
; }
2100 nsRuleNode::ResolveVariableReferences(const nsStyleStructID aSID
,
2101 nsRuleData
* aRuleData
,
2102 nsStyleContext
* aContext
)
2104 MOZ_ASSERT(aSID
!= eStyleStruct_Variables
);
2105 MOZ_ASSERT(aRuleData
->mSIDs
& nsCachedStyleData::GetBitForSID(aSID
));
2106 MOZ_ASSERT(aRuleData
->mValueOffsets
[aSID
] == 0);
2109 bool anyTokenStreams
= false;
2111 // Look at each property in the nsRuleData for the given style struct.
2112 size_t nprops
= nsCSSProps::PropertyCountInStruct(aSID
);
2113 for (nsCSSValue
* value
= aRuleData
->mValueStorage
,
2114 *values_end
= aRuleData
->mValueStorage
+ nprops
;
2115 value
!= values_end
; value
++) {
2116 if (value
->GetUnit() != eCSSUnit_TokenStream
) {
2120 const CSSVariableValues
* variables
=
2121 &aContext
->StyleVariables()->mVariables
;
2122 nsCSSValueTokenStream
* tokenStream
= value
->GetTokenStreamValue();
2124 // Note that ParsePropertyWithVariableReferences relies on the fact
2125 // that the nsCSSValue in aRuleData for the property we are re-parsing
2126 // is still the token stream value. When
2127 // ParsePropertyWithVariableReferences calls
2128 // nsCSSExpandedDataBlock::MapRuleInfoInto, that function will add
2129 // the ImageValue that is created into the token stream object's
2130 // mImageValues table; see the comment above mImageValues for why.
2132 // XXX Should pass in sheet here (see bug 952338).
2133 parser
.ParsePropertyWithVariableReferences(
2134 tokenStream
->mPropertyID
, tokenStream
->mShorthandPropertyID
,
2135 tokenStream
->mTokenStream
, variables
, aRuleData
,
2136 tokenStream
->mSheetURI
, tokenStream
->mBaseURI
,
2137 tokenStream
->mSheetPrincipal
, nullptr,
2138 tokenStream
->mLineNumber
, tokenStream
->mLineOffset
);
2139 aRuleData
->mCanStoreInRuleTree
= false;
2140 anyTokenStreams
= true;
2143 return anyTokenStreams
;
2147 nsRuleNode::WalkRuleTree(const nsStyleStructID aSID
,
2148 nsStyleContext
* aContext
)
2150 // use placement new[] on the result of alloca() to allocate a
2151 // variable-sized stack array, including execution of constructors,
2152 // and use an RAII class to run the destructors too.
2153 size_t nprops
= nsCSSProps::PropertyCountInStruct(aSID
);
2154 void* dataStorage
= alloca(nprops
* sizeof(nsCSSValue
));
2155 AutoCSSValueArray
dataArray(dataStorage
, nprops
);
2157 nsRuleData
ruleData(nsCachedStyleData::GetBitForSID(aSID
),
2158 dataArray
.get(), mPresContext
, aContext
);
2159 ruleData
.mValueOffsets
[aSID
] = 0;
2161 // We start at the most specific rule in the tree.
2162 void* startStruct
= nullptr;
2164 nsRuleNode
* ruleNode
= this;
2165 nsRuleNode
* highestNode
= nullptr; // The highest node in the rule tree
2166 // that has the same properties
2167 // specified for struct |aSID| as
2169 nsRuleNode
* rootNode
= this; // After the loop below, this will be the
2170 // highest node that we've walked without
2171 // finding cached data on the rule tree.
2172 // If we don't find any cached data, it
2173 // will be the root. (XXX misnamed)
2174 RuleDetail detail
= eRuleNone
;
2175 uint32_t bit
= nsCachedStyleData::GetBitForSID(aSID
);
2178 // See if this rule node has cached the fact that the remaining
2179 // nodes along this path specify no data whatsoever.
2180 if (ruleNode
->mNoneBits
& bit
)
2183 // If the dependent bit is set on a rule node for this struct, that
2184 // means its rule won't have any information to add, so skip it.
2185 // NOTE: If we exit the loop because of the !IsUsedDirectly() check,
2186 // then we're guaranteed to break immediately afterwards due to a
2187 // non-null startStruct.
2188 while ((ruleNode
->mDependentBits
& bit
) && !ruleNode
->IsUsedDirectly()) {
2189 NS_ASSERTION(ruleNode
->mStyleData
.GetStyleData(aSID
) == nullptr,
2190 "dependent bit with cached data makes no sense");
2191 // Climb up to the next rule in the tree (a less specific rule).
2192 rootNode
= ruleNode
;
2193 ruleNode
= ruleNode
->mParent
;
2194 NS_ASSERTION(!(ruleNode
->mNoneBits
& bit
), "can't have both bits set");
2197 // Check for cached data after the inner loop above -- otherwise
2199 startStruct
= ruleNode
->mStyleData
.GetStyleData(aSID
);
2201 break; // We found a rule with fully specified data. We don't
2202 // need to go up the tree any further, since the remainder
2203 // of this branch has already been computed.
2205 // Ask the rule to fill in the properties that it specifies.
2206 nsIStyleRule
*rule
= ruleNode
->mRule
;
2208 ruleData
.mLevel
= ruleNode
->GetLevel();
2209 ruleData
.mIsImportantRule
= ruleNode
->IsImportantRule();
2210 rule
->MapRuleInfoInto(&ruleData
);
2213 // Now we check to see how many properties have been specified by
2214 // the rules we've examined so far.
2215 RuleDetail oldDetail
= detail
;
2216 detail
= CheckSpecifiedProperties(aSID
, &ruleData
);
2218 if (oldDetail
== eRuleNone
&& detail
!= eRuleNone
)
2219 highestNode
= ruleNode
;
2221 if (detail
== eRuleFullReset
||
2222 detail
== eRuleFullMixed
||
2223 detail
== eRuleFullInherited
)
2224 break; // We don't need to examine any more rules. All properties
2225 // have been fully specified.
2227 // Climb up to the next rule in the tree (a less specific rule).
2228 rootNode
= ruleNode
;
2229 ruleNode
= ruleNode
->mParent
;
2232 bool recomputeDetail
= false;
2234 // If we are computing a style struct other than nsStyleVariables, and
2235 // ruleData has any properties with variable references (nsCSSValues of
2236 // type eCSSUnit_TokenStream), then we need to resolve these.
2237 if (aSID
!= eStyleStruct_Variables
) {
2238 // A property's value might have became 'inherit' after resolving
2239 // variable references. (This happens when an inherited property
2240 // fails to parse its resolved value.) We need to recompute
2241 // |detail| in case this happened.
2242 recomputeDetail
= ResolveVariableReferences(aSID
, &ruleData
, aContext
);
2245 // If needed, unset the properties that don't have a flag that allows
2246 // them to be set for this style context. (For example, only some
2247 // properties apply to :first-line and :first-letter.)
2248 uint32_t pseudoRestriction
= GetPseudoRestriction(aContext
);
2249 if (pseudoRestriction
) {
2250 UnsetPropertiesWithoutFlags(aSID
, &ruleData
, pseudoRestriction
);
2252 // We need to recompute |detail| based on the restrictions we just applied.
2253 // We can adjust |detail| arbitrarily because of the restriction
2254 // rule added in nsStyleSet::WalkRestrictionRule.
2255 recomputeDetail
= true;
2258 if (recomputeDetail
) {
2259 detail
= CheckSpecifiedProperties(aSID
, &ruleData
);
2262 NS_ASSERTION(!startStruct
|| (detail
!= eRuleFullReset
&&
2263 detail
!= eRuleFullMixed
&&
2264 detail
!= eRuleFullInherited
),
2265 "can't have start struct and be fully specified");
2267 bool isReset
= nsCachedStyleData::IsReset(aSID
);
2269 highestNode
= rootNode
;
2271 if (!ruleData
.mCanStoreInRuleTree
)
2272 detail
= eRulePartialMixed
; // Treat as though some data is specified to avoid
2273 // the optimizations and force data computation.
2275 if (detail
== eRuleNone
&& startStruct
) {
2276 // We specified absolutely no rule information, but a parent rule in the tree
2277 // specified all the rule information. We set a bit along the branch from our
2278 // node in the tree to the node that specified the data that tells nodes on that
2279 // branch that they never need to examine their rules for this particular struct type
2281 PropagateDependentBit(aSID
, ruleNode
, startStruct
);
2284 if ((!startStruct
&& !isReset
&&
2285 (detail
== eRuleNone
|| detail
== eRulePartialInherited
)) ||
2286 detail
== eRuleFullInherited
) {
2287 // We specified no non-inherited information and neither did any of
2288 // our parent rules.
2290 // We set a bit along the branch from the highest node (ruleNode)
2291 // down to our node (this) indicating that no non-inherited data was
2292 // specified. This bit is guaranteed to be set already on the path
2293 // from the highest node to the root node in the case where
2294 // (detail == eRuleNone), which is the most common case here.
2295 // We must check |!isReset| because the Compute*Data functions for
2296 // reset structs wouldn't handle none bits correctly.
2297 if (highestNode
!= this && !isReset
)
2298 PropagateNoneBit(bit
, highestNode
);
2300 // All information must necessarily be inherited from our parent style context.
2301 // In the absence of any computed data in the rule tree and with
2302 // no rules specified that didn't have values of 'inherit', we should check our parent.
2303 nsStyleContext
* parentContext
= aContext
->GetParent();
2305 /* Reset structs don't inherit from first-line. */
2306 /* See similar code in COMPUTE_START_RESET */
2307 while (parentContext
&&
2308 parentContext
->GetPseudo() == nsCSSPseudoElements::firstLine
) {
2309 parentContext
= parentContext
->GetParent();
2312 if (parentContext
) {
2313 // We have a parent, and so we should just inherit from the parent.
2314 // Set the inherit bits on our context. These bits tell the style context that
2315 // it never has to go back to the rule tree for data. Instead the style context tree
2316 // should be walked to find the data.
2317 const void* parentStruct
= parentContext
->StyleData(aSID
);
2318 aContext
->AddStyleBit(bit
); // makes const_cast OK.
2319 aContext
->SetStyle(aSID
, const_cast<void*>(parentStruct
));
2320 return parentStruct
;
2323 // We are the root. In the case of fonts, the default values just
2324 // come from the pres context.
2325 return SetDefaultOnRoot(aSID
, aContext
);
2328 // We need to compute the data from the information that the rules specified.
2330 #define STYLE_STRUCT_TEST aSID
2331 #define STYLE_STRUCT(name, checkdata_cb) \
2332 res = Compute##name##Data(startStruct, &ruleData, aContext, \
2333 highestNode, detail, ruleData.mCanStoreInRuleTree);
2334 #include "nsStyleStructList.h"
2336 #undef STYLE_STRUCT_TEST
2338 // Now return the result.
2343 nsRuleNode::SetDefaultOnRoot(const nsStyleStructID aSID
, nsStyleContext
* aContext
)
2346 case eStyleStruct_Font
:
2348 nsStyleFont
* fontData
= new (mPresContext
) nsStyleFont(mPresContext
);
2349 nscoord minimumFontSize
= mPresContext
->MinFontSize(fontData
->mLanguage
);
2351 if (minimumFontSize
> 0 && !mPresContext
->IsChrome()) {
2352 fontData
->mFont
.size
= std::max(fontData
->mSize
, minimumFontSize
);
2355 fontData
->mFont
.size
= fontData
->mSize
;
2357 aContext
->SetStyle(eStyleStruct_Font
, fontData
);
2360 case eStyleStruct_Display
:
2362 nsStyleDisplay
* disp
= new (mPresContext
) nsStyleDisplay();
2363 aContext
->SetStyle(eStyleStruct_Display
, disp
);
2366 case eStyleStruct_Visibility
:
2368 nsStyleVisibility
* vis
= new (mPresContext
) nsStyleVisibility(mPresContext
);
2369 aContext
->SetStyle(eStyleStruct_Visibility
, vis
);
2372 case eStyleStruct_Text
:
2374 nsStyleText
* text
= new (mPresContext
) nsStyleText();
2375 aContext
->SetStyle(eStyleStruct_Text
, text
);
2378 case eStyleStruct_TextReset
:
2380 nsStyleTextReset
* text
= new (mPresContext
) nsStyleTextReset();
2381 aContext
->SetStyle(eStyleStruct_TextReset
, text
);
2384 case eStyleStruct_Color
:
2386 nsStyleColor
* color
= new (mPresContext
) nsStyleColor(mPresContext
);
2387 aContext
->SetStyle(eStyleStruct_Color
, color
);
2390 case eStyleStruct_Background
:
2392 nsStyleBackground
* bg
= new (mPresContext
) nsStyleBackground();
2393 aContext
->SetStyle(eStyleStruct_Background
, bg
);
2396 case eStyleStruct_Margin
:
2398 nsStyleMargin
* margin
= new (mPresContext
) nsStyleMargin();
2399 aContext
->SetStyle(eStyleStruct_Margin
, margin
);
2402 case eStyleStruct_Border
:
2404 nsStyleBorder
* border
= new (mPresContext
) nsStyleBorder(mPresContext
);
2405 aContext
->SetStyle(eStyleStruct_Border
, border
);
2408 case eStyleStruct_Padding
:
2410 nsStylePadding
* padding
= new (mPresContext
) nsStylePadding();
2411 aContext
->SetStyle(eStyleStruct_Padding
, padding
);
2414 case eStyleStruct_Outline
:
2416 nsStyleOutline
* outline
= new (mPresContext
) nsStyleOutline(mPresContext
);
2417 aContext
->SetStyle(eStyleStruct_Outline
, outline
);
2420 case eStyleStruct_List
:
2422 nsStyleList
* list
= new (mPresContext
) nsStyleList(mPresContext
);
2423 aContext
->SetStyle(eStyleStruct_List
, list
);
2426 case eStyleStruct_Position
:
2428 nsStylePosition
* pos
= new (mPresContext
) nsStylePosition();
2429 aContext
->SetStyle(eStyleStruct_Position
, pos
);
2432 case eStyleStruct_Table
:
2434 nsStyleTable
* table
= new (mPresContext
) nsStyleTable();
2435 aContext
->SetStyle(eStyleStruct_Table
, table
);
2438 case eStyleStruct_TableBorder
:
2440 nsStyleTableBorder
* table
= new (mPresContext
) nsStyleTableBorder(mPresContext
);
2441 aContext
->SetStyle(eStyleStruct_TableBorder
, table
);
2444 case eStyleStruct_Content
:
2446 nsStyleContent
* content
= new (mPresContext
) nsStyleContent();
2447 aContext
->SetStyle(eStyleStruct_Content
, content
);
2450 case eStyleStruct_Quotes
:
2452 nsStyleQuotes
* quotes
= new (mPresContext
) nsStyleQuotes();
2453 aContext
->SetStyle(eStyleStruct_Quotes
, quotes
);
2456 case eStyleStruct_UserInterface
:
2458 nsStyleUserInterface
* ui
= new (mPresContext
) nsStyleUserInterface();
2459 aContext
->SetStyle(eStyleStruct_UserInterface
, ui
);
2462 case eStyleStruct_UIReset
:
2464 nsStyleUIReset
* ui
= new (mPresContext
) nsStyleUIReset();
2465 aContext
->SetStyle(eStyleStruct_UIReset
, ui
);
2468 case eStyleStruct_XUL
:
2470 nsStyleXUL
* xul
= new (mPresContext
) nsStyleXUL();
2471 aContext
->SetStyle(eStyleStruct_XUL
, xul
);
2474 case eStyleStruct_Column
:
2476 nsStyleColumn
* column
= new (mPresContext
) nsStyleColumn(mPresContext
);
2477 aContext
->SetStyle(eStyleStruct_Column
, column
);
2480 case eStyleStruct_SVG
:
2482 nsStyleSVG
* svg
= new (mPresContext
) nsStyleSVG();
2483 aContext
->SetStyle(eStyleStruct_SVG
, svg
);
2486 case eStyleStruct_SVGReset
:
2488 nsStyleSVGReset
* svgReset
= new (mPresContext
) nsStyleSVGReset();
2489 aContext
->SetStyle(eStyleStruct_SVGReset
, svgReset
);
2492 case eStyleStruct_Variables
:
2494 nsStyleVariables
* vars
= new (mPresContext
) nsStyleVariables();
2495 aContext
->SetStyle(eStyleStruct_Variables
, vars
);
2500 * unhandled case: nsStyleStructID_Length.
2501 * last item of nsStyleStructID, to know its length.
2503 NS_ABORT_IF_FALSE(false, "unexpected SID");
2510 * This function handles cascading of *-left or *-right box properties
2511 * against *-start (which is L for LTR and R for RTL) or *-end (which is
2512 * R for LTR and L for RTL).
2514 * Cascading these properties correctly is hard because we need to
2515 * cascade two properties as one, but which two properties depends on a
2516 * third property ('direction'). We solve this by treating each of
2517 * these properties (say, 'margin-start') as a shorthand that sets a
2518 * property containing the value of the property specified
2519 * ('margin-start-value') and sets a pair of properties
2520 * ('margin-left-ltr-source' and 'margin-right-rtl-source') saying which
2521 * of the properties we use. Thus, when we want to compute the value of
2522 * 'margin-left' when 'direction' is 'ltr', we look at the value of
2523 * 'margin-left-ltr-source', which tells us whether to use the highest
2524 * 'margin-left' in the cascade or the highest 'margin-start'.
2526 * Finally, since we can compute the normal (*-left and *-right)
2527 * properties in a loop, this function works by modifying the data we
2528 * will use in that loop (which the caller must copy from the const
2532 nsRuleNode::AdjustLogicalBoxProp(nsStyleContext
* aContext
,
2533 const nsCSSValue
& aLTRSource
,
2534 const nsCSSValue
& aRTLSource
,
2535 const nsCSSValue
& aLTRLogicalValue
,
2536 const nsCSSValue
& aRTLLogicalValue
,
2537 mozilla::css::Side aSide
,
2538 nsCSSRect
& aValueRect
,
2539 bool& aCanStoreInRuleTree
)
2541 bool LTRlogical
= aLTRSource
.GetUnit() == eCSSUnit_Enumerated
&&
2542 aLTRSource
.GetIntValue() == NS_BOXPROP_SOURCE_LOGICAL
;
2543 bool RTLlogical
= aRTLSource
.GetUnit() == eCSSUnit_Enumerated
&&
2544 aRTLSource
.GetIntValue() == NS_BOXPROP_SOURCE_LOGICAL
;
2545 if (LTRlogical
|| RTLlogical
) {
2546 // We can't cache anything on the rule tree if we use any data from
2547 // the style context, since data cached in the rule tree could be
2548 // used with a style context with a different value.
2549 aCanStoreInRuleTree
= false;
2550 uint8_t dir
= aContext
->StyleVisibility()->mDirection
;
2552 if (dir
== NS_STYLE_DIRECTION_LTR
) {
2554 aValueRect
.*(nsCSSRect::sides
[aSide
]) = aLTRLogicalValue
;
2557 aValueRect
.*(nsCSSRect::sides
[aSide
]) = aRTLLogicalValue
;
2559 } else if (aLTRLogicalValue
.GetUnit() == eCSSUnit_Inherit
||
2560 aRTLLogicalValue
.GetUnit() == eCSSUnit_Inherit
) {
2561 // It actually is valid to store this in the ruletree, since
2562 // LTRlogical and RTLlogical are both false, but doing that will
2563 // trigger asserts. Silence those.
2564 aCanStoreInRuleTree
= false;
2569 * Begin an nsRuleNode::Compute*Data function for an inherited struct.
2571 * @param type_ The nsStyle* type this function computes.
2572 * @param ctorargs_ The arguments used for the default nsStyle* constructor.
2573 * @param data_ Variable (declared here) holding the result of this
2575 * @param parentdata_ Variable (declared here) holding the parent style
2576 * context's data for this struct.
2578 #define COMPUTE_START_INHERITED(type_, ctorargs_, data_, parentdata_) \
2579 NS_ASSERTION(aRuleDetail != eRuleFullInherited, \
2580 "should not have bothered calling Compute*Data"); \
2582 nsStyleContext* parentContext = aContext->GetParent(); \
2584 nsStyle##type_* data_ = nullptr; \
2585 mozilla::Maybe<nsStyle##type_> maybeFakeParentData; \
2586 const nsStyle##type_* parentdata_ = nullptr; \
2587 bool canStoreInRuleTree = aCanStoreInRuleTree; \
2589 /* If |canStoreInRuleTree| might be true by the time we're done, we */ \
2590 /* can't call parentContext->Style##type_() since it could recur into */ \
2591 /* setting the same struct on the same rule node, causing a leak. */ \
2592 if (aRuleDetail != eRuleFullReset && \
2593 (!aStartStruct || (aRuleDetail != eRulePartialReset && \
2594 aRuleDetail != eRuleNone))) { \
2595 if (parentContext) { \
2596 parentdata_ = parentContext->Style##type_(); \
2598 maybeFakeParentData.emplace ctorargs_; \
2599 parentdata_ = maybeFakeParentData.ptr(); \
2603 /* We only need to compute the delta between this computed data and */ \
2604 /* our computed data. */ \
2605 data_ = new (mPresContext) \
2606 nsStyle##type_(*static_cast<nsStyle##type_*>(aStartStruct)); \
2608 if (aRuleDetail != eRuleFullMixed && aRuleDetail != eRuleFullReset) { \
2609 /* No question. We will have to inherit. Go ahead and init */ \
2610 /* with inherited vals from parent. */ \
2611 canStoreInRuleTree = false; \
2613 data_ = new (mPresContext) nsStyle##type_(*parentdata_); \
2615 data_ = new (mPresContext) nsStyle##type_ ctorargs_; \
2618 data_ = new (mPresContext) nsStyle##type_ ctorargs_; \
2622 parentdata_ = data_;
2625 * Begin an nsRuleNode::Compute*Data function for a reset struct.
2627 * @param type_ The nsStyle* type this function computes.
2628 * @param ctorargs_ The arguments used for the default nsStyle* constructor.
2629 * @param data_ Variable (declared here) holding the result of this
2631 * @param parentdata_ Variable (declared here) holding the parent style
2632 * context's data for this struct.
2634 #define COMPUTE_START_RESET(type_, ctorargs_, data_, parentdata_) \
2635 NS_ASSERTION(aRuleDetail != eRuleFullInherited, \
2636 "should not have bothered calling Compute*Data"); \
2638 nsStyleContext* parentContext = aContext->GetParent(); \
2639 /* Reset structs don't inherit from first-line */ \
2640 /* See similar code in WalkRuleTree */ \
2641 while (parentContext && \
2642 parentContext->GetPseudo() == nsCSSPseudoElements::firstLine) { \
2643 parentContext = parentContext->GetParent(); \
2646 nsStyle##type_* data_; \
2648 /* We only need to compute the delta between this computed data and */ \
2649 /* our computed data. */ \
2650 data_ = new (mPresContext) \
2651 nsStyle##type_(*static_cast<nsStyle##type_*>(aStartStruct)); \
2653 data_ = new (mPresContext) nsStyle##type_ ctorargs_; \
2655 /* If |canStoreInRuleTree| might be true by the time we're done, we */ \
2656 /* can't call parentContext->Style##type_() since it could recur into */ \
2657 /* setting the same struct on the same rule node, causing a leak. */ \
2658 mozilla::Maybe<nsStyle##type_> maybeFakeParentData; \
2659 const nsStyle##type_* parentdata_ = data_; \
2660 if (aRuleDetail != eRuleFullReset && \
2661 aRuleDetail != eRulePartialReset && \
2662 aRuleDetail != eRuleNone) { \
2663 if (parentContext) { \
2664 parentdata_ = parentContext->Style##type_(); \
2666 maybeFakeParentData.emplace ctorargs_; \
2667 parentdata_ = maybeFakeParentData.ptr(); \
2670 bool canStoreInRuleTree = aCanStoreInRuleTree;
2673 * End an nsRuleNode::Compute*Data function for an inherited struct.
2675 * @param type_ The nsStyle* type this function computes.
2676 * @param data_ Variable holding the result of this function.
2678 #define COMPUTE_END_INHERITED(type_, data_) \
2679 NS_POSTCONDITION(!canStoreInRuleTree || aRuleDetail == eRuleFullReset || \
2680 (aStartStruct && aRuleDetail == eRulePartialReset), \
2681 "canStoreInRuleTree must be false for inherited structs " \
2682 "unless all properties have been specified with values " \
2683 "other than inherit"); \
2684 if (canStoreInRuleTree) { \
2685 /* We were fully specified and can therefore be cached right on the */ \
2687 if (!aHighestNode->mStyleData.mInheritedData) { \
2688 aHighestNode->mStyleData.mInheritedData = \
2689 new (mPresContext) nsInheritedStyleData; \
2691 NS_ASSERTION(!aHighestNode->mStyleData.mInheritedData-> \
2692 mStyleStructs[eStyleStruct_##type_], \
2693 "Going to leak style data"); \
2694 aHighestNode->mStyleData.mInheritedData-> \
2695 mStyleStructs[eStyleStruct_##type_] = data_; \
2696 /* Propagate the bit down. */ \
2697 PropagateDependentBit(eStyleStruct_##type_, aHighestNode, data_); \
2698 /* Tell the style context that it doesn't own the data */ \
2700 AddStyleBit(nsCachedStyleData::GetBitForSID(eStyleStruct_##type_)); \
2702 /* Always cache inherited data on the style context */ \
2703 aContext->SetStyle##type_(data_); \
2708 * End an nsRuleNode::Compute*Data function for a reset struct.
2710 * @param type_ The nsStyle* type this function computes.
2711 * @param data_ Variable holding the result of this function.
2713 #define COMPUTE_END_RESET(type_, data_) \
2714 NS_POSTCONDITION(!canStoreInRuleTree || \
2715 aRuleDetail == eRuleNone || \
2716 aRuleDetail == eRulePartialReset || \
2717 aRuleDetail == eRuleFullReset, \
2718 "canStoreInRuleTree must be false for reset structs " \
2719 "if any properties were specified as inherit"); \
2720 if (!canStoreInRuleTree) \
2721 /* We can't be cached in the rule node. We have to be put right */ \
2722 /* on the style context. */ \
2723 aContext->SetStyle(eStyleStruct_##type_, data_); \
2725 /* We were fully specified and can therefore be cached right on the */ \
2727 if (!aHighestNode->mStyleData.mResetData) { \
2728 aHighestNode->mStyleData.mResetData = \
2729 new (mPresContext) nsResetStyleData; \
2731 NS_ASSERTION(!aHighestNode->mStyleData.mResetData-> \
2732 mStyleStructs[eStyleStruct_##type_], \
2733 "Going to leak style data"); \
2734 aHighestNode->mStyleData.mResetData-> \
2735 mStyleStructs[eStyleStruct_##type_] = data_; \
2736 /* Propagate the bit down. */ \
2737 PropagateDependentBit(eStyleStruct_##type_, aHighestNode, data_); \
2742 // This function figures out how much scaling should be suppressed to
2743 // satisfy scriptminsize. This is our attempt to implement
2744 // http://www.w3.org/TR/MathML2/chapter3.html#id.3.3.4.2.2
2745 // This is called after mScriptLevel, mScriptMinSize and mScriptSizeMultiplier
2746 // have been set in aFont.
2748 // Here are the invariants we enforce:
2749 // 1) A decrease in size must not reduce the size below minscriptsize.
2750 // 2) An increase in size must not increase the size above the size we would
2751 // have if minscriptsize had not been applied anywhere.
2752 // 3) The scriptlevel-induced size change must between 1.0 and the parent's
2753 // scriptsizemultiplier^(new script level - old script level), as close to the
2754 // latter as possible subject to constraints 1 and 2.
2756 ComputeScriptLevelSize(const nsStyleFont
* aFont
, const nsStyleFont
* aParentFont
,
2757 nsPresContext
* aPresContext
, nscoord
* aUnconstrainedSize
)
2759 int32_t scriptLevelChange
=
2760 aFont
->mScriptLevel
- aParentFont
->mScriptLevel
;
2761 if (scriptLevelChange
== 0) {
2762 *aUnconstrainedSize
= aParentFont
->mScriptUnconstrainedSize
;
2763 // Constraint #3 says that we cannot change size, and #1 and #2 are always
2764 // satisfied with no change. It's important this be fast because it covers
2765 // all non-MathML content.
2766 return aParentFont
->mSize
;
2769 // Compute actual value of minScriptSize
2770 nscoord minScriptSize
= aParentFont
->mScriptMinSize
;
2771 if (aFont
->mAllowZoom
) {
2772 minScriptSize
= nsStyleFont::ZoomText(aPresContext
, minScriptSize
);
2775 double scriptLevelScale
=
2776 pow(aParentFont
->mScriptSizeMultiplier
, scriptLevelChange
);
2777 // Compute the size we would have had if minscriptsize had never been
2778 // applied, also prevent overflow (bug 413274)
2779 *aUnconstrainedSize
=
2780 NSToCoordRoundWithClamp(aParentFont
->mScriptUnconstrainedSize
*scriptLevelScale
);
2781 // Compute the size we could get via scriptlevel change
2782 nscoord scriptLevelSize
=
2783 NSToCoordRoundWithClamp(aParentFont
->mSize
*scriptLevelScale
);
2784 if (scriptLevelScale
<= 1.0) {
2785 if (aParentFont
->mSize
<= minScriptSize
) {
2786 // We can't decrease the font size at all, so just stick to no change
2787 // (authors are allowed to explicitly set the font size smaller than
2789 return aParentFont
->mSize
;
2791 // We can decrease, so apply constraint #1
2792 return std::max(minScriptSize
, scriptLevelSize
);
2794 // scriptminsize can only make sizes larger than the unconstrained size
2795 NS_ASSERTION(*aUnconstrainedSize
<= scriptLevelSize
, "How can this ever happen?");
2796 // Apply constraint #2
2797 return std::min(scriptLevelSize
, std::max(*aUnconstrainedSize
, minScriptSize
));
2802 /* static */ nscoord
2803 nsRuleNode::CalcFontPointSize(int32_t aHTMLSize
, int32_t aBasePointSize
,
2804 nsPresContext
* aPresContext
,
2805 nsFontSizeType aFontSizeType
)
2807 #define sFontSizeTableMin 9
2808 #define sFontSizeTableMax 16
2810 // This table seems to be the one used by MacIE5. We hope its adoption in Mozilla
2811 // and eventually in WinIE5.5 will help to establish a standard rendering across
2812 // platforms and browsers. For now, it is used only in Strict mode. More can be read
2813 // in the document written by Todd Farhner at:
2814 // http://style.verso.com/font_size_intervals/altintervals.html
2816 static int32_t sStrictFontSizeTable
[sFontSizeTableMax
- sFontSizeTableMin
+ 1][8] =
2818 { 9, 9, 9, 9, 11, 14, 18, 27},
2819 { 9, 9, 9, 10, 12, 15, 20, 30},
2820 { 9, 9, 10, 11, 13, 17, 22, 33},
2821 { 9, 9, 10, 12, 14, 18, 24, 36},
2822 { 9, 10, 12, 13, 16, 20, 26, 39},
2823 { 9, 10, 12, 14, 17, 21, 28, 42},
2824 { 9, 10, 13, 15, 18, 23, 30, 45},
2825 { 9, 10, 13, 16, 18, 24, 32, 48}
2827 // HTML 1 2 3 4 5 6 7
2828 // CSS xxs xs s m l xl xxl
2832 //------------------------------------------------------------
2834 // This table gives us compatibility with WinNav4 for the default fonts only.
2835 // In WinNav4, the default fonts were:
2837 // Times/12pt == Times/16px at 96ppi
2838 // Courier/10pt == Courier/13px at 96ppi
2840 // The 2 lines below marked "anchored" have the exact pixel sizes used by
2841 // WinNav4 for Times/12pt and Courier/10pt at 96ppi. As you can see, the
2842 // HTML size 3 (user pref) for those 2 anchored lines is 13px and 16px.
2844 // All values other than the anchored values were filled in by hand, never
2845 // going below 9px, and maintaining a "diagonal" relationship. See for
2846 // example the 13s -- they follow a diagonal line through the table.
2848 static int32_t sQuirksFontSizeTable
[sFontSizeTableMax
- sFontSizeTableMin
+ 1][8] =
2850 { 9, 9, 9, 9, 11, 14, 18, 28 },
2851 { 9, 9, 9, 10, 12, 15, 20, 31 },
2852 { 9, 9, 9, 11, 13, 17, 22, 34 },
2853 { 9, 9, 10, 12, 14, 18, 24, 37 },
2854 { 9, 9, 10, 13, 16, 20, 26, 40 }, // anchored (13)
2855 { 9, 9, 11, 14, 17, 21, 28, 42 },
2856 { 9, 10, 12, 15, 17, 23, 30, 45 },
2857 { 9, 10, 13, 16, 18, 24, 32, 48 } // anchored (16)
2859 // HTML 1 2 3 4 5 6 7
2860 // CSS xxs xs s m l xl xxl
2866 // These are the exact pixel values used by WinIE5 at 96ppi.
2868 { ?, 8, 11, 12, 13, 16, 21, 32 }, // smallest
2869 { ?, 9, 12, 13, 16, 21, 27, 40 }, // smaller
2870 { ?, 10, 13, 16, 18, 24, 32, 48 }, // medium
2871 { ?, 13, 16, 19, 21, 27, 37, ?? }, // larger
2872 { ?, 16, 19, 21, 24, 32, 43, ?? } // largest
2874 // HTML 1 2 3 4 5 6 7
2875 // CSS ? ? ? ? ? ? ? ?
2877 // (CSS not tested yet.)
2881 static int32_t sFontSizeFactors
[8] = { 60,75,89,100,120,150,200,300 };
2883 static int32_t sCSSColumns
[7] = {0, 1, 2, 3, 4, 5, 6}; // xxs...xxl
2884 static int32_t sHTMLColumns
[7] = {1, 2, 3, 4, 5, 6, 7}; // 1...7
2888 if (aFontSizeType
== eFontSize_HTML
) {
2889 aHTMLSize
--; // input as 1-7
2894 else if (aHTMLSize
> 6)
2898 switch (aFontSizeType
)
2900 case eFontSize_HTML
: column
= sHTMLColumns
; break;
2901 case eFontSize_CSS
: column
= sCSSColumns
; break;
2904 // Make special call specifically for fonts (needed PrintPreview)
2905 int32_t fontSize
= nsPresContext::AppUnitsToIntCSSPixels(aBasePointSize
);
2907 if ((fontSize
>= sFontSizeTableMin
) && (fontSize
<= sFontSizeTableMax
))
2909 int32_t row
= fontSize
- sFontSizeTableMin
;
2911 if (aPresContext
->CompatibilityMode() == eCompatibility_NavQuirks
) {
2912 dFontSize
= nsPresContext::CSSPixelsToAppUnits(sQuirksFontSizeTable
[row
][column
[aHTMLSize
]]);
2914 dFontSize
= nsPresContext::CSSPixelsToAppUnits(sStrictFontSizeTable
[row
][column
[aHTMLSize
]]);
2919 int32_t factor
= sFontSizeFactors
[column
[aHTMLSize
]];
2920 dFontSize
= (factor
* aBasePointSize
) / 100;
2924 if (1.0 < dFontSize
) {
2925 return (nscoord
)dFontSize
;
2931 //------------------------------------------------------------------------------
2933 //------------------------------------------------------------------------------
2935 /* static */ nscoord
2936 nsRuleNode::FindNextSmallerFontSize(nscoord aFontSize
, int32_t aBasePointSize
,
2937 nsPresContext
* aPresContext
,
2938 nsFontSizeType aFontSizeType
)
2943 float relativePosition
;
2944 nscoord smallerSize
;
2945 nscoord indexFontSize
= aFontSize
; // XXX initialize to quell a spurious gcc3.2 warning
2946 nscoord smallestIndexFontSize
;
2947 nscoord largestIndexFontSize
;
2948 nscoord smallerIndexFontSize
;
2949 nscoord largerIndexFontSize
;
2951 nscoord onePx
= nsPresContext::CSSPixelsToAppUnits(1);
2953 if (aFontSizeType
== eFontSize_HTML
) {
2961 smallestIndexFontSize
= CalcFontPointSize(indexMin
, aBasePointSize
, aPresContext
, aFontSizeType
);
2962 largestIndexFontSize
= CalcFontPointSize(indexMax
, aBasePointSize
, aPresContext
, aFontSizeType
);
2963 if (aFontSize
> smallestIndexFontSize
) {
2964 if (aFontSize
< NSToCoordRound(float(largestIndexFontSize
) * 1.5)) { // smaller will be in HTML table
2965 // find largest index smaller than current
2966 for (index
= indexMax
; index
>= indexMin
; index
--) {
2967 indexFontSize
= CalcFontPointSize(index
, aBasePointSize
, aPresContext
, aFontSizeType
);
2968 if (indexFontSize
< aFontSize
)
2971 // set up points beyond table for interpolation purposes
2972 if (indexFontSize
== smallestIndexFontSize
) {
2973 smallerIndexFontSize
= indexFontSize
- onePx
;
2974 largerIndexFontSize
= CalcFontPointSize(index
+1, aBasePointSize
, aPresContext
, aFontSizeType
);
2975 } else if (indexFontSize
== largestIndexFontSize
) {
2976 smallerIndexFontSize
= CalcFontPointSize(index
-1, aBasePointSize
, aPresContext
, aFontSizeType
);
2977 largerIndexFontSize
= NSToCoordRound(float(largestIndexFontSize
) * 1.5);
2979 smallerIndexFontSize
= CalcFontPointSize(index
-1, aBasePointSize
, aPresContext
, aFontSizeType
);
2980 largerIndexFontSize
= CalcFontPointSize(index
+1, aBasePointSize
, aPresContext
, aFontSizeType
);
2982 // compute the relative position of the parent size between the two closest indexed sizes
2983 relativePosition
= float(aFontSize
- indexFontSize
) / float(largerIndexFontSize
- indexFontSize
);
2984 // set the new size to have the same relative position between the next smallest two indexed sizes
2985 smallerSize
= smallerIndexFontSize
+ NSToCoordRound(relativePosition
* (indexFontSize
- smallerIndexFontSize
));
2987 else { // larger than HTML table, drop by 33%
2988 smallerSize
= NSToCoordRound(float(aFontSize
) / 1.5);
2991 else { // smaller than HTML table, drop by 1px
2992 smallerSize
= std::max(aFontSize
- onePx
, onePx
);
2997 //------------------------------------------------------------------------------
2999 //------------------------------------------------------------------------------
3001 /* static */ nscoord
3002 nsRuleNode::FindNextLargerFontSize(nscoord aFontSize
, int32_t aBasePointSize
,
3003 nsPresContext
* aPresContext
,
3004 nsFontSizeType aFontSizeType
)
3009 float relativePosition
;
3012 nscoord indexFontSize
= aFontSize
; // XXX initialize to quell a spurious gcc3.2 warning
3013 nscoord smallestIndexFontSize
;
3014 nscoord largestIndexFontSize
;
3015 nscoord smallerIndexFontSize
;
3016 nscoord largerIndexFontSize
;
3018 nscoord onePx
= nsPresContext::CSSPixelsToAppUnits(1);
3020 if (aFontSizeType
== eFontSize_HTML
) {
3028 smallestIndexFontSize
= CalcFontPointSize(indexMin
, aBasePointSize
, aPresContext
, aFontSizeType
);
3029 largestIndexFontSize
= CalcFontPointSize(indexMax
, aBasePointSize
, aPresContext
, aFontSizeType
);
3030 if (aFontSize
> (smallestIndexFontSize
- onePx
)) {
3031 if (aFontSize
< largestIndexFontSize
) { // larger will be in HTML table
3032 // find smallest index larger than current
3033 for (index
= indexMin
; index
<= indexMax
; index
++) {
3034 indexFontSize
= CalcFontPointSize(index
, aBasePointSize
, aPresContext
, aFontSizeType
);
3035 if (indexFontSize
> aFontSize
)
3038 // set up points beyond table for interpolation purposes
3039 if (indexFontSize
== smallestIndexFontSize
) {
3040 smallerIndexFontSize
= indexFontSize
- onePx
;
3041 largerIndexFontSize
= CalcFontPointSize(index
+1, aBasePointSize
, aPresContext
, aFontSizeType
);
3042 } else if (indexFontSize
== largestIndexFontSize
) {
3043 smallerIndexFontSize
= CalcFontPointSize(index
-1, aBasePointSize
, aPresContext
, aFontSizeType
);
3044 largerIndexFontSize
= NSCoordSaturatingMultiply(largestIndexFontSize
, 1.5);
3046 smallerIndexFontSize
= CalcFontPointSize(index
-1, aBasePointSize
, aPresContext
, aFontSizeType
);
3047 largerIndexFontSize
= CalcFontPointSize(index
+1, aBasePointSize
, aPresContext
, aFontSizeType
);
3049 // compute the relative position of the parent size between the two closest indexed sizes
3050 relativePosition
= float(aFontSize
- smallerIndexFontSize
) / float(indexFontSize
- smallerIndexFontSize
);
3051 // set the new size to have the same relative position between the next largest two indexed sizes
3052 adjustment
= NSCoordSaturatingNonnegativeMultiply(largerIndexFontSize
- indexFontSize
, relativePosition
);
3053 largerSize
= NSCoordSaturatingAdd(indexFontSize
, adjustment
);
3055 else { // larger than HTML table, increase by 50%
3056 largerSize
= NSCoordSaturatingMultiply(aFontSize
, 1.5);
3059 else { // smaller than HTML table, increase by 1px
3060 largerSize
= NSCoordSaturatingAdd(aFontSize
, onePx
);
3065 struct SetFontSizeCalcOps
: public css::BasicCoordCalcOps
,
3066 public css::NumbersAlreadyNormalizedOps
3068 // The parameters beyond aValue that we need for CalcLengthWith.
3069 const nscoord mParentSize
;
3070 const nsStyleFont
* const mParentFont
;
3071 nsPresContext
* const mPresContext
;
3073 bool& mCanStoreInRuleTree
;
3075 SetFontSizeCalcOps(nscoord aParentSize
, const nsStyleFont
* aParentFont
,
3076 nsPresContext
* aPresContext
, bool aAtRoot
,
3077 bool& aCanStoreInRuleTree
)
3078 : mParentSize(aParentSize
),
3079 mParentFont(aParentFont
),
3080 mPresContext(aPresContext
),
3082 mCanStoreInRuleTree(aCanStoreInRuleTree
)
3086 result_type
ComputeLeafValue(const nsCSSValue
& aValue
)
3089 if (aValue
.IsLengthUnit()) {
3090 // Note that font-based length units use the parent's size
3091 // unadjusted for scriptlevel changes. A scriptlevel change
3092 // between us and the parent is simply ignored.
3093 size
= CalcLengthWith(aValue
, mParentSize
,
3095 nullptr, mPresContext
, mAtRoot
,
3096 true, mCanStoreInRuleTree
);
3097 if (!aValue
.IsRelativeLengthUnit() && mParentFont
->mAllowZoom
) {
3098 size
= nsStyleFont::ZoomText(mPresContext
, size
);
3101 else if (eCSSUnit_Percent
== aValue
.GetUnit()) {
3102 mCanStoreInRuleTree
= false;
3103 // Note that % units use the parent's size unadjusted for scriptlevel
3104 // changes. A scriptlevel change between us and the parent is simply
3106 // aValue.GetPercentValue() may be negative for, e.g., calc(-50%)
3107 size
= NSCoordSaturatingMultiply(mParentSize
, aValue
.GetPercentValue());
3109 NS_ABORT_IF_FALSE(false, "unexpected value");
3118 nsRuleNode::SetFontSize(nsPresContext
* aPresContext
,
3119 const nsRuleData
* aRuleData
,
3120 const nsStyleFont
* aFont
,
3121 const nsStyleFont
* aParentFont
,
3123 const nsFont
& aSystemFont
,
3124 nscoord aParentSize
,
3125 nscoord aScriptLevelAdjustedParentSize
,
3126 bool aUsedStartStruct
,
3128 bool& aCanStoreInRuleTree
)
3130 // If false, means that *aSize has not been zoomed. If true, means that
3131 // *aSize has been zoomed iff aParentFont->mAllowZoom is true.
3132 bool sizeIsZoomedAccordingToParent
= false;
3134 int32_t baseSize
= (int32_t) aPresContext
->
3135 GetDefaultFont(aFont
->mGenericID
, aFont
->mLanguage
)->size
;
3136 const nsCSSValue
* sizeValue
= aRuleData
->ValueForFontSize();
3137 if (eCSSUnit_Enumerated
== sizeValue
->GetUnit()) {
3138 int32_t value
= sizeValue
->GetIntValue();
3140 if ((NS_STYLE_FONT_SIZE_XXSMALL
<= value
) &&
3141 (value
<= NS_STYLE_FONT_SIZE_XXLARGE
)) {
3142 *aSize
= CalcFontPointSize(value
, baseSize
,
3143 aPresContext
, eFontSize_CSS
);
3145 else if (NS_STYLE_FONT_SIZE_XXXLARGE
== value
) {
3146 // <font size="7"> is not specified in CSS, so we don't use eFontSize_CSS.
3147 *aSize
= CalcFontPointSize(value
, baseSize
, aPresContext
);
3149 else if (NS_STYLE_FONT_SIZE_LARGER
== value
||
3150 NS_STYLE_FONT_SIZE_SMALLER
== value
) {
3151 aCanStoreInRuleTree
= false;
3153 // Un-zoom so we use the tables correctly. We'll then rezoom due
3154 // to the |zoom = true| above.
3155 // Note that relative units here use the parent's size unadjusted
3156 // for scriptlevel changes. A scriptlevel change between us and the parent
3157 // is simply ignored.
3158 nscoord parentSize
= aParentSize
;
3159 if (aParentFont
->mAllowZoom
) {
3160 parentSize
= nsStyleFont::UnZoomText(aPresContext
, parentSize
);
3163 if (NS_STYLE_FONT_SIZE_LARGER
== value
) {
3164 *aSize
= FindNextLargerFontSize(parentSize
,
3165 baseSize
, aPresContext
, eFontSize_CSS
);
3167 NS_ASSERTION(*aSize
>= parentSize
,
3168 "FindNextLargerFontSize failed");
3171 *aSize
= FindNextSmallerFontSize(parentSize
,
3172 baseSize
, aPresContext
, eFontSize_CSS
);
3173 NS_ASSERTION(*aSize
< parentSize
||
3174 parentSize
<= nsPresContext::CSSPixelsToAppUnits(1),
3175 "FindNextSmallerFontSize failed");
3178 NS_NOTREACHED("unexpected value");
3181 else if (sizeValue
->IsLengthUnit() ||
3182 sizeValue
->GetUnit() == eCSSUnit_Percent
||
3183 sizeValue
->IsCalcUnit()) {
3184 SetFontSizeCalcOps
ops(aParentSize
, aParentFont
,
3185 aPresContext
, aAtRoot
,
3186 aCanStoreInRuleTree
);
3187 *aSize
= css::ComputeCalc(*sizeValue
, ops
);
3189 NS_ABORT_IF_FALSE(sizeValue
->IsCalcUnit(),
3190 "negative lengths and percents should be rejected "
3194 // The calc ops will always zoom its result according to the value
3195 // of aParentFont->mAllowZoom.
3196 sizeIsZoomedAccordingToParent
= true;
3198 else if (eCSSUnit_System_Font
== sizeValue
->GetUnit()) {
3199 // this becomes our cascading size
3200 *aSize
= aSystemFont
.size
;
3202 else if (eCSSUnit_Inherit
== sizeValue
->GetUnit() ||
3203 eCSSUnit_Unset
== sizeValue
->GetUnit()) {
3204 aCanStoreInRuleTree
= false;
3205 // We apply scriptlevel change for this case, because the default is
3206 // to inherit and we don't want explicit "inherit" to differ from the
3208 *aSize
= aScriptLevelAdjustedParentSize
;
3209 sizeIsZoomedAccordingToParent
= true;
3211 else if (eCSSUnit_Initial
== sizeValue
->GetUnit()) {
3212 // The initial value is 'medium', which has magical sizing based on
3213 // the generic font family, so do that here too.
3216 NS_ASSERTION(eCSSUnit_Null
== sizeValue
->GetUnit(),
3217 "What kind of font-size value is this?");
3218 // if aUsedStartStruct is true, then every single property in the
3219 // font struct is being set all at once. This means scriptlevel is not
3220 // going to have any influence on the font size; there is no need to
3221 // do anything here.
3222 if (!aUsedStartStruct
&& aParentSize
!= aScriptLevelAdjustedParentSize
) {
3223 // There was no rule affecting the size but the size has been
3224 // affected by the parent's size via scriptlevel change. So we cannot
3225 // store the data in the rule tree.
3226 aCanStoreInRuleTree
= false;
3227 *aSize
= aScriptLevelAdjustedParentSize
;
3228 sizeIsZoomedAccordingToParent
= true;
3234 // We want to zoom the cascaded size so that em-based measurements,
3235 // line-heights, etc., work.
3236 bool currentlyZoomed
= sizeIsZoomedAccordingToParent
&&
3237 aParentFont
->mAllowZoom
;
3238 if (!currentlyZoomed
&& aFont
->mAllowZoom
) {
3239 *aSize
= nsStyleFont::ZoomText(aPresContext
, *aSize
);
3240 } else if (currentlyZoomed
&& !aFont
->mAllowZoom
) {
3241 *aSize
= nsStyleFont::UnZoomText(aPresContext
, *aSize
);
3245 static int8_t ClampTo8Bit(int32_t aValue
) {
3250 return int8_t(aValue
);
3254 nsRuleNode::SetFont(nsPresContext
* aPresContext
, nsStyleContext
* aContext
,
3255 uint8_t aGenericFontID
, const nsRuleData
* aRuleData
,
3256 const nsStyleFont
* aParentFont
,
3257 nsStyleFont
* aFont
, bool aUsedStartStruct
,
3258 bool& aCanStoreInRuleTree
)
3260 bool atRoot
= !aContext
->GetParent();
3262 // -x-text-zoom: none, inherit, initial
3264 const nsCSSValue
* textZoomValue
= aRuleData
->ValueForTextZoom();
3265 if (eCSSUnit_Null
!= textZoomValue
->GetUnit()) {
3266 if (eCSSUnit_Inherit
== textZoomValue
->GetUnit()) {
3267 allowZoom
= aParentFont
->mAllowZoom
;
3268 } else if (eCSSUnit_None
== textZoomValue
->GetUnit()) {
3271 MOZ_ASSERT(eCSSUnit_Initial
== textZoomValue
->GetUnit(),
3275 aFont
->EnableZoom(aPresContext
, allowZoom
);
3278 // mLanguage must be set before before any of the CalcLengthWith calls
3279 // (direct calls or calls via SetFontSize) for the cases where |aParentFont|
3280 // is the same as |aFont|.
3282 // -x-lang: string, inherit
3283 // This is not a real CSS property, it is an HTML attribute mapped to CSS.
3284 const nsCSSValue
* langValue
= aRuleData
->ValueForLang();
3285 if (eCSSUnit_Ident
== langValue
->GetUnit()) {
3287 langValue
->GetStringValue(lang
);
3289 nsContentUtils::ASCIIToLower(lang
);
3290 aFont
->mLanguage
= do_GetAtom(lang
);
3291 aFont
->mExplicitLanguage
= true;
3294 const nsFont
* defaultVariableFont
=
3295 aPresContext
->GetDefaultFont(kPresContext_DefaultVariableFont_ID
,
3298 // -moz-system-font: enum (never inherit!)
3300 NS_STYLE_FONT_CAPTION
== LookAndFeel::eFont_Caption
&&
3301 NS_STYLE_FONT_ICON
== LookAndFeel::eFont_Icon
&&
3302 NS_STYLE_FONT_MENU
== LookAndFeel::eFont_Menu
&&
3303 NS_STYLE_FONT_MESSAGE_BOX
== LookAndFeel::eFont_MessageBox
&&
3304 NS_STYLE_FONT_SMALL_CAPTION
== LookAndFeel::eFont_SmallCaption
&&
3305 NS_STYLE_FONT_STATUS_BAR
== LookAndFeel::eFont_StatusBar
&&
3306 NS_STYLE_FONT_WINDOW
== LookAndFeel::eFont_Window
&&
3307 NS_STYLE_FONT_DOCUMENT
== LookAndFeel::eFont_Document
&&
3308 NS_STYLE_FONT_WORKSPACE
== LookAndFeel::eFont_Workspace
&&
3309 NS_STYLE_FONT_DESKTOP
== LookAndFeel::eFont_Desktop
&&
3310 NS_STYLE_FONT_INFO
== LookAndFeel::eFont_Info
&&
3311 NS_STYLE_FONT_DIALOG
== LookAndFeel::eFont_Dialog
&&
3312 NS_STYLE_FONT_BUTTON
== LookAndFeel::eFont_Button
&&
3313 NS_STYLE_FONT_PULL_DOWN_MENU
== LookAndFeel::eFont_PullDownMenu
&&
3314 NS_STYLE_FONT_LIST
== LookAndFeel::eFont_List
&&
3315 NS_STYLE_FONT_FIELD
== LookAndFeel::eFont_Field
,
3316 "LookAndFeel.h system-font constants out of sync with nsStyleConsts.h");
3318 // Fall back to defaultVariableFont.
3319 nsFont systemFont
= *defaultVariableFont
;
3320 const nsCSSValue
* systemFontValue
= aRuleData
->ValueForSystemFont();
3321 if (eCSSUnit_Enumerated
== systemFontValue
->GetUnit()) {
3322 gfxFontStyle fontStyle
;
3323 LookAndFeel::FontID fontID
=
3324 (LookAndFeel::FontID
)systemFontValue
->GetIntValue();
3326 (float)nsPresContext::AppUnitsPerCSSPixel() /
3327 aPresContext
->DeviceContext()->UnscaledAppUnitsPerDevPixel();
3328 nsAutoString systemFontName
;
3329 if (LookAndFeel::GetFont(fontID
, systemFontName
, fontStyle
, devPerCSS
)) {
3330 systemFontName
.Trim("\"'");
3331 systemFont
.fontlist
= FontFamilyList(systemFontName
, eUnquotedName
);
3332 systemFont
.fontlist
.SetDefaultFontType(eFamily_none
);
3333 systemFont
.style
= fontStyle
.style
;
3334 systemFont
.systemFont
= fontStyle
.systemFont
;
3335 systemFont
.weight
= fontStyle
.weight
;
3336 systemFont
.stretch
= fontStyle
.stretch
;
3337 systemFont
.decorations
= NS_FONT_DECORATION_NONE
;
3338 systemFont
.size
= NSFloatPixelsToAppUnits(fontStyle
.size
,
3339 aPresContext
->DeviceContext()->
3340 UnscaledAppUnitsPerDevPixel());
3341 //systemFont.langGroup = fontStyle.langGroup;
3342 systemFont
.sizeAdjust
= fontStyle
.sizeAdjust
;
3345 // XXXldb This platform-specific stuff should be in the
3346 // LookAndFeel implementation, not here.
3347 // XXXzw Should we even still *have* this code? It looks to be making
3348 // old, probably obsolete assumptions.
3350 if (fontID
== LookAndFeel::eFont_Field
||
3351 fontID
== LookAndFeel::eFont_Button
||
3352 fontID
== LookAndFeel::eFont_List
) {
3353 // As far as I can tell the system default fonts and sizes
3354 // on MS-Windows for Buttons, Listboxes/Comboxes and Text Fields are
3355 // all pre-determined and cannot be changed by either the control panel
3356 // or programmatically.
3357 // Fields (text fields)
3358 // Button and Selects (listboxes/comboboxes)
3359 // We use whatever font is defined by the system. Which it appears
3360 // (and the assumption is) it is always a proportional font. Then we
3361 // always use 2 points smaller than what the browser has defined as
3362 // the default proportional font.
3363 // Assumption: system defined font is proportional
3365 std::max(defaultVariableFont
->size
-
3366 nsPresContext::CSSPointsToAppUnits(2), 0);
3372 // font-family: font family list, enum, inherit
3373 const nsCSSValue
* familyValue
= aRuleData
->ValueForFontFamily();
3374 NS_ASSERTION(eCSSUnit_Enumerated
!= familyValue
->GetUnit(),
3375 "system fonts should not be in mFamily anymore");
3376 if (eCSSUnit_FontFamilyList
== familyValue
->GetUnit()) {
3377 // set the correct font if we are using DocumentFonts OR we are overriding for XUL
3379 if (aGenericFontID
== kGenericFont_NONE
) {
3380 uint32_t len
= defaultVariableFont
->fontlist
.Length();
3381 FontFamilyType generic
= defaultVariableFont
->fontlist
.FirstGeneric();
3382 NS_ASSERTION(len
== 1 &&
3383 (generic
== eFamily_serif
|| generic
== eFamily_sans_serif
),
3384 "default variable font must be a single serif or sans-serif");
3385 if (len
== 1 && generic
!= eFamily_none
) {
3386 aFont
->mFont
.fontlist
.SetDefaultFontType(generic
);
3389 aFont
->mFont
.fontlist
.SetDefaultFontType(eFamily_none
);
3391 aFont
->mFont
.systemFont
= false;
3392 // Technically this is redundant with the code below, but it's good
3393 // to have since we'll still want it once we get rid of
3394 // SetGenericFont (bug 380915).
3395 aFont
->mGenericID
= aGenericFontID
;
3397 else if (eCSSUnit_System_Font
== familyValue
->GetUnit()) {
3398 aFont
->mFont
.fontlist
= systemFont
.fontlist
;
3399 aFont
->mFont
.systemFont
= true;
3400 aFont
->mGenericID
= kGenericFont_NONE
;
3402 else if (eCSSUnit_Inherit
== familyValue
->GetUnit() ||
3403 eCSSUnit_Unset
== familyValue
->GetUnit()) {
3404 aCanStoreInRuleTree
= false;
3405 aFont
->mFont
.fontlist
= aParentFont
->mFont
.fontlist
;
3406 aFont
->mFont
.systemFont
= aParentFont
->mFont
.systemFont
;
3407 aFont
->mGenericID
= aParentFont
->mGenericID
;
3409 else if (eCSSUnit_Initial
== familyValue
->GetUnit()) {
3410 aFont
->mFont
.fontlist
= defaultVariableFont
->fontlist
;
3411 aFont
->mFont
.systemFont
= defaultVariableFont
->systemFont
;
3412 aFont
->mGenericID
= kGenericFont_NONE
;
3415 // When we're in the loop in SetGenericFont, we must ensure that we
3416 // always keep aFont->mFlags set to the correct generic. But we have
3417 // to be careful not to touch it when we're called directly from
3418 // ComputeFontData, because we could have a start struct.
3419 if (aGenericFontID
!= kGenericFont_NONE
) {
3420 aFont
->mGenericID
= aGenericFontID
;
3423 // -moz-math-variant: enum, inherit, initial
3424 SetDiscrete(*aRuleData
->ValueForMathVariant(), aFont
->mMathVariant
,
3425 aCanStoreInRuleTree
,
3426 SETDSC_ENUMERATED
| SETDSC_UNSET_INHERIT
,
3427 aParentFont
->mMathVariant
, NS_MATHML_MATHVARIANT_NONE
,
3430 // -moz-math-display: enum, inherit, initial
3431 SetDiscrete(*aRuleData
->ValueForMathDisplay(), aFont
->mMathDisplay
,
3432 aCanStoreInRuleTree
,
3433 SETDSC_ENUMERATED
| SETDSC_UNSET_INHERIT
,
3434 aParentFont
->mMathDisplay
, NS_MATHML_DISPLAYSTYLE_INLINE
,
3437 // font-smoothing: enum, inherit, initial
3438 SetDiscrete(*aRuleData
->ValueForOSXFontSmoothing(),
3439 aFont
->mFont
.smoothing
, aCanStoreInRuleTree
,
3440 SETDSC_ENUMERATED
| SETDSC_UNSET_INHERIT
,
3441 aParentFont
->mFont
.smoothing
,
3442 defaultVariableFont
->smoothing
,
3445 // font-style: enum, inherit, initial, -moz-system-font
3446 if (aFont
->mMathVariant
!= NS_MATHML_MATHVARIANT_NONE
) {
3447 // -moz-math-variant overrides font-style
3448 aFont
->mFont
.style
= NS_FONT_STYLE_NORMAL
;
3450 SetDiscrete(*aRuleData
->ValueForFontStyle(),
3451 aFont
->mFont
.style
, aCanStoreInRuleTree
,
3452 SETDSC_ENUMERATED
| SETDSC_SYSTEM_FONT
| SETDSC_UNSET_INHERIT
,
3453 aParentFont
->mFont
.style
,
3454 defaultVariableFont
->style
,
3455 0, 0, 0, systemFont
.style
);
3458 // font-weight: int, enum, inherit, initial, -moz-system-font
3459 // special handling for enum
3460 const nsCSSValue
* weightValue
= aRuleData
->ValueForFontWeight();
3461 if (aFont
->mMathVariant
!= NS_MATHML_MATHVARIANT_NONE
) {
3462 // -moz-math-variant overrides font-weight
3463 aFont
->mFont
.weight
= NS_FONT_WEIGHT_NORMAL
;
3464 } else if (eCSSUnit_Enumerated
== weightValue
->GetUnit()) {
3465 int32_t value
= weightValue
->GetIntValue();
3467 case NS_STYLE_FONT_WEIGHT_NORMAL
:
3468 case NS_STYLE_FONT_WEIGHT_BOLD
:
3469 aFont
->mFont
.weight
= value
;
3471 case NS_STYLE_FONT_WEIGHT_BOLDER
: {
3472 aCanStoreInRuleTree
= false;
3473 int32_t inheritedValue
= aParentFont
->mFont
.weight
;
3474 if (inheritedValue
<= 300) {
3475 aFont
->mFont
.weight
= 400;
3476 } else if (inheritedValue
<= 500) {
3477 aFont
->mFont
.weight
= 700;
3479 aFont
->mFont
.weight
= 900;
3483 case NS_STYLE_FONT_WEIGHT_LIGHTER
: {
3484 aCanStoreInRuleTree
= false;
3485 int32_t inheritedValue
= aParentFont
->mFont
.weight
;
3486 if (inheritedValue
< 600) {
3487 aFont
->mFont
.weight
= 100;
3488 } else if (inheritedValue
< 800) {
3489 aFont
->mFont
.weight
= 400;
3491 aFont
->mFont
.weight
= 700;
3497 SetDiscrete(*weightValue
, aFont
->mFont
.weight
, aCanStoreInRuleTree
,
3498 SETDSC_INTEGER
| SETDSC_SYSTEM_FONT
| SETDSC_UNSET_INHERIT
,
3499 aParentFont
->mFont
.weight
,
3500 defaultVariableFont
->weight
,
3501 0, 0, 0, systemFont
.weight
);
3503 // font-stretch: enum, inherit, initial, -moz-system-font
3504 SetDiscrete(*aRuleData
->ValueForFontStretch(),
3505 aFont
->mFont
.stretch
, aCanStoreInRuleTree
,
3506 SETDSC_SYSTEM_FONT
| SETDSC_ENUMERATED
| SETDSC_UNSET_INHERIT
,
3507 aParentFont
->mFont
.stretch
,
3508 defaultVariableFont
->stretch
,
3509 0, 0, 0, systemFont
.stretch
);
3511 // Compute scriptlevel, scriptminsize and scriptsizemultiplier now so
3512 // they're available for font-size computation.
3514 // -moz-script-min-size: length
3515 const nsCSSValue
* scriptMinSizeValue
= aRuleData
->ValueForScriptMinSize();
3516 if (scriptMinSizeValue
->IsLengthUnit()) {
3517 // scriptminsize in font units (em, ex) has to be interpreted relative
3518 // to the parent font, or the size definitions are circular and we
3520 aFont
->mScriptMinSize
=
3521 CalcLengthWith(*scriptMinSizeValue
, aParentFont
->mSize
,
3523 nullptr, aPresContext
, atRoot
, true,
3524 aCanStoreInRuleTree
);
3527 // -moz-script-size-multiplier: factor, inherit, initial
3528 SetFactor(*aRuleData
->ValueForScriptSizeMultiplier(),
3529 aFont
->mScriptSizeMultiplier
,
3530 aCanStoreInRuleTree
, aParentFont
->mScriptSizeMultiplier
,
3531 NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER
,
3532 SETFCT_POSITIVE
| SETFCT_UNSET_INHERIT
);
3534 // -moz-script-level: integer, number, inherit
3535 const nsCSSValue
* scriptLevelValue
= aRuleData
->ValueForScriptLevel();
3536 if (eCSSUnit_Integer
== scriptLevelValue
->GetUnit()) {
3538 aCanStoreInRuleTree
= false;
3539 aFont
->mScriptLevel
= ClampTo8Bit(aParentFont
->mScriptLevel
+ scriptLevelValue
->GetIntValue());
3541 else if (eCSSUnit_Number
== scriptLevelValue
->GetUnit()) {
3543 aFont
->mScriptLevel
= ClampTo8Bit(int32_t(scriptLevelValue
->GetFloatValue()));
3545 else if (eCSSUnit_Auto
== scriptLevelValue
->GetUnit()) {
3547 aCanStoreInRuleTree
= false;
3548 aFont
->mScriptLevel
= ClampTo8Bit(aParentFont
->mScriptLevel
+
3549 (aParentFont
->mMathDisplay
==
3550 NS_MATHML_DISPLAYSTYLE_INLINE
? 1 : 0));
3552 else if (eCSSUnit_Inherit
== scriptLevelValue
->GetUnit() ||
3553 eCSSUnit_Unset
== scriptLevelValue
->GetUnit()) {
3554 aCanStoreInRuleTree
= false;
3555 aFont
->mScriptLevel
= aParentFont
->mScriptLevel
;
3557 else if (eCSSUnit_Initial
== scriptLevelValue
->GetUnit()) {
3558 aFont
->mScriptLevel
= 0;
3561 // font-kerning: none, enum, inherit, initial, -moz-system-font
3562 SetDiscrete(*aRuleData
->ValueForFontKerning(),
3563 aFont
->mFont
.kerning
, aCanStoreInRuleTree
,
3564 SETDSC_ENUMERATED
| SETDSC_SYSTEM_FONT
| SETDSC_UNSET_INHERIT
,
3565 aParentFont
->mFont
.kerning
,
3566 defaultVariableFont
->kerning
,
3567 0, 0, 0, systemFont
.kerning
);
3569 // font-synthesis: none, enum (bit field), inherit, initial, -moz-system-font
3570 SetDiscrete(*aRuleData
->ValueForFontSynthesis(),
3571 aFont
->mFont
.synthesis
, aCanStoreInRuleTree
,
3572 SETDSC_NONE
| SETDSC_ENUMERATED
| SETDSC_SYSTEM_FONT
|
3573 SETDSC_UNSET_INHERIT
,
3574 aParentFont
->mFont
.synthesis
,
3575 defaultVariableFont
->synthesis
,
3576 0, 0, 0, systemFont
.synthesis
);
3578 // font-variant-alternates: normal, enum (bit field) + functions, inherit,
3579 // initial, -moz-system-font
3580 const nsCSSValue
* variantAlternatesValue
=
3581 aRuleData
->ValueForFontVariantAlternates();
3582 int32_t variantAlternates
= 0;
3584 switch (variantAlternatesValue
->GetUnit()) {
3585 case eCSSUnit_Inherit
:
3586 case eCSSUnit_Unset
:
3587 aFont
->mFont
.CopyAlternates(aParentFont
->mFont
);
3588 aCanStoreInRuleTree
= false;
3591 case eCSSUnit_Initial
:
3592 case eCSSUnit_Normal
:
3593 aFont
->mFont
.variantAlternates
= 0;
3594 aFont
->mFont
.alternateValues
.Clear();
3595 aFont
->mFont
.featureValueLookup
= nullptr;
3599 NS_ASSERTION(variantAlternatesValue
->GetPairValue().mXValue
.GetUnit() ==
3600 eCSSUnit_Enumerated
, "strange unit for variantAlternates");
3602 variantAlternatesValue
->GetPairValue().mXValue
.GetIntValue();
3603 aFont
->mFont
.variantAlternates
= variantAlternates
;
3605 if (variantAlternates
& NS_FONT_VARIANT_ALTERNATES_FUNCTIONAL_MASK
) {
3606 // fetch the feature lookup object from the styleset
3607 aFont
->mFont
.featureValueLookup
=
3608 aPresContext
->StyleSet()->GetFontFeatureValuesLookup();
3610 NS_ASSERTION(variantAlternatesValue
->GetPairValue().mYValue
.GetUnit() ==
3611 eCSSUnit_List
, "function list not a list value");
3612 nsStyleUtil::ComputeFunctionalAlternates(
3613 variantAlternatesValue
->GetPairValue().mYValue
.GetListValue(),
3614 aFont
->mFont
.alternateValues
);
3622 // font-variant-caps: normal, enum, inherit, initial, -moz-system-font
3623 SetDiscrete(*aRuleData
->ValueForFontVariantCaps(),
3624 aFont
->mFont
.variantCaps
, aCanStoreInRuleTree
,
3625 SETDSC_NORMAL
| SETDSC_ENUMERATED
| SETDSC_SYSTEM_FONT
|
3626 SETDSC_UNSET_INHERIT
,
3627 aParentFont
->mFont
.variantCaps
,
3628 defaultVariableFont
->variantCaps
,
3629 0, 0, 0, systemFont
.variantCaps
);
3631 // font-variant-east-asian: normal, enum (bit field), inherit, initial,
3633 SetDiscrete(*aRuleData
->ValueForFontVariantEastAsian(),
3634 aFont
->mFont
.variantEastAsian
, aCanStoreInRuleTree
,
3635 SETDSC_NORMAL
| SETDSC_ENUMERATED
| SETDSC_SYSTEM_FONT
|
3636 SETDSC_UNSET_INHERIT
,
3637 aParentFont
->mFont
.variantEastAsian
,
3638 defaultVariableFont
->variantEastAsian
,
3639 0, 0, 0, systemFont
.variantEastAsian
);
3641 // font-variant-ligatures: normal, none, enum (bit field), inherit, initial,
3643 SetDiscrete(*aRuleData
->ValueForFontVariantLigatures(),
3644 aFont
->mFont
.variantLigatures
, aCanStoreInRuleTree
,
3645 SETDSC_NORMAL
| SETDSC_NONE
| SETDSC_ENUMERATED
|
3646 SETDSC_SYSTEM_FONT
| SETDSC_UNSET_INHERIT
,
3647 aParentFont
->mFont
.variantLigatures
,
3648 defaultVariableFont
->variantLigatures
,
3649 0, NS_FONT_VARIANT_LIGATURES_NONE
, 0, systemFont
.variantLigatures
);
3651 // font-variant-numeric: normal, enum (bit field), inherit, initial,
3653 SetDiscrete(*aRuleData
->ValueForFontVariantNumeric(),
3654 aFont
->mFont
.variantNumeric
, aCanStoreInRuleTree
,
3655 SETDSC_NORMAL
| SETDSC_ENUMERATED
| SETDSC_SYSTEM_FONT
|
3656 SETDSC_UNSET_INHERIT
,
3657 aParentFont
->mFont
.variantNumeric
,
3658 defaultVariableFont
->variantNumeric
,
3659 0, 0, 0, systemFont
.variantNumeric
);
3661 // font-variant-position: normal, enum, inherit, initial,
3663 SetDiscrete(*aRuleData
->ValueForFontVariantPosition(),
3664 aFont
->mFont
.variantPosition
, aCanStoreInRuleTree
,
3665 SETDSC_NORMAL
| SETDSC_ENUMERATED
| SETDSC_SYSTEM_FONT
|
3666 SETDSC_UNSET_INHERIT
,
3667 aParentFont
->mFont
.variantPosition
,
3668 defaultVariableFont
->variantPosition
,
3669 0, 0, 0, systemFont
.variantPosition
);
3671 // font-feature-settings
3672 const nsCSSValue
* featureSettingsValue
=
3673 aRuleData
->ValueForFontFeatureSettings();
3675 switch (featureSettingsValue
->GetUnit()) {
3679 case eCSSUnit_Normal
:
3680 case eCSSUnit_Initial
:
3681 aFont
->mFont
.fontFeatureSettings
.Clear();
3684 case eCSSUnit_Inherit
:
3685 case eCSSUnit_Unset
:
3686 aCanStoreInRuleTree
= false;
3687 aFont
->mFont
.fontFeatureSettings
= aParentFont
->mFont
.fontFeatureSettings
;
3690 case eCSSUnit_System_Font
:
3691 aFont
->mFont
.fontFeatureSettings
= systemFont
.fontFeatureSettings
;
3694 case eCSSUnit_PairList
:
3695 case eCSSUnit_PairListDep
:
3696 ComputeFontFeatures(featureSettingsValue
->GetPairListValue(),
3697 aFont
->mFont
.fontFeatureSettings
);
3701 NS_ABORT_IF_FALSE(false, "unexpected value unit");
3705 // font-language-override
3706 const nsCSSValue
* languageOverrideValue
=
3707 aRuleData
->ValueForFontLanguageOverride();
3708 if (eCSSUnit_Inherit
== languageOverrideValue
->GetUnit() ||
3709 eCSSUnit_Unset
== languageOverrideValue
->GetUnit()) {
3710 aCanStoreInRuleTree
= false;
3711 aFont
->mFont
.languageOverride
= aParentFont
->mFont
.languageOverride
;
3712 } else if (eCSSUnit_Normal
== languageOverrideValue
->GetUnit() ||
3713 eCSSUnit_Initial
== languageOverrideValue
->GetUnit()) {
3714 aFont
->mFont
.languageOverride
.Truncate();
3715 } else if (eCSSUnit_System_Font
== languageOverrideValue
->GetUnit()) {
3716 aFont
->mFont
.languageOverride
= systemFont
.languageOverride
;
3717 } else if (eCSSUnit_String
== languageOverrideValue
->GetUnit()) {
3718 languageOverrideValue
->GetStringValue(aFont
->mFont
.languageOverride
);
3721 // font-size: enum, length, percent, inherit
3722 nscoord scriptLevelAdjustedParentSize
= aParentFont
->mSize
;
3723 nscoord scriptLevelAdjustedUnconstrainedParentSize
;
3724 scriptLevelAdjustedParentSize
=
3725 ComputeScriptLevelSize(aFont
, aParentFont
, aPresContext
,
3726 &scriptLevelAdjustedUnconstrainedParentSize
);
3727 NS_ASSERTION(!aUsedStartStruct
|| aFont
->mScriptUnconstrainedSize
== aFont
->mSize
,
3728 "If we have a start struct, we should have reset everything coming in here");
3729 SetFontSize(aPresContext
, aRuleData
, aFont
, aParentFont
,
3731 systemFont
, aParentFont
->mSize
, scriptLevelAdjustedParentSize
,
3732 aUsedStartStruct
, atRoot
, aCanStoreInRuleTree
);
3733 if (aParentFont
->mSize
== aParentFont
->mScriptUnconstrainedSize
&&
3734 scriptLevelAdjustedParentSize
== scriptLevelAdjustedUnconstrainedParentSize
) {
3735 // Fast path: we have not been affected by scriptminsize so we don't
3736 // need to call SetFontSize again to compute the
3737 // scriptminsize-unconstrained size. This is OK even if we have a
3738 // start struct, because if we have a start struct then 'font-size'
3739 // was specified and so scriptminsize has no effect.
3740 aFont
->mScriptUnconstrainedSize
= aFont
->mSize
;
3742 SetFontSize(aPresContext
, aRuleData
, aFont
, aParentFont
,
3743 &aFont
->mScriptUnconstrainedSize
,
3744 systemFont
, aParentFont
->mScriptUnconstrainedSize
,
3745 scriptLevelAdjustedUnconstrainedParentSize
,
3746 aUsedStartStruct
, atRoot
, aCanStoreInRuleTree
);
3748 NS_ASSERTION(aFont
->mScriptUnconstrainedSize
<= aFont
->mSize
,
3749 "scriptminsize should never be making things bigger");
3751 nscoord fontSize
= aFont
->mSize
;
3753 // enforce the user' specified minimum font-size on the value that we expose
3754 // (but don't change font-size:0, since that would unhide hidden text)
3756 nscoord minFontSize
= aPresContext
->MinFontSize(aFont
->mLanguage
);
3757 if (minFontSize
< 0) {
3760 if (fontSize
< minFontSize
&& !aPresContext
->IsChrome()) {
3761 // override the minimum font-size constraint
3762 fontSize
= minFontSize
;
3765 aFont
->mFont
.size
= fontSize
;
3767 // font-size-adjust: number, none, inherit, initial, -moz-system-font
3768 const nsCSSValue
* sizeAdjustValue
= aRuleData
->ValueForFontSizeAdjust();
3769 if (eCSSUnit_System_Font
== sizeAdjustValue
->GetUnit()) {
3770 aFont
->mFont
.sizeAdjust
= systemFont
.sizeAdjust
;
3772 SetFactor(*sizeAdjustValue
, aFont
->mFont
.sizeAdjust
,
3773 aCanStoreInRuleTree
, aParentFont
->mFont
.sizeAdjust
, 0.0f
,
3774 SETFCT_NONE
| SETFCT_UNSET_INHERIT
);
3778 nsRuleNode::ComputeFontFeatures(const nsCSSValuePairList
*aFeaturesList
,
3779 nsTArray
<gfxFontFeature
>& aFeatureSettings
)
3781 aFeatureSettings
.Clear();
3782 for (const nsCSSValuePairList
* p
= aFeaturesList
; p
; p
= p
->mNext
) {
3783 gfxFontFeature feat
= {0, 0};
3785 NS_ABORT_IF_FALSE(aFeaturesList
->mXValue
.GetUnit() == eCSSUnit_String
,
3786 "unexpected value unit");
3788 // tag is a 4-byte ASCII sequence
3790 p
->mXValue
.GetStringValue(tag
);
3791 if (tag
.Length() != 4) {
3794 // parsing validates that these are ASCII chars
3795 // tags are always big-endian
3796 feat
.mTag
= (tag
[0] << 24) | (tag
[1] << 16) | (tag
[2] << 8) | tag
[3];
3799 NS_ASSERTION(p
->mYValue
.GetUnit() == eCSSUnit_Integer
,
3800 "should have found an integer unit");
3801 feat
.mValue
= p
->mYValue
.GetIntValue();
3803 aFeatureSettings
.AppendElement(feat
);
3807 // This should die (bug 380915).
3810 // - backtrack to an ancestor with the same generic font name (possibly
3811 // up to the root where default values come from the presentation context)
3812 // - re-apply cascading rules from there without caching intermediate values
3814 nsRuleNode::SetGenericFont(nsPresContext
* aPresContext
,
3815 nsStyleContext
* aContext
,
3816 uint8_t aGenericFontID
,
3819 // walk up the contexts until a context with the desired generic font
3820 nsAutoTArray
<nsStyleContext
*, 8> contextPath
;
3821 contextPath
.AppendElement(aContext
);
3822 nsStyleContext
* higherContext
= aContext
->GetParent();
3823 while (higherContext
) {
3824 if (higherContext
->StyleFont()->mGenericID
== aGenericFontID
) {
3825 // done walking up the higher contexts
3828 contextPath
.AppendElement(higherContext
);
3829 higherContext
= higherContext
->GetParent();
3832 // re-apply the cascading rules, starting from the higher context
3834 // If we stopped earlier because we reached the root of the style tree,
3835 // we will start with the default generic font from the presentation
3836 // context. Otherwise we start with the higher context.
3837 const nsFont
* defaultFont
=
3838 aPresContext
->GetDefaultFont(aGenericFontID
, aFont
->mLanguage
);
3839 nsStyleFont
parentFont(*defaultFont
, aPresContext
);
3840 if (higherContext
) {
3841 const nsStyleFont
* tmpFont
= higherContext
->StyleFont();
3842 parentFont
= *tmpFont
;
3844 *aFont
= parentFont
;
3847 uint32_t fontBit
= nsCachedStyleData::GetBitForSID(eStyleStruct_Font
);
3849 // use placement new[] on the result of alloca() to allocate a
3850 // variable-sized stack array, including execution of constructors,
3851 // and use an RAII class to run the destructors too.
3852 size_t nprops
= nsCSSProps::PropertyCountInStruct(eStyleStruct_Font
);
3853 void* dataStorage
= alloca(nprops
* sizeof(nsCSSValue
));
3855 for (int32_t i
= contextPath
.Length() - 1; i
>= 0; --i
) {
3856 nsStyleContext
* context
= contextPath
[i
];
3857 AutoCSSValueArray
dataArray(dataStorage
, nprops
);
3859 nsRuleData
ruleData(NS_STYLE_INHERIT_BIT(Font
), dataArray
.get(),
3860 aPresContext
, context
);
3861 ruleData
.mValueOffsets
[eStyleStruct_Font
] = 0;
3863 // Trimmed down version of ::WalkRuleTree() to re-apply the style rules
3864 // Note that we *do* need to do this for our own data, since what is
3865 // in |fontData| in ComputeFontData is only for the rules below
3867 for (nsRuleNode
* ruleNode
= context
->RuleNode(); ruleNode
;
3868 ruleNode
= ruleNode
->GetParent()) {
3869 if (ruleNode
->mNoneBits
& fontBit
)
3870 // no more font rules on this branch, get out
3873 nsIStyleRule
*rule
= ruleNode
->GetRule();
3875 ruleData
.mLevel
= ruleNode
->GetLevel();
3876 ruleData
.mIsImportantRule
= ruleNode
->IsImportantRule();
3877 rule
->MapRuleInfoInto(&ruleData
);
3881 // Compute the delta from the information that the rules specified
3883 // Avoid unnecessary operations in SetFont(). But we care if it's
3884 // the final value that we're computing.
3886 ruleData
.ValueForFontFamily()->Reset();
3888 ResolveVariableReferences(eStyleStruct_Font
, &ruleData
, aContext
);
3890 nsRuleNode::SetFont(aPresContext
, context
,
3891 aGenericFontID
, &ruleData
, &parentFont
, aFont
,
3894 parentFont
= *aFont
;
3899 nsRuleNode::ComputeFontData(void* aStartStruct
,
3900 const nsRuleData
* aRuleData
,
3901 nsStyleContext
* aContext
,
3902 nsRuleNode
* aHighestNode
,
3903 const RuleDetail aRuleDetail
,
3904 const bool aCanStoreInRuleTree
)
3906 COMPUTE_START_INHERITED(Font
, (mPresContext
), font
, parentFont
)
3908 // NOTE: The |aRuleDetail| passed in is a little bit conservative due
3909 // to the -moz-system-font property. We really don't need to consider
3910 // it here in determining whether to cache in the rule tree. However,
3911 // we do need to consider it in WalkRuleTree when deciding whether to
3912 // walk further up the tree. So this means that when the font struct
3913 // is fully specified using *longhand* properties (excluding
3914 // -moz-system-font), we won't cache in the rule tree even though we
3915 // could. However, it's pretty unlikely authors will do that
3916 // (although there is a pretty good chance they'll fully specify it
3917 // using the 'font' shorthand).
3919 bool useDocumentFonts
=
3920 mPresContext
->GetCachedBoolPref(kPresContext_UseDocumentFonts
);
3922 // See if we are in the chrome
3923 // We only need to know this to determine if we have to use the
3924 // document fonts (overriding the useDocumentFonts flag).
3925 if (!useDocumentFonts
&& mPresContext
->IsChrome()) {
3926 // if we are not using document fonts, but this is a XUL document,
3927 // then we use the document fonts anyway
3928 useDocumentFonts
= true;
3931 // Figure out if we are a generic font
3932 uint8_t generic
= kGenericFont_NONE
;
3933 // XXXldb What if we would have had a string if we hadn't been doing
3934 // the optimization with a non-null aStartStruct?
3935 const nsCSSValue
* familyValue
= aRuleData
->ValueForFontFamily();
3936 if (eCSSUnit_FontFamilyList
== familyValue
->GetUnit()) {
3937 const FontFamilyList
* fontlist
= familyValue
->GetFontFamilyListValue();
3938 FontFamilyList
& fl
= font
->mFont
.fontlist
;
3941 // extract the first generic in the fontlist, if exists
3942 FontFamilyType fontType
= fontlist
->FirstGeneric();
3944 // if only a single generic, set the generic type
3945 if (fontlist
->Length() == 1) {
3948 generic
= kGenericFont_serif
;
3950 case eFamily_sans_serif
:
3951 generic
= kGenericFont_sans_serif
;
3953 case eFamily_monospace
:
3954 generic
= kGenericFont_monospace
;
3956 case eFamily_cursive
:
3957 generic
= kGenericFont_cursive
;
3959 case eFamily_fantasy
:
3960 generic
= kGenericFont_fantasy
;
3962 case eFamily_moz_fixed
:
3963 generic
= kGenericFont_moz_fixed
;
3970 // If we aren't allowed to use document fonts, then we are only entitled
3971 // to use the user's default variable-width font and fixed-width font
3972 if (!useDocumentFonts
) {
3974 case eFamily_monospace
:
3975 fl
= FontFamilyList(eFamily_monospace
);
3976 generic
= kGenericFont_monospace
;
3978 case eFamily_moz_fixed
:
3979 fl
= FontFamilyList(eFamily_moz_fixed
);
3980 generic
= kGenericFont_moz_fixed
;
3984 generic
= kGenericFont_NONE
;
3990 // Now compute our font struct
3991 if (generic
== kGenericFont_NONE
) {
3992 // continue the normal processing
3993 nsRuleNode::SetFont(mPresContext
, aContext
, generic
,
3994 aRuleData
, parentFont
, font
,
3995 aStartStruct
!= nullptr, canStoreInRuleTree
);
3998 // re-calculate the font as a generic font
3999 canStoreInRuleTree
= false;
4000 nsRuleNode::SetGenericFont(mPresContext
, aContext
, generic
,
4004 COMPUTE_END_INHERITED(Font
, font
)
4007 template <typename T
>
4008 inline uint32_t ListLength(const T
* aList
)
4013 aList
= aList
->mNext
;
4020 already_AddRefed
<nsCSSShadowArray
>
4021 nsRuleNode::GetShadowData(const nsCSSValueList
* aList
,
4022 nsStyleContext
* aContext
,
4024 bool& aCanStoreInRuleTree
)
4026 uint32_t arrayLength
= ListLength(aList
);
4028 NS_ABORT_IF_FALSE(arrayLength
> 0,
4029 "Non-null text-shadow list, yet we counted 0 items.");
4030 nsRefPtr
<nsCSSShadowArray
> shadowList
=
4031 new(arrayLength
) nsCSSShadowArray(arrayLength
);
4036 nsStyleCoord tempCoord
;
4037 DebugOnly
<bool> unitOK
;
4038 for (nsCSSShadowItem
* item
= shadowList
->ShadowAt(0);
4040 aList
= aList
->mNext
, ++item
) {
4041 NS_ABORT_IF_FALSE(aList
->mValue
.GetUnit() == eCSSUnit_Array
,
4042 "expecting a plain array value");
4043 nsCSSValue::Array
*arr
= aList
->mValue
.GetArrayValue();
4044 // OK to pass bad aParentCoord since we're not passing SETCOORD_INHERIT
4045 unitOK
= SetCoord(arr
->Item(0), tempCoord
, nsStyleCoord(),
4046 SETCOORD_LENGTH
| SETCOORD_CALC_LENGTH_ONLY
,
4047 aContext
, mPresContext
, aCanStoreInRuleTree
);
4048 NS_ASSERTION(unitOK
, "unexpected unit");
4049 item
->mXOffset
= tempCoord
.GetCoordValue();
4051 unitOK
= SetCoord(arr
->Item(1), tempCoord
, nsStyleCoord(),
4052 SETCOORD_LENGTH
| SETCOORD_CALC_LENGTH_ONLY
,
4053 aContext
, mPresContext
, aCanStoreInRuleTree
);
4054 NS_ASSERTION(unitOK
, "unexpected unit");
4055 item
->mYOffset
= tempCoord
.GetCoordValue();
4057 // Blur radius is optional in the current box-shadow spec
4058 if (arr
->Item(2).GetUnit() != eCSSUnit_Null
) {
4059 unitOK
= SetCoord(arr
->Item(2), tempCoord
, nsStyleCoord(),
4060 SETCOORD_LENGTH
| SETCOORD_CALC_LENGTH_ONLY
|
4061 SETCOORD_CALC_CLAMP_NONNEGATIVE
,
4062 aContext
, mPresContext
, aCanStoreInRuleTree
);
4063 NS_ASSERTION(unitOK
, "unexpected unit");
4064 item
->mRadius
= tempCoord
.GetCoordValue();
4069 // Find the spread radius
4070 if (aIsBoxShadow
&& arr
->Item(3).GetUnit() != eCSSUnit_Null
) {
4071 unitOK
= SetCoord(arr
->Item(3), tempCoord
, nsStyleCoord(),
4072 SETCOORD_LENGTH
| SETCOORD_CALC_LENGTH_ONLY
,
4073 aContext
, mPresContext
, aCanStoreInRuleTree
);
4074 NS_ASSERTION(unitOK
, "unexpected unit");
4075 item
->mSpread
= tempCoord
.GetCoordValue();
4080 if (arr
->Item(4).GetUnit() != eCSSUnit_Null
) {
4081 item
->mHasColor
= true;
4082 // 2nd argument can be bogus since inherit is not a valid color
4083 unitOK
= SetColor(arr
->Item(4), 0, mPresContext
, aContext
, item
->mColor
,
4084 aCanStoreInRuleTree
);
4085 NS_ASSERTION(unitOK
, "unexpected unit");
4088 if (aIsBoxShadow
&& arr
->Item(5).GetUnit() == eCSSUnit_Enumerated
) {
4089 NS_ASSERTION(arr
->Item(5).GetIntValue() == NS_STYLE_BOX_SHADOW_INSET
,
4090 "invalid keyword type for box shadow");
4091 item
->mInset
= true;
4093 item
->mInset
= false;
4097 return shadowList
.forget();
4101 nsRuleNode::ComputeTextData(void* aStartStruct
,
4102 const nsRuleData
* aRuleData
,
4103 nsStyleContext
* aContext
,
4104 nsRuleNode
* aHighestNode
,
4105 const RuleDetail aRuleDetail
,
4106 const bool aCanStoreInRuleTree
)
4108 COMPUTE_START_INHERITED(Text
, (), text
, parentText
)
4110 // tab-size: integer, inherit
4111 SetDiscrete(*aRuleData
->ValueForTabSize(),
4112 text
->mTabSize
, canStoreInRuleTree
,
4113 SETDSC_INTEGER
| SETDSC_UNSET_INHERIT
, parentText
->mTabSize
,
4114 NS_STYLE_TABSIZE_INITIAL
, 0, 0, 0, 0);
4116 // letter-spacing: normal, length, inherit
4117 SetCoord(*aRuleData
->ValueForLetterSpacing(),
4118 text
->mLetterSpacing
, parentText
->mLetterSpacing
,
4119 SETCOORD_LH
| SETCOORD_NORMAL
| SETCOORD_INITIAL_NORMAL
|
4120 SETCOORD_CALC_LENGTH_ONLY
| SETCOORD_UNSET_INHERIT
,
4121 aContext
, mPresContext
, canStoreInRuleTree
);
4123 // text-shadow: none, list, inherit, initial
4124 const nsCSSValue
* textShadowValue
= aRuleData
->ValueForTextShadow();
4125 if (textShadowValue
->GetUnit() != eCSSUnit_Null
) {
4126 text
->mTextShadow
= nullptr;
4128 // Don't need to handle none/initial explicitly: The above assignment
4129 // takes care of that
4130 if (textShadowValue
->GetUnit() == eCSSUnit_Inherit
||
4131 textShadowValue
->GetUnit() == eCSSUnit_Unset
) {
4132 canStoreInRuleTree
= false;
4133 text
->mTextShadow
= parentText
->mTextShadow
;
4134 } else if (textShadowValue
->GetUnit() == eCSSUnit_List
||
4135 textShadowValue
->GetUnit() == eCSSUnit_ListDep
) {
4137 text
->mTextShadow
= GetShadowData(textShadowValue
->GetListValue(),
4138 aContext
, false, canStoreInRuleTree
);
4142 // line-height: normal, number, length, percent, inherit
4143 const nsCSSValue
* lineHeightValue
= aRuleData
->ValueForLineHeight();
4144 if (eCSSUnit_Percent
== lineHeightValue
->GetUnit()) {
4145 canStoreInRuleTree
= false;
4146 // Use |mFont.size| to pick up minimum font size.
4147 text
->mLineHeight
.SetCoordValue(
4148 NSToCoordRound(float(aContext
->StyleFont()->mFont
.size
) *
4149 lineHeightValue
->GetPercentValue()));
4151 else if (eCSSUnit_Initial
== lineHeightValue
->GetUnit() ||
4152 eCSSUnit_System_Font
== lineHeightValue
->GetUnit()) {
4153 text
->mLineHeight
.SetNormalValue();
4156 SetCoord(*lineHeightValue
, text
->mLineHeight
, parentText
->mLineHeight
,
4157 SETCOORD_LEH
| SETCOORD_FACTOR
| SETCOORD_NORMAL
|
4158 SETCOORD_UNSET_INHERIT
,
4159 aContext
, mPresContext
, canStoreInRuleTree
);
4160 if (lineHeightValue
->IsLengthUnit() &&
4161 !lineHeightValue
->IsRelativeLengthUnit()) {
4162 nscoord lh
= nsStyleFont::ZoomText(mPresContext
,
4163 text
->mLineHeight
.GetCoordValue());
4165 canStoreInRuleTree
= false;
4166 const nsStyleFont
*font
= aContext
->StyleFont();
4167 nscoord minimumFontSize
= mPresContext
->MinFontSize(font
->mLanguage
);
4169 if (minimumFontSize
> 0 && !mPresContext
->IsChrome()) {
4170 if (font
->mSize
!= 0) {
4171 lh
= nscoord(float(lh
) * float(font
->mFont
.size
) / float(font
->mSize
));
4173 lh
= minimumFontSize
;
4176 text
->mLineHeight
.SetCoordValue(lh
);
4181 // text-align: enum, string, pair(enum|string), inherit, initial
4182 // NOTE: string is not implemented yet.
4183 const nsCSSValue
* textAlignValue
= aRuleData
->ValueForTextAlign();
4184 text
->mTextAlignTrue
= false;
4185 if (eCSSUnit_String
== textAlignValue
->GetUnit()) {
4186 NS_NOTYETIMPLEMENTED("align string");
4187 } else if (eCSSUnit_Enumerated
== textAlignValue
->GetUnit() &&
4188 NS_STYLE_TEXT_ALIGN_MOZ_CENTER_OR_INHERIT
==
4189 textAlignValue
->GetIntValue()) {
4190 canStoreInRuleTree
= false;
4191 uint8_t parentAlign
= parentText
->mTextAlign
;
4192 text
->mTextAlign
= (NS_STYLE_TEXT_ALIGN_DEFAULT
== parentAlign
) ?
4193 NS_STYLE_TEXT_ALIGN_CENTER
: parentAlign
;
4195 if (eCSSUnit_Pair
== textAlignValue
->GetUnit()) {
4196 // Two values were specified, one must be 'true'.
4197 text
->mTextAlignTrue
= true;
4198 const nsCSSValuePair
& textAlignValuePair
= textAlignValue
->GetPairValue();
4199 textAlignValue
= &textAlignValuePair
.mXValue
;
4200 if (eCSSUnit_Enumerated
== textAlignValue
->GetUnit()) {
4201 if (textAlignValue
->GetIntValue() == NS_STYLE_TEXT_ALIGN_TRUE
) {
4202 textAlignValue
= &textAlignValuePair
.mYValue
;
4204 } else if (eCSSUnit_String
== textAlignValue
->GetUnit()) {
4205 NS_NOTYETIMPLEMENTED("align string");
4207 } else if (eCSSUnit_Inherit
== textAlignValue
->GetUnit() ||
4208 eCSSUnit_Unset
== textAlignValue
->GetUnit()) {
4209 text
->mTextAlignTrue
= parentText
->mTextAlignTrue
;
4211 SetDiscrete(*textAlignValue
, text
->mTextAlign
, canStoreInRuleTree
,
4212 SETDSC_ENUMERATED
| SETDSC_UNSET_INHERIT
,
4213 parentText
->mTextAlign
,
4214 NS_STYLE_TEXT_ALIGN_DEFAULT
, 0, 0, 0, 0);
4217 // text-align-last: enum, pair(enum), inherit, initial
4218 const nsCSSValue
* textAlignLastValue
= aRuleData
->ValueForTextAlignLast();
4219 text
->mTextAlignLastTrue
= false;
4220 if (eCSSUnit_Pair
== textAlignLastValue
->GetUnit()) {
4221 // Two values were specified, one must be 'true'.
4222 text
->mTextAlignLastTrue
= true;
4223 const nsCSSValuePair
& textAlignLastValuePair
= textAlignLastValue
->GetPairValue();
4224 textAlignLastValue
= &textAlignLastValuePair
.mXValue
;
4225 if (eCSSUnit_Enumerated
== textAlignLastValue
->GetUnit()) {
4226 if (textAlignLastValue
->GetIntValue() == NS_STYLE_TEXT_ALIGN_TRUE
) {
4227 textAlignLastValue
= &textAlignLastValuePair
.mYValue
;
4230 } else if (eCSSUnit_Inherit
== textAlignLastValue
->GetUnit() ||
4231 eCSSUnit_Unset
== textAlignLastValue
->GetUnit()) {
4232 text
->mTextAlignLastTrue
= parentText
->mTextAlignLastTrue
;
4234 SetDiscrete(*textAlignLastValue
, text
->mTextAlignLast
,
4236 SETDSC_ENUMERATED
| SETDSC_UNSET_INHERIT
,
4237 parentText
->mTextAlignLast
,
4238 NS_STYLE_TEXT_ALIGN_AUTO
, 0, 0, 0, 0);
4240 // text-indent: length, percent, calc, inherit, initial
4241 SetCoord(*aRuleData
->ValueForTextIndent(), text
->mTextIndent
, parentText
->mTextIndent
,
4242 SETCOORD_LPH
| SETCOORD_INITIAL_ZERO
| SETCOORD_STORE_CALC
|
4243 SETCOORD_UNSET_INHERIT
,
4244 aContext
, mPresContext
, canStoreInRuleTree
);
4246 // text-transform: enum, inherit, initial
4247 SetDiscrete(*aRuleData
->ValueForTextTransform(), text
->mTextTransform
, canStoreInRuleTree
,
4248 SETDSC_ENUMERATED
| SETDSC_UNSET_INHERIT
,
4249 parentText
->mTextTransform
,
4250 NS_STYLE_TEXT_TRANSFORM_NONE
, 0, 0, 0, 0);
4252 // white-space: enum, inherit, initial
4253 SetDiscrete(*aRuleData
->ValueForWhiteSpace(), text
->mWhiteSpace
, canStoreInRuleTree
,
4254 SETDSC_ENUMERATED
| SETDSC_UNSET_INHERIT
,
4255 parentText
->mWhiteSpace
,
4256 NS_STYLE_WHITESPACE_NORMAL
, 0, 0, 0, 0);
4258 // word-break: enum, inherit, initial
4259 SetDiscrete(*aRuleData
->ValueForWordBreak(), text
->mWordBreak
, canStoreInRuleTree
,
4260 SETDSC_ENUMERATED
| SETDSC_UNSET_INHERIT
,
4261 parentText
->mWordBreak
,
4262 NS_STYLE_WORDBREAK_NORMAL
, 0, 0, 0, 0);
4264 // word-spacing: normal, length, inherit
4265 nsStyleCoord tempCoord
;
4266 const nsCSSValue
* wordSpacingValue
= aRuleData
->ValueForWordSpacing();
4267 if (SetCoord(*wordSpacingValue
, tempCoord
,
4268 nsStyleCoord(parentText
->mWordSpacing
,
4269 nsStyleCoord::CoordConstructor
),
4270 SETCOORD_LH
| SETCOORD_NORMAL
| SETCOORD_INITIAL_NORMAL
|
4271 SETCOORD_CALC_LENGTH_ONLY
| SETCOORD_UNSET_INHERIT
,
4272 aContext
, mPresContext
, canStoreInRuleTree
)) {
4273 if (tempCoord
.GetUnit() == eStyleUnit_Coord
) {
4274 text
->mWordSpacing
= tempCoord
.GetCoordValue();
4275 } else if (tempCoord
.GetUnit() == eStyleUnit_Normal
) {
4276 text
->mWordSpacing
= 0;
4278 NS_NOTREACHED("unexpected unit");
4281 NS_ASSERTION(wordSpacingValue
->GetUnit() == eCSSUnit_Null
,
4285 // word-wrap: enum, inherit, initial
4286 SetDiscrete(*aRuleData
->ValueForWordWrap(), text
->mWordWrap
, canStoreInRuleTree
,
4287 SETDSC_ENUMERATED
| SETDSC_UNSET_INHERIT
,
4288 parentText
->mWordWrap
,
4289 NS_STYLE_WORDWRAP_NORMAL
, 0, 0, 0, 0);
4291 // hyphens: enum, inherit, initial
4292 SetDiscrete(*aRuleData
->ValueForHyphens(), text
->mHyphens
, canStoreInRuleTree
,
4293 SETDSC_ENUMERATED
| SETDSC_UNSET_INHERIT
,
4294 parentText
->mHyphens
,
4295 NS_STYLE_HYPHENS_MANUAL
, 0, 0, 0, 0);
4297 // text-size-adjust: none, auto, inherit, initial
4298 SetDiscrete(*aRuleData
->ValueForTextSizeAdjust(), text
->mTextSizeAdjust
,
4300 SETDSC_NONE
| SETDSC_AUTO
| SETDSC_UNSET_INHERIT
,
4301 parentText
->mTextSizeAdjust
,
4302 NS_STYLE_TEXT_SIZE_ADJUST_AUTO
, // initial value
4303 NS_STYLE_TEXT_SIZE_ADJUST_AUTO
, // auto value
4304 NS_STYLE_TEXT_SIZE_ADJUST_NONE
, // none value
4307 // -moz-text-discard: enum, inherit, initial
4308 SetDiscrete(*aRuleData
->ValueForControlCharacterVisibility(),
4309 text
->mControlCharacterVisibility
,
4311 SETDSC_ENUMERATED
| SETDSC_UNSET_INHERIT
,
4312 parentText
->mControlCharacterVisibility
,
4313 NS_STYLE_CONTROL_CHARACTER_VISIBILITY_HIDDEN
, 0, 0, 0, 0);
4315 // text-orientation: enum, inherit, initial
4316 SetDiscrete(*aRuleData
->ValueForTextOrientation(), text
->mTextOrientation
,
4318 SETDSC_ENUMERATED
| SETDSC_UNSET_INHERIT
,
4319 parentText
->mTextOrientation
,
4320 NS_STYLE_TEXT_ORIENTATION_AUTO
, 0, 0, 0, 0);
4322 // text-combine-upright: enum, inherit, initial
4323 SetDiscrete(*aRuleData
->ValueForTextCombineUpright(),
4324 text
->mTextCombineUpright
,
4326 SETDSC_ENUMERATED
| SETDSC_UNSET_INHERIT
,
4327 parentText
->mTextCombineUpright
,
4328 NS_STYLE_TEXT_COMBINE_UPRIGHT_NONE
, 0, 0, 0, 0);
4330 COMPUTE_END_INHERITED(Text
, text
)
4334 nsRuleNode::ComputeTextResetData(void* aStartStruct
,
4335 const nsRuleData
* aRuleData
,
4336 nsStyleContext
* aContext
,
4337 nsRuleNode
* aHighestNode
,
4338 const RuleDetail aRuleDetail
,
4339 const bool aCanStoreInRuleTree
)
4341 COMPUTE_START_RESET(TextReset
, (), text
, parentText
)
4343 // vertical-align: enum, length, percent, calc, inherit
4344 const nsCSSValue
* verticalAlignValue
= aRuleData
->ValueForVerticalAlign();
4345 if (!SetCoord(*verticalAlignValue
, text
->mVerticalAlign
,
4346 parentText
->mVerticalAlign
,
4347 SETCOORD_LPH
| SETCOORD_ENUMERATED
| SETCOORD_STORE_CALC
,
4348 aContext
, mPresContext
, canStoreInRuleTree
)) {
4349 if (eCSSUnit_Initial
== verticalAlignValue
->GetUnit() ||
4350 eCSSUnit_Unset
== verticalAlignValue
->GetUnit()) {
4351 text
->mVerticalAlign
.SetIntValue(NS_STYLE_VERTICAL_ALIGN_BASELINE
,
4352 eStyleUnit_Enumerated
);
4356 // text-decoration-line: enum (bit field), inherit, initial
4357 const nsCSSValue
* decorationLineValue
=
4358 aRuleData
->ValueForTextDecorationLine();
4359 if (eCSSUnit_Enumerated
== decorationLineValue
->GetUnit()) {
4360 int32_t td
= decorationLineValue
->GetIntValue();
4361 text
->mTextDecorationLine
= td
;
4362 if (td
& NS_STYLE_TEXT_DECORATION_LINE_PREF_ANCHORS
) {
4363 bool underlineLinks
=
4364 mPresContext
->GetCachedBoolPref(kPresContext_UnderlineLinks
);
4365 if (underlineLinks
) {
4366 text
->mTextDecorationLine
|= NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE
;
4369 text
->mTextDecorationLine
&= ~NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE
;
4372 } else if (eCSSUnit_Inherit
== decorationLineValue
->GetUnit()) {
4373 canStoreInRuleTree
= false;
4374 text
->mTextDecorationLine
= parentText
->mTextDecorationLine
;
4375 } else if (eCSSUnit_Initial
== decorationLineValue
->GetUnit() ||
4376 eCSSUnit_Unset
== decorationLineValue
->GetUnit()) {
4377 text
->mTextDecorationLine
= NS_STYLE_TEXT_DECORATION_LINE_NONE
;
4380 // text-decoration-color: color, string, enum, inherit, initial
4381 const nsCSSValue
* decorationColorValue
=
4382 aRuleData
->ValueForTextDecorationColor();
4383 nscolor decorationColor
;
4384 if (eCSSUnit_Inherit
== decorationColorValue
->GetUnit()) {
4385 canStoreInRuleTree
= false;
4386 if (parentContext
) {
4388 parentText
->GetDecorationColor(decorationColor
, isForeground
);
4390 text
->SetDecorationColor(parentContext
->StyleColor()->mColor
);
4392 text
->SetDecorationColor(decorationColor
);
4395 text
->SetDecorationColorToForeground();
4398 else if (eCSSUnit_EnumColor
== decorationColorValue
->GetUnit() &&
4399 decorationColorValue
->GetIntValue() == NS_COLOR_CURRENTCOLOR
) {
4400 text
->SetDecorationColorToForeground();
4402 else if (SetColor(*decorationColorValue
, 0, mPresContext
, aContext
,
4403 decorationColor
, canStoreInRuleTree
)) {
4404 text
->SetDecorationColor(decorationColor
);
4406 else if (eCSSUnit_Initial
== decorationColorValue
->GetUnit() ||
4407 eCSSUnit_Unset
== decorationColorValue
->GetUnit() ||
4408 eCSSUnit_Enumerated
== decorationColorValue
->GetUnit()) {
4409 NS_ABORT_IF_FALSE(eCSSUnit_Enumerated
!= decorationColorValue
->GetUnit() ||
4410 decorationColorValue
->GetIntValue() ==
4411 NS_STYLE_COLOR_MOZ_USE_TEXT_COLOR
,
4412 "unexpected enumerated value");
4413 text
->SetDecorationColorToForeground();
4416 // text-decoration-style: enum, inherit, initial
4417 const nsCSSValue
* decorationStyleValue
=
4418 aRuleData
->ValueForTextDecorationStyle();
4419 if (eCSSUnit_Enumerated
== decorationStyleValue
->GetUnit()) {
4420 text
->SetDecorationStyle(decorationStyleValue
->GetIntValue());
4421 } else if (eCSSUnit_Inherit
== decorationStyleValue
->GetUnit()) {
4422 text
->SetDecorationStyle(parentText
->GetDecorationStyle());
4423 canStoreInRuleTree
= false;
4424 } else if (eCSSUnit_Initial
== decorationStyleValue
->GetUnit() ||
4425 eCSSUnit_Unset
== decorationStyleValue
->GetUnit()) {
4426 text
->SetDecorationStyle(NS_STYLE_TEXT_DECORATION_STYLE_SOLID
);
4429 // text-overflow: enum, string, pair(enum|string), inherit, initial
4430 const nsCSSValue
* textOverflowValue
=
4431 aRuleData
->ValueForTextOverflow();
4432 if (eCSSUnit_Initial
== textOverflowValue
->GetUnit() ||
4433 eCSSUnit_Unset
== textOverflowValue
->GetUnit()) {
4434 text
->mTextOverflow
= nsStyleTextOverflow();
4435 } else if (eCSSUnit_Inherit
== textOverflowValue
->GetUnit()) {
4436 canStoreInRuleTree
= false;
4437 text
->mTextOverflow
= parentText
->mTextOverflow
;
4438 } else if (eCSSUnit_Enumerated
== textOverflowValue
->GetUnit()) {
4439 // A single enumerated value.
4440 SetDiscrete(*textOverflowValue
, text
->mTextOverflow
.mRight
.mType
,
4442 SETDSC_ENUMERATED
, parentText
->mTextOverflow
.mRight
.mType
,
4443 NS_STYLE_TEXT_OVERFLOW_CLIP
, 0, 0, 0, 0);
4444 text
->mTextOverflow
.mRight
.mString
.Truncate();
4445 text
->mTextOverflow
.mLeft
.mType
= NS_STYLE_TEXT_OVERFLOW_CLIP
;
4446 text
->mTextOverflow
.mLeft
.mString
.Truncate();
4447 text
->mTextOverflow
.mLogicalDirections
= true;
4448 } else if (eCSSUnit_String
== textOverflowValue
->GetUnit()) {
4449 // A single string value.
4450 text
->mTextOverflow
.mRight
.mType
= NS_STYLE_TEXT_OVERFLOW_STRING
;
4451 textOverflowValue
->GetStringValue(text
->mTextOverflow
.mRight
.mString
);
4452 text
->mTextOverflow
.mLeft
.mType
= NS_STYLE_TEXT_OVERFLOW_CLIP
;
4453 text
->mTextOverflow
.mLeft
.mString
.Truncate();
4454 text
->mTextOverflow
.mLogicalDirections
= true;
4455 } else if (eCSSUnit_Pair
== textOverflowValue
->GetUnit()) {
4456 // Two values were specified.
4457 text
->mTextOverflow
.mLogicalDirections
= false;
4458 const nsCSSValuePair
& textOverflowValuePair
=
4459 textOverflowValue
->GetPairValue();
4461 const nsCSSValue
*textOverflowLeftValue
= &textOverflowValuePair
.mXValue
;
4462 if (eCSSUnit_Enumerated
== textOverflowLeftValue
->GetUnit()) {
4463 SetDiscrete(*textOverflowLeftValue
, text
->mTextOverflow
.mLeft
.mType
,
4465 SETDSC_ENUMERATED
, parentText
->mTextOverflow
.mLeft
.mType
,
4466 NS_STYLE_TEXT_OVERFLOW_CLIP
, 0, 0, 0, 0);
4467 text
->mTextOverflow
.mLeft
.mString
.Truncate();
4468 } else if (eCSSUnit_String
== textOverflowLeftValue
->GetUnit()) {
4469 textOverflowLeftValue
->GetStringValue(text
->mTextOverflow
.mLeft
.mString
);
4470 text
->mTextOverflow
.mLeft
.mType
= NS_STYLE_TEXT_OVERFLOW_STRING
;
4473 const nsCSSValue
*textOverflowRightValue
= &textOverflowValuePair
.mYValue
;
4474 if (eCSSUnit_Enumerated
== textOverflowRightValue
->GetUnit()) {
4475 SetDiscrete(*textOverflowRightValue
, text
->mTextOverflow
.mRight
.mType
,
4477 SETDSC_ENUMERATED
, parentText
->mTextOverflow
.mRight
.mType
,
4478 NS_STYLE_TEXT_OVERFLOW_CLIP
, 0, 0, 0, 0);
4479 text
->mTextOverflow
.mRight
.mString
.Truncate();
4480 } else if (eCSSUnit_String
== textOverflowRightValue
->GetUnit()) {
4481 textOverflowRightValue
->GetStringValue(text
->mTextOverflow
.mRight
.mString
);
4482 text
->mTextOverflow
.mRight
.mType
= NS_STYLE_TEXT_OVERFLOW_STRING
;
4486 // unicode-bidi: enum, inherit, initial
4487 SetDiscrete(*aRuleData
->ValueForUnicodeBidi(), text
->mUnicodeBidi
, canStoreInRuleTree
,
4488 SETDSC_ENUMERATED
| SETDSC_UNSET_INITIAL
,
4489 parentText
->mUnicodeBidi
,
4490 NS_STYLE_UNICODE_BIDI_NORMAL
, 0, 0, 0, 0);
4492 COMPUTE_END_RESET(TextReset
, text
)
4496 nsRuleNode::ComputeUserInterfaceData(void* aStartStruct
,
4497 const nsRuleData
* aRuleData
,
4498 nsStyleContext
* aContext
,
4499 nsRuleNode
* aHighestNode
,
4500 const RuleDetail aRuleDetail
,
4501 const bool aCanStoreInRuleTree
)
4503 COMPUTE_START_INHERITED(UserInterface
, (), ui
, parentUI
)
4505 // cursor: enum, url, inherit
4506 const nsCSSValue
* cursorValue
= aRuleData
->ValueForCursor();
4507 nsCSSUnit cursorUnit
= cursorValue
->GetUnit();
4508 if (cursorUnit
!= eCSSUnit_Null
) {
4509 delete [] ui
->mCursorArray
;
4510 ui
->mCursorArray
= nullptr;
4511 ui
->mCursorArrayLength
= 0;
4513 if (cursorUnit
== eCSSUnit_Inherit
||
4514 cursorUnit
== eCSSUnit_Unset
) {
4515 canStoreInRuleTree
= false;
4516 ui
->mCursor
= parentUI
->mCursor
;
4517 ui
->CopyCursorArrayFrom(*parentUI
);
4519 else if (cursorUnit
== eCSSUnit_Initial
) {
4520 ui
->mCursor
= NS_STYLE_CURSOR_AUTO
;
4523 // The parser will never create a list that is *all* URL values --
4525 NS_ABORT_IF_FALSE(cursorUnit
== eCSSUnit_List
||
4526 cursorUnit
== eCSSUnit_ListDep
,
4527 nsPrintfCString("unrecognized cursor unit %d",
4529 const nsCSSValueList
* list
= cursorValue
->GetListValue();
4530 const nsCSSValueList
* list2
= list
;
4531 nsIDocument
* doc
= aContext
->PresContext()->Document();
4532 uint32_t arrayLength
= 0;
4533 for ( ; list
->mValue
.GetUnit() == eCSSUnit_Array
; list
= list
->mNext
)
4534 if (list
->mValue
.GetArrayValue()->Item(0).GetImageValue(doc
))
4537 if (arrayLength
!= 0) {
4538 ui
->mCursorArray
= new nsCursorImage
[arrayLength
];
4539 if (ui
->mCursorArray
) {
4540 ui
->mCursorArrayLength
= arrayLength
;
4542 for (nsCursorImage
*item
= ui
->mCursorArray
;
4543 list2
->mValue
.GetUnit() == eCSSUnit_Array
;
4544 list2
= list2
->mNext
) {
4545 nsCSSValue::Array
*arr
= list2
->mValue
.GetArrayValue();
4546 imgIRequest
*req
= arr
->Item(0).GetImageValue(doc
);
4548 item
->SetImage(req
);
4549 if (arr
->Item(1).GetUnit() != eCSSUnit_Null
) {
4550 item
->mHaveHotspot
= true;
4551 item
->mHotspotX
= arr
->Item(1).GetFloatValue(),
4552 item
->mHotspotY
= arr
->Item(2).GetFloatValue();
4560 NS_ASSERTION(list
, "Must have non-array value at the end");
4561 NS_ASSERTION(list
->mValue
.GetUnit() == eCSSUnit_Enumerated
,
4562 "Unexpected fallback value at end of cursor list");
4563 ui
->mCursor
= list
->mValue
.GetIntValue();
4567 // user-input: enum, inherit, initial
4568 SetDiscrete(*aRuleData
->ValueForUserInput(),
4569 ui
->mUserInput
, canStoreInRuleTree
,
4570 SETDSC_ENUMERATED
| SETDSC_UNSET_INHERIT
,
4571 parentUI
->mUserInput
,
4572 NS_STYLE_USER_INPUT_AUTO
, 0, 0, 0, 0);
4574 // user-modify: enum, inherit, initial
4575 SetDiscrete(*aRuleData
->ValueForUserModify(),
4576 ui
->mUserModify
, canStoreInRuleTree
,
4577 SETDSC_ENUMERATED
| SETDSC_UNSET_INHERIT
,
4578 parentUI
->mUserModify
,
4579 NS_STYLE_USER_MODIFY_READ_ONLY
,
4582 // user-focus: enum, inherit, initial
4583 SetDiscrete(*aRuleData
->ValueForUserFocus(),
4584 ui
->mUserFocus
, canStoreInRuleTree
,
4585 SETDSC_ENUMERATED
| SETDSC_UNSET_INHERIT
,
4586 parentUI
->mUserFocus
,
4587 NS_STYLE_USER_FOCUS_NONE
, 0, 0, 0, 0);
4589 COMPUTE_END_INHERITED(UserInterface
, ui
)
4593 nsRuleNode::ComputeUIResetData(void* aStartStruct
,
4594 const nsRuleData
* aRuleData
,
4595 nsStyleContext
* aContext
,
4596 nsRuleNode
* aHighestNode
,
4597 const RuleDetail aRuleDetail
,
4598 const bool aCanStoreInRuleTree
)
4600 COMPUTE_START_RESET(UIReset
, (), ui
, parentUI
)
4602 // user-select: enum, inherit, initial
4603 SetDiscrete(*aRuleData
->ValueForUserSelect(),
4604 ui
->mUserSelect
, canStoreInRuleTree
,
4605 SETDSC_ENUMERATED
| SETDSC_UNSET_INITIAL
,
4606 parentUI
->mUserSelect
,
4607 NS_STYLE_USER_SELECT_AUTO
, 0, 0, 0, 0);
4609 // ime-mode: enum, inherit, initial
4610 SetDiscrete(*aRuleData
->ValueForImeMode(),
4611 ui
->mIMEMode
, canStoreInRuleTree
,
4612 SETDSC_ENUMERATED
| SETDSC_UNSET_INITIAL
,
4614 NS_STYLE_IME_MODE_AUTO
, 0, 0, 0, 0);
4616 // force-broken-image-icons: integer, inherit, initial
4617 SetDiscrete(*aRuleData
->ValueForForceBrokenImageIcon(),
4618 ui
->mForceBrokenImageIcon
,
4620 SETDSC_INTEGER
| SETDSC_UNSET_INITIAL
,
4621 parentUI
->mForceBrokenImageIcon
,
4624 // -moz-window-shadow: enum, inherit, initial
4625 SetDiscrete(*aRuleData
->ValueForWindowShadow(),
4626 ui
->mWindowShadow
, canStoreInRuleTree
,
4627 SETDSC_ENUMERATED
| SETDSC_UNSET_INITIAL
,
4628 parentUI
->mWindowShadow
,
4629 NS_STYLE_WINDOW_SHADOW_DEFAULT
, 0, 0, 0, 0);
4631 COMPUTE_END_RESET(UIReset
, ui
)
4634 // Information about each transition or animation property that is
4636 struct TransitionPropInfo
{
4637 nsCSSProperty property
;
4638 // Location of the count of the property's computed value.
4639 uint32_t nsStyleDisplay::* sdCount
;
4642 // Each property's index in this array must match its index in the
4643 // mutable array |transitionPropData| below.
4644 static const TransitionPropInfo transitionPropInfo
[4] = {
4645 { eCSSProperty_transition_delay
,
4646 &nsStyleDisplay::mTransitionDelayCount
},
4647 { eCSSProperty_transition_duration
,
4648 &nsStyleDisplay::mTransitionDurationCount
},
4649 { eCSSProperty_transition_property
,
4650 &nsStyleDisplay::mTransitionPropertyCount
},
4651 { eCSSProperty_transition_timing_function
,
4652 &nsStyleDisplay::mTransitionTimingFunctionCount
},
4655 // Each property's index in this array must match its index in the
4656 // mutable array |animationPropData| below.
4657 static const TransitionPropInfo animationPropInfo
[8] = {
4658 { eCSSProperty_animation_delay
,
4659 &nsStyleDisplay::mAnimationDelayCount
},
4660 { eCSSProperty_animation_duration
,
4661 &nsStyleDisplay::mAnimationDurationCount
},
4662 { eCSSProperty_animation_name
,
4663 &nsStyleDisplay::mAnimationNameCount
},
4664 { eCSSProperty_animation_timing_function
,
4665 &nsStyleDisplay::mAnimationTimingFunctionCount
},
4666 { eCSSProperty_animation_direction
,
4667 &nsStyleDisplay::mAnimationDirectionCount
},
4668 { eCSSProperty_animation_fill_mode
,
4669 &nsStyleDisplay::mAnimationFillModeCount
},
4670 { eCSSProperty_animation_play_state
,
4671 &nsStyleDisplay::mAnimationPlayStateCount
},
4672 { eCSSProperty_animation_iteration_count
,
4673 &nsStyleDisplay::mAnimationIterationCountCount
},
4676 // Information about each transition or animation property that changes
4677 // during ComputeDisplayData.
4678 struct TransitionPropData
{
4679 const nsCSSValueList
*list
;
4685 CountTransitionProps(const TransitionPropInfo
* aInfo
,
4686 TransitionPropData
* aData
,
4688 nsStyleDisplay
* aDisplay
,
4689 const nsStyleDisplay
* aParentDisplay
,
4690 const nsRuleData
* aRuleData
,
4691 bool& aCanStoreInRuleTree
)
4693 // The four transition properties or eight animation properties are
4694 // stored in nsCSSDisplay in a single array for all properties. The
4695 // number of transitions is equal to the number of items in the
4696 // longest property's value. Properties that have fewer values than
4697 // the longest are filled in by repeating the list. However, this
4698 // repetition does not extend the computed value of that particular
4699 // property (for purposes of inheritance, or, in our code, for when
4700 // other properties are overridden by a more specific rule).
4702 // But actually, since the spec isn't clear yet, we'll fully compute
4703 // all of them (so we can switch easily later), but only care about
4704 // the ones up to the number of items for 'transition-property', per
4705 // http://lists.w3.org/Archives/Public/www-style/2009Aug/0109.html .
4707 // Transitions are difficult to handle correctly because of this. For
4708 // example, we need to handle scenarios such as:
4709 // * a more general rule specifies transition-property: a, b, c;
4710 // * a more specific rule overrides as transition-property: d;
4712 // If only the general rule applied, we would fill in the extra
4713 // properties (duration, delay, etc) with initial values to create 3
4714 // fully-specified transitions. But when the more specific rule
4715 // applies, we should only create a single transition. In order to do
4716 // this we need to remember which properties were explicitly specified
4717 // and which ones were just filled in with initial values to get a
4718 // fully-specified transition, which we do by remembering the number
4719 // of values for each property.
4721 uint32_t numTransitions
= 0;
4722 for (size_t i
= 0; i
< aLength
; ++i
) {
4723 const TransitionPropInfo
& info
= aInfo
[i
];
4724 TransitionPropData
& data
= aData
[i
];
4726 // cache whether any of the properties are specified as 'inherit' so
4727 // we can use it below
4729 const nsCSSValue
& value
= *aRuleData
->ValueFor(info
.property
);
4730 data
.unit
= value
.GetUnit();
4731 data
.list
= (value
.GetUnit() == eCSSUnit_List
||
4732 value
.GetUnit() == eCSSUnit_ListDep
)
4733 ? value
.GetListValue() : nullptr;
4735 // General algorithm to determine how many total transitions we need
4736 // to build. For each property:
4737 // - if there is no value specified in for the property in
4738 // displayData, use the values from the start struct, but only if
4739 // they were explicitly specified
4740 // - if there is a value specified for the property in displayData:
4741 // - if the value is 'inherit', count the number of values for
4742 // that property are specified by the parent, but only those
4743 // that were explicitly specified
4744 // - otherwise, count the number of values specified in displayData
4747 // calculate number of elements
4748 if (data
.unit
== eCSSUnit_Inherit
) {
4749 data
.num
= aParentDisplay
->*(info
.sdCount
);
4750 aCanStoreInRuleTree
= false;
4751 } else if (data
.list
) {
4752 data
.num
= ListLength(data
.list
);
4754 data
.num
= aDisplay
->*(info
.sdCount
);
4756 if (data
.num
> numTransitions
)
4757 numTransitions
= data
.num
;
4760 return numTransitions
;
4764 ComputeTimingFunction(const nsCSSValue
& aValue
, nsTimingFunction
& aResult
)
4766 switch (aValue
.GetUnit()) {
4767 case eCSSUnit_Enumerated
:
4768 aResult
= nsTimingFunction(aValue
.GetIntValue());
4770 case eCSSUnit_Cubic_Bezier
:
4772 nsCSSValue::Array
* array
= aValue
.GetArrayValue();
4773 NS_ASSERTION(array
&& array
->Count() == 4,
4774 "Need 4 control points");
4775 aResult
= nsTimingFunction(array
->Item(0).GetFloatValue(),
4776 array
->Item(1).GetFloatValue(),
4777 array
->Item(2).GetFloatValue(),
4778 array
->Item(3).GetFloatValue());
4781 case eCSSUnit_Steps
:
4783 nsCSSValue::Array
* array
= aValue
.GetArrayValue();
4784 NS_ASSERTION(array
&& array
->Count() == 2,
4786 NS_ASSERTION(array
->Item(0).GetUnit() == eCSSUnit_Integer
,
4787 "unexpected first value");
4788 NS_ASSERTION(array
->Item(1).GetUnit() == eCSSUnit_Enumerated
&&
4789 (array
->Item(1).GetIntValue() ==
4790 NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_START
||
4791 array
->Item(1).GetIntValue() ==
4792 NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END
),
4793 "unexpected second value");
4794 nsTimingFunction::Type type
=
4795 (array
->Item(1).GetIntValue() ==
4796 NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END
)
4797 ? nsTimingFunction::StepEnd
: nsTimingFunction::StepStart
;
4798 aResult
= nsTimingFunction(type
, array
->Item(0).GetIntValue());
4802 NS_NOTREACHED("Invalid transition property unit");
4807 nsRuleNode::ComputeDisplayData(void* aStartStruct
,
4808 const nsRuleData
* aRuleData
,
4809 nsStyleContext
* aContext
,
4810 nsRuleNode
* aHighestNode
,
4811 const RuleDetail aRuleDetail
,
4812 const bool aCanStoreInRuleTree
)
4814 COMPUTE_START_RESET(Display
, (), display
, parentDisplay
)
4816 // We may have ended up with aStartStruct's values of mDisplay and
4817 // mFloats, but those may not be correct if our style data overrides
4818 // its position or float properties. Reset to mOriginalDisplay and
4819 // mOriginalFloats; it if turns out we still need the display/floats
4820 // adjustments we'll do them below.
4821 display
->mDisplay
= display
->mOriginalDisplay
;
4822 display
->mFloats
= display
->mOriginalFloats
;
4824 // Each property's index in this array must match its index in the
4825 // const array |transitionPropInfo| above.
4826 TransitionPropData transitionPropData
[4];
4827 TransitionPropData
& delay
= transitionPropData
[0];
4828 TransitionPropData
& duration
= transitionPropData
[1];
4829 TransitionPropData
& property
= transitionPropData
[2];
4830 TransitionPropData
& timingFunction
= transitionPropData
[3];
4832 #define FOR_ALL_TRANSITION_PROPS(var_) \
4833 for (uint32_t var_ = 0; var_ < 4; ++var_)
4836 uint32_t numTransitions
=
4837 CountTransitionProps(transitionPropInfo
, transitionPropData
,
4838 ArrayLength(transitionPropData
),
4839 display
, parentDisplay
, aRuleData
,
4840 canStoreInRuleTree
);
4842 display
->mTransitions
.SetLength(numTransitions
);
4844 FOR_ALL_TRANSITION_PROPS(p
) {
4845 const TransitionPropInfo
& i
= transitionPropInfo
[p
];
4846 TransitionPropData
& d
= transitionPropData
[p
];
4848 display
->*(i
.sdCount
) = d
.num
;
4851 // Fill in the transitions we just allocated with the appropriate values.
4852 for (uint32_t i
= 0; i
< numTransitions
; ++i
) {
4853 StyleTransition
*transition
= &display
->mTransitions
[i
];
4855 if (i
>= delay
.num
) {
4856 transition
->SetDelay(display
->mTransitions
[i
% delay
.num
].GetDelay());
4857 } else if (delay
.unit
== eCSSUnit_Inherit
) {
4858 // FIXME (Bug 522599) (for all transition properties): write a test that
4859 // detects when this was wrong for i >= delay.num if parent had
4860 // count for this property not equal to length
4861 NS_ABORT_IF_FALSE(i
< parentDisplay
->mTransitionDelayCount
,
4862 "delay.num computed incorrectly");
4863 NS_ABORT_IF_FALSE(!canStoreInRuleTree
,
4864 "should have made canStoreInRuleTree false above");
4865 transition
->SetDelay(parentDisplay
->mTransitions
[i
].GetDelay());
4866 } else if (delay
.unit
== eCSSUnit_Initial
||
4867 delay
.unit
== eCSSUnit_Unset
) {
4868 transition
->SetDelay(0.0);
4869 } else if (delay
.list
) {
4870 switch (delay
.list
->mValue
.GetUnit()) {
4871 case eCSSUnit_Seconds
:
4872 transition
->SetDelay(PR_MSEC_PER_SEC
*
4873 delay
.list
->mValue
.GetFloatValue());
4875 case eCSSUnit_Milliseconds
:
4876 transition
->SetDelay(delay
.list
->mValue
.GetFloatValue());
4879 NS_NOTREACHED("Invalid delay unit");
4883 if (i
>= duration
.num
) {
4884 transition
->SetDuration(
4885 display
->mTransitions
[i
% duration
.num
].GetDuration());
4886 } else if (duration
.unit
== eCSSUnit_Inherit
) {
4887 NS_ABORT_IF_FALSE(i
< parentDisplay
->mTransitionDurationCount
,
4888 "duration.num computed incorrectly");
4889 NS_ABORT_IF_FALSE(!canStoreInRuleTree
,
4890 "should have made canStoreInRuleTree false above");
4891 transition
->SetDuration(parentDisplay
->mTransitions
[i
].GetDuration());
4892 } else if (duration
.unit
== eCSSUnit_Initial
||
4893 duration
.unit
== eCSSUnit_Unset
) {
4894 transition
->SetDuration(0.0);
4895 } else if (duration
.list
) {
4896 switch (duration
.list
->mValue
.GetUnit()) {
4897 case eCSSUnit_Seconds
:
4898 transition
->SetDuration(PR_MSEC_PER_SEC
*
4899 duration
.list
->mValue
.GetFloatValue());
4901 case eCSSUnit_Milliseconds
:
4902 transition
->SetDuration(duration
.list
->mValue
.GetFloatValue());
4905 NS_NOTREACHED("Invalid duration unit");
4909 if (i
>= property
.num
) {
4910 transition
->CopyPropertyFrom(display
->mTransitions
[i
% property
.num
]);
4911 } else if (property
.unit
== eCSSUnit_Inherit
) {
4912 NS_ABORT_IF_FALSE(i
< parentDisplay
->mTransitionPropertyCount
,
4913 "property.num computed incorrectly");
4914 NS_ABORT_IF_FALSE(!canStoreInRuleTree
,
4915 "should have made canStoreInRuleTree false above");
4916 transition
->CopyPropertyFrom(parentDisplay
->mTransitions
[i
]);
4917 } else if (property
.unit
== eCSSUnit_Initial
||
4918 property
.unit
== eCSSUnit_Unset
) {
4919 transition
->SetProperty(eCSSPropertyExtra_all_properties
);
4920 } else if (property
.unit
== eCSSUnit_None
) {
4921 transition
->SetProperty(eCSSPropertyExtra_no_properties
);
4922 } else if (property
.list
) {
4923 const nsCSSValue
&val
= property
.list
->mValue
;
4925 if (val
.GetUnit() == eCSSUnit_Ident
) {
4927 propertyStr(property
.list
->mValue
.GetStringBufferValue());
4928 nsCSSProperty prop
=
4929 nsCSSProps::LookupProperty(propertyStr
,
4930 nsCSSProps::eEnabledForAllContent
);
4931 if (prop
== eCSSProperty_UNKNOWN
) {
4932 transition
->SetUnknownProperty(propertyStr
);
4934 transition
->SetProperty(prop
);
4937 NS_ABORT_IF_FALSE(val
.GetUnit() == eCSSUnit_All
,
4938 nsPrintfCString("Invalid transition property unit %d",
4939 val
.GetUnit()).get());
4940 transition
->SetProperty(eCSSPropertyExtra_all_properties
);
4944 if (i
>= timingFunction
.num
) {
4945 transition
->SetTimingFunction(
4946 display
->mTransitions
[i
% timingFunction
.num
].GetTimingFunction());
4947 } else if (timingFunction
.unit
== eCSSUnit_Inherit
) {
4948 NS_ABORT_IF_FALSE(i
< parentDisplay
->mTransitionTimingFunctionCount
,
4949 "timingFunction.num computed incorrectly");
4950 NS_ABORT_IF_FALSE(!canStoreInRuleTree
,
4951 "should have made canStoreInRuleTree false above");
4952 transition
->SetTimingFunction(
4953 parentDisplay
->mTransitions
[i
].GetTimingFunction());
4954 } else if (timingFunction
.unit
== eCSSUnit_Initial
||
4955 timingFunction
.unit
== eCSSUnit_Unset
) {
4956 transition
->SetTimingFunction(
4957 nsTimingFunction(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE
));
4958 } else if (timingFunction
.list
) {
4959 ComputeTimingFunction(timingFunction
.list
->mValue
,
4960 transition
->TimingFunctionSlot());
4963 FOR_ALL_TRANSITION_PROPS(p
) {
4964 const TransitionPropInfo
& info
= transitionPropInfo
[p
];
4965 TransitionPropData
& d
= transitionPropData
[p
];
4967 // if we're at the end of the list, start at the beginning and repeat
4968 // until we're out of transitions to populate
4970 d
.list
= d
.list
->mNext
? d
.list
->mNext
:
4971 aRuleData
->ValueFor(info
.property
)->GetListValue();
4976 // Each property's index in this array must match its index in the
4977 // const array |animationPropInfo| above.
4978 TransitionPropData animationPropData
[8];
4979 TransitionPropData
& animDelay
= animationPropData
[0];
4980 TransitionPropData
& animDuration
= animationPropData
[1];
4981 TransitionPropData
& animName
= animationPropData
[2];
4982 TransitionPropData
& animTimingFunction
= animationPropData
[3];
4983 TransitionPropData
& animDirection
= animationPropData
[4];
4984 TransitionPropData
& animFillMode
= animationPropData
[5];
4985 TransitionPropData
& animPlayState
= animationPropData
[6];
4986 TransitionPropData
& animIterationCount
= animationPropData
[7];
4988 #define FOR_ALL_ANIMATION_PROPS(var_) \
4989 for (uint32_t var_ = 0; var_ < 8; ++var_)
4993 uint32_t numAnimations
=
4994 CountTransitionProps(animationPropInfo
, animationPropData
,
4995 ArrayLength(animationPropData
),
4996 display
, parentDisplay
, aRuleData
,
4997 canStoreInRuleTree
);
4999 display
->mAnimations
.SetLength(numAnimations
);
5001 FOR_ALL_ANIMATION_PROPS(p
) {
5002 const TransitionPropInfo
& i
= animationPropInfo
[p
];
5003 TransitionPropData
& d
= animationPropData
[p
];
5005 display
->*(i
.sdCount
) = d
.num
;
5008 // Fill in the animations we just allocated with the appropriate values.
5009 for (uint32_t i
= 0; i
< numAnimations
; ++i
) {
5010 StyleAnimation
*animation
= &display
->mAnimations
[i
];
5012 if (i
>= animDelay
.num
) {
5013 animation
->SetDelay(display
->mAnimations
[i
% animDelay
.num
].GetDelay());
5014 } else if (animDelay
.unit
== eCSSUnit_Inherit
) {
5015 // FIXME (Bug 522599) (for all animation properties): write a test that
5016 // detects when this was wrong for i >= animDelay.num if parent had
5017 // count for this property not equal to length
5018 NS_ABORT_IF_FALSE(i
< parentDisplay
->mAnimationDelayCount
,
5019 "animDelay.num computed incorrectly");
5020 NS_ABORT_IF_FALSE(!canStoreInRuleTree
,
5021 "should have made canStoreInRuleTree false above");
5022 animation
->SetDelay(parentDisplay
->mAnimations
[i
].GetDelay());
5023 } else if (animDelay
.unit
== eCSSUnit_Initial
||
5024 animDelay
.unit
== eCSSUnit_Unset
) {
5025 animation
->SetDelay(0.0);
5026 } else if (animDelay
.list
) {
5027 switch (animDelay
.list
->mValue
.GetUnit()) {
5028 case eCSSUnit_Seconds
:
5029 animation
->SetDelay(PR_MSEC_PER_SEC
*
5030 animDelay
.list
->mValue
.GetFloatValue());
5032 case eCSSUnit_Milliseconds
:
5033 animation
->SetDelay(animDelay
.list
->mValue
.GetFloatValue());
5036 NS_NOTREACHED("Invalid delay unit");
5040 if (i
>= animDuration
.num
) {
5041 animation
->SetDuration(
5042 display
->mAnimations
[i
% animDuration
.num
].GetDuration());
5043 } else if (animDuration
.unit
== eCSSUnit_Inherit
) {
5044 NS_ABORT_IF_FALSE(i
< parentDisplay
->mAnimationDurationCount
,
5045 "animDuration.num computed incorrectly");
5046 NS_ABORT_IF_FALSE(!canStoreInRuleTree
,
5047 "should have made canStoreInRuleTree false above");
5048 animation
->SetDuration(parentDisplay
->mAnimations
[i
].GetDuration());
5049 } else if (animDuration
.unit
== eCSSUnit_Initial
||
5050 animDuration
.unit
== eCSSUnit_Unset
) {
5051 animation
->SetDuration(0.0);
5052 } else if (animDuration
.list
) {
5053 switch (animDuration
.list
->mValue
.GetUnit()) {
5054 case eCSSUnit_Seconds
:
5055 animation
->SetDuration(PR_MSEC_PER_SEC
*
5056 animDuration
.list
->mValue
.GetFloatValue());
5058 case eCSSUnit_Milliseconds
:
5059 animation
->SetDuration(animDuration
.list
->mValue
.GetFloatValue());
5062 NS_NOTREACHED("Invalid duration unit");
5066 if (i
>= animName
.num
) {
5067 animation
->SetName(display
->mAnimations
[i
% animName
.num
].GetName());
5068 } else if (animName
.unit
== eCSSUnit_Inherit
) {
5069 NS_ABORT_IF_FALSE(i
< parentDisplay
->mAnimationNameCount
,
5070 "animName.num computed incorrectly");
5071 NS_ABORT_IF_FALSE(!canStoreInRuleTree
,
5072 "should have made canStoreInRuleTree false above");
5073 animation
->SetName(parentDisplay
->mAnimations
[i
].GetName());
5074 } else if (animName
.unit
== eCSSUnit_Initial
||
5075 animName
.unit
== eCSSUnit_Unset
) {
5076 animation
->SetName(EmptyString());
5077 } else if (animName
.list
) {
5078 switch (animName
.list
->mValue
.GetUnit()) {
5079 case eCSSUnit_Ident
: {
5081 nameStr(animName
.list
->mValue
.GetStringBufferValue());
5082 animation
->SetName(nameStr
);
5085 case eCSSUnit_None
: {
5086 animation
->SetName(EmptyString());
5090 NS_ABORT_IF_FALSE(false,
5091 nsPrintfCString("Invalid animation-name unit %d",
5092 animName
.list
->mValue
.GetUnit()).get());
5096 if (i
>= animTimingFunction
.num
) {
5097 animation
->SetTimingFunction(
5098 display
->mAnimations
[i
% animTimingFunction
.num
].GetTimingFunction());
5099 } else if (animTimingFunction
.unit
== eCSSUnit_Inherit
) {
5100 NS_ABORT_IF_FALSE(i
< parentDisplay
->mAnimationTimingFunctionCount
,
5101 "animTimingFunction.num computed incorrectly");
5102 NS_ABORT_IF_FALSE(!canStoreInRuleTree
,
5103 "should have made canStoreInRuleTree false above");
5104 animation
->SetTimingFunction(
5105 parentDisplay
->mAnimations
[i
].GetTimingFunction());
5106 } else if (animTimingFunction
.unit
== eCSSUnit_Initial
||
5107 animTimingFunction
.unit
== eCSSUnit_Unset
) {
5108 animation
->SetTimingFunction(
5109 nsTimingFunction(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE
));
5110 } else if (animTimingFunction
.list
) {
5111 ComputeTimingFunction(animTimingFunction
.list
->mValue
,
5112 animation
->TimingFunctionSlot());
5115 if (i
>= animDirection
.num
) {
5116 animation
->SetDirection(display
->mAnimations
[i
% animDirection
.num
].GetDirection());
5117 } else if (animDirection
.unit
== eCSSUnit_Inherit
) {
5118 NS_ABORT_IF_FALSE(i
< parentDisplay
->mAnimationDirectionCount
,
5119 "animDirection.num computed incorrectly");
5120 NS_ABORT_IF_FALSE(!canStoreInRuleTree
,
5121 "should have made canStoreInRuleTree false above");
5122 animation
->SetDirection(parentDisplay
->mAnimations
[i
].GetDirection());
5123 } else if (animDirection
.unit
== eCSSUnit_Initial
||
5124 animDirection
.unit
== eCSSUnit_Unset
) {
5125 animation
->SetDirection(NS_STYLE_ANIMATION_DIRECTION_NORMAL
);
5126 } else if (animDirection
.list
) {
5127 NS_ABORT_IF_FALSE(animDirection
.list
->mValue
.GetUnit() == eCSSUnit_Enumerated
,
5128 nsPrintfCString("Invalid animation-direction unit %d",
5129 animDirection
.list
->mValue
.GetUnit()).get());
5131 animation
->SetDirection(animDirection
.list
->mValue
.GetIntValue());
5134 if (i
>= animFillMode
.num
) {
5135 animation
->SetFillMode(display
->mAnimations
[i
% animFillMode
.num
].GetFillMode());
5136 } else if (animFillMode
.unit
== eCSSUnit_Inherit
) {
5137 NS_ABORT_IF_FALSE(i
< parentDisplay
->mAnimationFillModeCount
,
5138 "animFillMode.num computed incorrectly");
5139 NS_ABORT_IF_FALSE(!canStoreInRuleTree
,
5140 "should have made canStoreInRuleTree false above");
5141 animation
->SetFillMode(parentDisplay
->mAnimations
[i
].GetFillMode());
5142 } else if (animFillMode
.unit
== eCSSUnit_Initial
||
5143 animFillMode
.unit
== eCSSUnit_Unset
) {
5144 animation
->SetFillMode(NS_STYLE_ANIMATION_FILL_MODE_NONE
);
5145 } else if (animFillMode
.list
) {
5146 NS_ABORT_IF_FALSE(animFillMode
.list
->mValue
.GetUnit() == eCSSUnit_Enumerated
,
5147 nsPrintfCString("Invalid animation-fill-mode unit %d",
5148 animFillMode
.list
->mValue
.GetUnit()).get());
5150 animation
->SetFillMode(animFillMode
.list
->mValue
.GetIntValue());
5153 if (i
>= animPlayState
.num
) {
5154 animation
->SetPlayState(display
->mAnimations
[i
% animPlayState
.num
].GetPlayState());
5155 } else if (animPlayState
.unit
== eCSSUnit_Inherit
) {
5156 NS_ABORT_IF_FALSE(i
< parentDisplay
->mAnimationPlayStateCount
,
5157 "animPlayState.num computed incorrectly");
5158 NS_ABORT_IF_FALSE(!canStoreInRuleTree
,
5159 "should have made canStoreInRuleTree false above");
5160 animation
->SetPlayState(parentDisplay
->mAnimations
[i
].GetPlayState());
5161 } else if (animPlayState
.unit
== eCSSUnit_Initial
||
5162 animPlayState
.unit
== eCSSUnit_Unset
) {
5163 animation
->SetPlayState(NS_STYLE_ANIMATION_PLAY_STATE_RUNNING
);
5164 } else if (animPlayState
.list
) {
5165 NS_ABORT_IF_FALSE(animPlayState
.list
->mValue
.GetUnit() == eCSSUnit_Enumerated
,
5166 nsPrintfCString("Invalid animation-play-state unit %d",
5167 animPlayState
.list
->mValue
.GetUnit()).get());
5169 animation
->SetPlayState(animPlayState
.list
->mValue
.GetIntValue());
5172 if (i
>= animIterationCount
.num
) {
5173 animation
->SetIterationCount(display
->mAnimations
[i
% animIterationCount
.num
].GetIterationCount());
5174 } else if (animIterationCount
.unit
== eCSSUnit_Inherit
) {
5175 NS_ABORT_IF_FALSE(i
< parentDisplay
->mAnimationIterationCountCount
,
5176 "animIterationCount.num computed incorrectly");
5177 NS_ABORT_IF_FALSE(!canStoreInRuleTree
,
5178 "should have made canStoreInRuleTree false above");
5179 animation
->SetIterationCount(parentDisplay
->mAnimations
[i
].GetIterationCount());
5180 } else if (animIterationCount
.unit
== eCSSUnit_Initial
||
5181 animIterationCount
.unit
== eCSSUnit_Unset
) {
5182 animation
->SetIterationCount(1.0f
);
5183 } else if (animIterationCount
.list
) {
5184 switch (animIterationCount
.list
->mValue
.GetUnit()) {
5185 case eCSSUnit_Enumerated
:
5186 NS_ABORT_IF_FALSE(animIterationCount
.list
->mValue
.GetIntValue() ==
5187 NS_STYLE_ANIMATION_ITERATION_COUNT_INFINITE
,
5188 "unexpected value");
5189 animation
->SetIterationCount(NS_IEEEPositiveInfinity());
5191 case eCSSUnit_Number
:
5192 animation
->SetIterationCount(
5193 animIterationCount
.list
->mValue
.GetFloatValue());
5196 NS_ABORT_IF_FALSE(false,
5197 "unexpected animation-iteration-count unit");
5201 FOR_ALL_ANIMATION_PROPS(p
) {
5202 const TransitionPropInfo
& info
= animationPropInfo
[p
];
5203 TransitionPropData
& d
= animationPropData
[p
];
5205 // if we're at the end of the list, start at the beginning and repeat
5206 // until we're out of animations to populate
5208 d
.list
= d
.list
->mNext
? d
.list
->mNext
:
5209 aRuleData
->ValueFor(info
.property
)->GetListValue();
5214 // opacity: factor, inherit, initial
5215 SetFactor(*aRuleData
->ValueForOpacity(), display
->mOpacity
, canStoreInRuleTree
,
5216 parentDisplay
->mOpacity
, 1.0f
,
5217 SETFCT_OPACITY
| SETFCT_UNSET_INITIAL
);
5219 // display: enum, inherit, initial
5220 SetDiscrete(*aRuleData
->ValueForDisplay(), display
->mDisplay
, canStoreInRuleTree
,
5221 SETDSC_ENUMERATED
| SETDSC_UNSET_INITIAL
,
5222 parentDisplay
->mDisplay
,
5223 NS_STYLE_DISPLAY_INLINE
, 0, 0, 0, 0);
5225 // mix-blend-mode: enum, inherit, initial
5226 SetDiscrete(*aRuleData
->ValueForMixBlendMode(), display
->mMixBlendMode
,
5228 SETDSC_ENUMERATED
| SETDSC_UNSET_INITIAL
,
5229 parentDisplay
->mMixBlendMode
, NS_STYLE_BLEND_NORMAL
,
5232 // Backup original display value for calculation of a hypothetical
5233 // box (CSS2 10.6.4/10.6.5), in addition to getting our style data right later.
5234 // See nsHTMLReflowState::CalculateHypotheticalBox
5235 display
->mOriginalDisplay
= display
->mDisplay
;
5237 // appearance: enum, inherit, initial
5238 SetDiscrete(*aRuleData
->ValueForAppearance(),
5239 display
->mAppearance
, canStoreInRuleTree
,
5240 SETDSC_ENUMERATED
| SETDSC_UNSET_INITIAL
,
5241 parentDisplay
->mAppearance
,
5242 NS_THEME_NONE
, 0, 0, 0, 0);
5244 // binding: url, none, inherit
5245 const nsCSSValue
* bindingValue
= aRuleData
->ValueForBinding();
5246 if (eCSSUnit_URL
== bindingValue
->GetUnit()) {
5247 mozilla::css::URLValue
* url
= bindingValue
->GetURLStructValue();
5248 NS_ASSERTION(url
, "What's going on here?");
5250 if (MOZ_LIKELY(url
->GetURI())) {
5251 display
->mBinding
= url
;
5253 display
->mBinding
= nullptr;
5256 else if (eCSSUnit_None
== bindingValue
->GetUnit() ||
5257 eCSSUnit_Initial
== bindingValue
->GetUnit() ||
5258 eCSSUnit_Unset
== bindingValue
->GetUnit()) {
5259 display
->mBinding
= nullptr;
5261 else if (eCSSUnit_Inherit
== bindingValue
->GetUnit()) {
5262 canStoreInRuleTree
= false;
5263 display
->mBinding
= parentDisplay
->mBinding
;
5266 // position: enum, inherit, initial
5267 SetDiscrete(*aRuleData
->ValueForPosition(), display
->mPosition
, canStoreInRuleTree
,
5268 SETDSC_ENUMERATED
| SETDSC_UNSET_INITIAL
,
5269 parentDisplay
->mPosition
,
5270 NS_STYLE_POSITION_STATIC
, 0, 0, 0, 0);
5272 // clear: enum, inherit, initial
5273 SetDiscrete(*aRuleData
->ValueForClear(), display
->mBreakType
, canStoreInRuleTree
,
5274 SETDSC_ENUMERATED
| SETDSC_UNSET_INITIAL
,
5275 parentDisplay
->mBreakType
,
5276 NS_STYLE_CLEAR_NONE
, 0, 0, 0, 0);
5278 // temp fix for bug 24000
5279 // Map 'auto' and 'avoid' to false, and 'always', 'left', and
5281 // "A conforming user agent may interpret the values 'left' and
5282 // 'right' as 'always'." - CSS2.1, section 13.3.1
5283 const nsCSSValue
* breakBeforeValue
= aRuleData
->ValueForPageBreakBefore();
5284 if (eCSSUnit_Enumerated
== breakBeforeValue
->GetUnit()) {
5285 display
->mBreakBefore
=
5286 (NS_STYLE_PAGE_BREAK_AVOID
!= breakBeforeValue
->GetIntValue() &&
5287 NS_STYLE_PAGE_BREAK_AUTO
!= breakBeforeValue
->GetIntValue());
5289 else if (eCSSUnit_Initial
== breakBeforeValue
->GetUnit() ||
5290 eCSSUnit_Unset
== breakBeforeValue
->GetUnit()) {
5291 display
->mBreakBefore
= false;
5293 else if (eCSSUnit_Inherit
== breakBeforeValue
->GetUnit()) {
5294 canStoreInRuleTree
= false;
5295 display
->mBreakBefore
= parentDisplay
->mBreakBefore
;
5298 const nsCSSValue
* breakAfterValue
= aRuleData
->ValueForPageBreakAfter();
5299 if (eCSSUnit_Enumerated
== breakAfterValue
->GetUnit()) {
5300 display
->mBreakAfter
=
5301 (NS_STYLE_PAGE_BREAK_AVOID
!= breakAfterValue
->GetIntValue() &&
5302 NS_STYLE_PAGE_BREAK_AUTO
!= breakAfterValue
->GetIntValue());
5304 else if (eCSSUnit_Initial
== breakAfterValue
->GetUnit() ||
5305 eCSSUnit_Unset
== breakAfterValue
->GetUnit()) {
5306 display
->mBreakAfter
= false;
5308 else if (eCSSUnit_Inherit
== breakAfterValue
->GetUnit()) {
5309 canStoreInRuleTree
= false;
5310 display
->mBreakAfter
= parentDisplay
->mBreakAfter
;
5314 // page-break-inside: enum, inherit, initial
5315 SetDiscrete(*aRuleData
->ValueForPageBreakInside(),
5316 display
->mBreakInside
, canStoreInRuleTree
,
5317 SETDSC_ENUMERATED
| SETDSC_UNSET_INITIAL
,
5318 parentDisplay
->mBreakInside
,
5319 NS_STYLE_PAGE_BREAK_AUTO
, 0, 0, 0, 0);
5321 // touch-action: none, auto, enum, inherit, initial
5322 SetDiscrete(*aRuleData
->ValueForTouchAction(), display
->mTouchAction
,
5324 SETDSC_ENUMERATED
| SETDSC_AUTO
| SETDSC_NONE
|
5325 SETDSC_UNSET_INITIAL
,
5326 parentDisplay
->mTouchAction
,
5327 NS_STYLE_TOUCH_ACTION_AUTO
,
5328 NS_STYLE_TOUCH_ACTION_AUTO
,
5329 NS_STYLE_TOUCH_ACTION_NONE
, 0, 0);
5331 // float: enum, inherit, initial
5332 SetDiscrete(*aRuleData
->ValueForFloat(),
5333 display
->mFloats
, canStoreInRuleTree
,
5334 SETDSC_ENUMERATED
| SETDSC_UNSET_INITIAL
,
5335 parentDisplay
->mFloats
,
5336 NS_STYLE_FLOAT_NONE
, 0, 0, 0, 0);
5337 // Save mFloats in mOriginalFloats in case we need it later
5338 display
->mOriginalFloats
= display
->mFloats
;
5340 // overflow-x: enum, inherit, initial
5341 SetDiscrete(*aRuleData
->ValueForOverflowX(),
5342 display
->mOverflowX
, canStoreInRuleTree
,
5343 SETDSC_ENUMERATED
| SETDSC_UNSET_INITIAL
,
5344 parentDisplay
->mOverflowX
,
5345 NS_STYLE_OVERFLOW_VISIBLE
, 0, 0, 0, 0);
5347 // overflow-y: enum, inherit, initial
5348 SetDiscrete(*aRuleData
->ValueForOverflowY(),
5349 display
->mOverflowY
, canStoreInRuleTree
,
5350 SETDSC_ENUMERATED
| SETDSC_UNSET_INITIAL
,
5351 parentDisplay
->mOverflowY
,
5352 NS_STYLE_OVERFLOW_VISIBLE
, 0, 0, 0, 0);
5354 // CSS3 overflow-x and overflow-y require some fixup as well in some
5355 // cases. NS_STYLE_OVERFLOW_VISIBLE and NS_STYLE_OVERFLOW_CLIP are
5356 // meaningful only when used in both dimensions.
5357 if (display
->mOverflowX
!= display
->mOverflowY
&&
5358 (display
->mOverflowX
== NS_STYLE_OVERFLOW_VISIBLE
||
5359 display
->mOverflowX
== NS_STYLE_OVERFLOW_CLIP
||
5360 display
->mOverflowY
== NS_STYLE_OVERFLOW_VISIBLE
||
5361 display
->mOverflowY
== NS_STYLE_OVERFLOW_CLIP
)) {
5362 // We can't store in the rule tree since a more specific rule might
5363 // change these conditions.
5364 canStoreInRuleTree
= false;
5366 // NS_STYLE_OVERFLOW_CLIP is a deprecated value, so if it's specified
5367 // in only one dimension, convert it to NS_STYLE_OVERFLOW_HIDDEN.
5368 if (display
->mOverflowX
== NS_STYLE_OVERFLOW_CLIP
)
5369 display
->mOverflowX
= NS_STYLE_OVERFLOW_HIDDEN
;
5370 if (display
->mOverflowY
== NS_STYLE_OVERFLOW_CLIP
)
5371 display
->mOverflowY
= NS_STYLE_OVERFLOW_HIDDEN
;
5373 // If 'visible' is specified but doesn't match the other dimension, it
5374 // turns into 'auto'.
5375 if (display
->mOverflowX
== NS_STYLE_OVERFLOW_VISIBLE
)
5376 display
->mOverflowX
= NS_STYLE_OVERFLOW_AUTO
;
5377 if (display
->mOverflowY
== NS_STYLE_OVERFLOW_VISIBLE
)
5378 display
->mOverflowY
= NS_STYLE_OVERFLOW_AUTO
;
5381 SetDiscrete(*aRuleData
->ValueForOverflowClipBox(), display
->mOverflowClipBox
,
5383 SETDSC_ENUMERATED
| SETDSC_UNSET_INITIAL
,
5384 parentDisplay
->mOverflowClipBox
,
5385 NS_STYLE_OVERFLOW_CLIP_BOX_PADDING_BOX
, 0, 0, 0, 0);
5387 SetDiscrete(*aRuleData
->ValueForResize(), display
->mResize
, canStoreInRuleTree
,
5388 SETDSC_ENUMERATED
| SETDSC_UNSET_INITIAL
,
5389 parentDisplay
->mResize
,
5390 NS_STYLE_RESIZE_NONE
, 0, 0, 0, 0);
5392 // clip property: length, auto, inherit
5393 const nsCSSValue
* clipValue
= aRuleData
->ValueForClip();
5394 switch (clipValue
->GetUnit()) {
5395 case eCSSUnit_Inherit
:
5396 canStoreInRuleTree
= false;
5397 display
->mClipFlags
= parentDisplay
->mClipFlags
;
5398 display
->mClip
= parentDisplay
->mClip
;
5401 case eCSSUnit_Initial
:
5402 case eCSSUnit_Unset
:
5404 display
->mClipFlags
= NS_STYLE_CLIP_AUTO
;
5405 display
->mClip
.SetRect(0,0,0,0);
5411 case eCSSUnit_Rect
: {
5412 const nsCSSRect
& clipRect
= clipValue
->GetRectValue();
5414 display
->mClipFlags
= NS_STYLE_CLIP_RECT
;
5416 if (clipRect
.mTop
.GetUnit() == eCSSUnit_Auto
) {
5417 display
->mClip
.y
= 0;
5418 display
->mClipFlags
|= NS_STYLE_CLIP_TOP_AUTO
;
5420 else if (clipRect
.mTop
.IsLengthUnit()) {
5421 display
->mClip
.y
= CalcLength(clipRect
.mTop
, aContext
,
5422 mPresContext
, canStoreInRuleTree
);
5425 if (clipRect
.mBottom
.GetUnit() == eCSSUnit_Auto
) {
5426 // Setting to NS_MAXSIZE for the 'auto' case ensures that
5427 // the clip rect is nonempty. It is important that mClip be
5428 // nonempty if the actual clip rect could be nonempty.
5429 display
->mClip
.height
= NS_MAXSIZE
;
5430 display
->mClipFlags
|= NS_STYLE_CLIP_BOTTOM_AUTO
;
5432 else if (clipRect
.mBottom
.IsLengthUnit()) {
5433 display
->mClip
.height
= CalcLength(clipRect
.mBottom
, aContext
,
5434 mPresContext
, canStoreInRuleTree
) -
5438 if (clipRect
.mLeft
.GetUnit() == eCSSUnit_Auto
) {
5439 display
->mClip
.x
= 0;
5440 display
->mClipFlags
|= NS_STYLE_CLIP_LEFT_AUTO
;
5442 else if (clipRect
.mLeft
.IsLengthUnit()) {
5443 display
->mClip
.x
= CalcLength(clipRect
.mLeft
, aContext
,
5444 mPresContext
, canStoreInRuleTree
);
5447 if (clipRect
.mRight
.GetUnit() == eCSSUnit_Auto
) {
5448 // Setting to NS_MAXSIZE for the 'auto' case ensures that
5449 // the clip rect is nonempty. It is important that mClip be
5450 // nonempty if the actual clip rect could be nonempty.
5451 display
->mClip
.width
= NS_MAXSIZE
;
5452 display
->mClipFlags
|= NS_STYLE_CLIP_RIGHT_AUTO
;
5454 else if (clipRect
.mRight
.IsLengthUnit()) {
5455 display
->mClip
.width
= CalcLength(clipRect
.mRight
, aContext
,
5456 mPresContext
, canStoreInRuleTree
) -
5463 NS_ABORT_IF_FALSE(false, "unrecognized clip unit");
5466 if (display
->mDisplay
!= NS_STYLE_DISPLAY_NONE
) {
5467 // CSS2 9.7 specifies display type corrections dealing with 'float'
5468 // and 'position'. Since generated content can't be floated or
5469 // positioned, we can deal with it here.
5471 if (nsCSSPseudoElements::firstLetter
== aContext
->GetPseudo()) {
5472 // a non-floating first-letter must be inline
5473 // XXX this fix can go away once bug 103189 is fixed correctly
5474 // Note that we reset mOriginalDisplay to enforce the invariant that it equals mDisplay if we're not positioned or floating.
5475 display
->mOriginalDisplay
= display
->mDisplay
= NS_STYLE_DISPLAY_INLINE
;
5477 // We can't cache the data in the rule tree since if a more specific
5478 // rule has 'float: left' we'll end up with the wrong 'display'
5480 canStoreInRuleTree
= false;
5483 if (display
->IsAbsolutelyPositionedStyle()) {
5484 // 1) if position is 'absolute' or 'fixed' then display must be
5485 // block-level and float must be 'none'
5486 EnsureBlockDisplay(display
->mDisplay
);
5487 display
->mFloats
= NS_STYLE_FLOAT_NONE
;
5489 // Note that it's OK to cache this struct in the ruletree
5490 // because it's fine as-is for any style context that points to
5491 // it directly, and any use of it as aStartStruct (e.g. if a
5492 // more specific rule sets "position: static") will use
5493 // mOriginalDisplay and mOriginalFloats, which we have carefully
5495 } else if (display
->mFloats
!= NS_STYLE_FLOAT_NONE
) {
5496 // 2) if float is not none, and display is not none, then we must
5497 // set a block-level 'display' type per CSS2.1 section 9.7.
5498 EnsureBlockDisplay(display
->mDisplay
);
5500 // Note that it's OK to cache this struct in the ruletree
5501 // because it's fine as-is for any style context that points to
5502 // it directly, and any use of it as aStartStruct (e.g. if a
5503 // more specific rule sets "float: none") will use
5504 // mOriginalDisplay, which we have carefully not changed.
5509 /* Convert the nsCSSValueList into an nsTArray<nsTransformFunction *>. */
5510 const nsCSSValue
* transformValue
= aRuleData
->ValueForTransform();
5511 switch (transformValue
->GetUnit()) {
5515 case eCSSUnit_Initial
:
5516 case eCSSUnit_Unset
:
5518 display
->mSpecifiedTransform
= nullptr;
5521 case eCSSUnit_Inherit
:
5522 display
->mSpecifiedTransform
= parentDisplay
->mSpecifiedTransform
;
5523 canStoreInRuleTree
= false;
5526 case eCSSUnit_SharedList
: {
5527 nsCSSValueSharedList
* list
= transformValue
->GetSharedListValue();
5528 nsCSSValueList
* head
= list
->mHead
;
5529 MOZ_ASSERT(head
, "transform list must have at least one item");
5530 // can get a _None in here from transform animation
5531 if (head
->mValue
.GetUnit() == eCSSUnit_None
) {
5532 NS_ABORT_IF_FALSE(head
->mNext
== nullptr, "none must be alone");
5533 display
->mSpecifiedTransform
= nullptr;
5535 display
->mSpecifiedTransform
= list
;
5541 NS_ABORT_IF_FALSE(false, "unrecognized transform unit");
5544 /* Convert the nsCSSValueList into a will-change bitfield for fast lookup */
5545 const nsCSSValue
* willChangeValue
= aRuleData
->ValueForWillChange();
5546 switch (willChangeValue
->GetUnit()) {
5551 case eCSSUnit_ListDep
: {
5552 display
->mWillChange
.Clear();
5553 display
->mWillChangeBitField
= 0;
5554 for (const nsCSSValueList
* item
= willChangeValue
->GetListValue();
5555 item
; item
= item
->mNext
)
5557 if (item
->mValue
.UnitHasStringValue()) {
5558 nsAutoString buffer
;
5559 item
->mValue
.GetStringValue(buffer
);
5560 display
->mWillChange
.AppendElement(buffer
);
5562 if (buffer
.EqualsLiteral("transform")) {
5563 display
->mWillChangeBitField
|= NS_STYLE_WILL_CHANGE_TRANSFORM
;
5565 if (buffer
.EqualsLiteral("opacity")) {
5566 display
->mWillChangeBitField
|= NS_STYLE_WILL_CHANGE_OPACITY
;
5568 if (buffer
.EqualsLiteral("scroll-position")) {
5569 display
->mWillChangeBitField
|= NS_STYLE_WILL_CHANGE_SCROLL
;
5572 nsCSSProperty prop
=
5573 nsCSSProps::LookupProperty(buffer
,
5574 nsCSSProps::eEnabledForAllContent
);
5575 if (prop
!= eCSSProperty_UNKNOWN
&&
5576 nsCSSProps::PropHasFlags(prop
,
5577 CSS_PROPERTY_CREATES_STACKING_CONTEXT
))
5579 display
->mWillChangeBitField
|= NS_STYLE_WILL_CHANGE_STACKING_CONTEXT
;
5586 case eCSSUnit_Inherit
:
5587 display
->mWillChange
= parentDisplay
->mWillChange
;
5588 display
->mWillChangeBitField
= parentDisplay
->mWillChangeBitField
;
5589 canStoreInRuleTree
= false;
5592 case eCSSUnit_Initial
:
5593 case eCSSUnit_Unset
:
5595 display
->mWillChange
.Clear();
5596 display
->mWillChangeBitField
= 0;
5600 MOZ_ASSERT(false, "unrecognized will-change unit");
5603 /* Convert -moz-transform-origin. */
5604 const nsCSSValue
* transformOriginValue
=
5605 aRuleData
->ValueForTransformOrigin();
5606 if (transformOriginValue
->GetUnit() != eCSSUnit_Null
) {
5607 const nsCSSValue
& valX
=
5608 transformOriginValue
->GetUnit() == eCSSUnit_Triplet
?
5609 transformOriginValue
->GetTripletValue().mXValue
: *transformOriginValue
;
5610 const nsCSSValue
& valY
=
5611 transformOriginValue
->GetUnit() == eCSSUnit_Triplet
?
5612 transformOriginValue
->GetTripletValue().mYValue
: *transformOriginValue
;
5613 const nsCSSValue
& valZ
=
5614 transformOriginValue
->GetUnit() == eCSSUnit_Triplet
?
5615 transformOriginValue
->GetTripletValue().mZValue
: *transformOriginValue
;
5617 mozilla::DebugOnly
<bool> cX
=
5618 SetCoord(valX
, display
->mTransformOrigin
[0],
5619 parentDisplay
->mTransformOrigin
[0],
5620 SETCOORD_LPH
| SETCOORD_INITIAL_HALF
|
5621 SETCOORD_BOX_POSITION
| SETCOORD_STORE_CALC
|
5622 SETCOORD_UNSET_INITIAL
,
5623 aContext
, mPresContext
, canStoreInRuleTree
);
5625 mozilla::DebugOnly
<bool> cY
=
5626 SetCoord(valY
, display
->mTransformOrigin
[1],
5627 parentDisplay
->mTransformOrigin
[1],
5628 SETCOORD_LPH
| SETCOORD_INITIAL_HALF
|
5629 SETCOORD_BOX_POSITION
| SETCOORD_STORE_CALC
|
5630 SETCOORD_UNSET_INITIAL
,
5631 aContext
, mPresContext
, canStoreInRuleTree
);
5633 if (valZ
.GetUnit() == eCSSUnit_Null
) {
5634 // Null for the z component means a 0 translation, not
5635 // unspecified, as we have already checked the triplet
5637 display
->mTransformOrigin
[2].SetCoordValue(0);
5639 mozilla::DebugOnly
<bool> cZ
=
5640 SetCoord(valZ
, display
->mTransformOrigin
[2],
5641 parentDisplay
->mTransformOrigin
[2],
5642 SETCOORD_LH
| SETCOORD_INITIAL_ZERO
| SETCOORD_STORE_CALC
|
5643 SETCOORD_UNSET_INITIAL
,
5644 aContext
, mPresContext
, canStoreInRuleTree
);
5645 NS_ABORT_IF_FALSE(cY
== cZ
, "changed one but not the other");
5647 NS_ABORT_IF_FALSE(cX
== cY
, "changed one but not the other");
5648 NS_ASSERTION(cX
, "Malformed -moz-transform-origin parse!");
5651 const nsCSSValue
* perspectiveOriginValue
=
5652 aRuleData
->ValueForPerspectiveOrigin();
5653 if (perspectiveOriginValue
->GetUnit() != eCSSUnit_Null
) {
5654 mozilla::DebugOnly
<bool> result
=
5655 SetPairCoords(*perspectiveOriginValue
,
5656 display
->mPerspectiveOrigin
[0],
5657 display
->mPerspectiveOrigin
[1],
5658 parentDisplay
->mPerspectiveOrigin
[0],
5659 parentDisplay
->mPerspectiveOrigin
[1],
5660 SETCOORD_LPH
| SETCOORD_INITIAL_HALF
|
5661 SETCOORD_BOX_POSITION
| SETCOORD_STORE_CALC
|
5662 SETCOORD_UNSET_INITIAL
,
5663 aContext
, mPresContext
, canStoreInRuleTree
);
5664 NS_ASSERTION(result
, "Malformed -moz-perspective-origin parse!");
5667 SetCoord(*aRuleData
->ValueForPerspective(),
5668 display
->mChildPerspective
, parentDisplay
->mChildPerspective
,
5669 SETCOORD_LAH
| SETCOORD_INITIAL_NONE
| SETCOORD_NONE
|
5670 SETCOORD_UNSET_INITIAL
,
5671 aContext
, mPresContext
, canStoreInRuleTree
);
5673 SetDiscrete(*aRuleData
->ValueForBackfaceVisibility(),
5674 display
->mBackfaceVisibility
, canStoreInRuleTree
,
5675 SETDSC_ENUMERATED
| SETDSC_UNSET_INITIAL
,
5676 parentDisplay
->mBackfaceVisibility
,
5677 NS_STYLE_BACKFACE_VISIBILITY_VISIBLE
, 0, 0, 0, 0);
5679 // transform-style: enum, inherit, initial
5680 SetDiscrete(*aRuleData
->ValueForTransformStyle(),
5681 display
->mTransformStyle
, canStoreInRuleTree
,
5682 SETDSC_ENUMERATED
| SETDSC_UNSET_INITIAL
,
5683 parentDisplay
->mTransformStyle
,
5684 NS_STYLE_TRANSFORM_STYLE_FLAT
, 0, 0, 0, 0);
5686 // orient: enum, inherit, initial
5687 SetDiscrete(*aRuleData
->ValueForOrient(),
5688 display
->mOrient
, canStoreInRuleTree
,
5689 SETDSC_ENUMERATED
| SETDSC_UNSET_INITIAL
,
5690 parentDisplay
->mOrient
,
5691 NS_STYLE_ORIENT_AUTO
, 0, 0, 0, 0);
5693 COMPUTE_END_RESET(Display
, display
)
5697 nsRuleNode::ComputeVisibilityData(void* aStartStruct
,
5698 const nsRuleData
* aRuleData
,
5699 nsStyleContext
* aContext
,
5700 nsRuleNode
* aHighestNode
,
5701 const RuleDetail aRuleDetail
,
5702 const bool aCanStoreInRuleTree
)
5704 COMPUTE_START_INHERITED(Visibility
, (mPresContext
),
5705 visibility
, parentVisibility
)
5707 // IMPORTANT: No properties in this struct have lengths in them. We
5708 // depend on this since CalcLengthWith can call StyleVisibility()
5709 // to get the language for resolving fonts!
5711 // direction: enum, inherit, initial
5712 SetDiscrete(*aRuleData
->ValueForDirection(), visibility
->mDirection
,
5714 SETDSC_ENUMERATED
| SETDSC_UNSET_INHERIT
,
5715 parentVisibility
->mDirection
,
5716 (GET_BIDI_OPTION_DIRECTION(mPresContext
->GetBidi())
5717 == IBMBIDI_TEXTDIRECTION_RTL
)
5718 ? NS_STYLE_DIRECTION_RTL
: NS_STYLE_DIRECTION_LTR
,
5721 // visibility: enum, inherit, initial
5722 SetDiscrete(*aRuleData
->ValueForVisibility(), visibility
->mVisible
,
5724 SETDSC_ENUMERATED
| SETDSC_UNSET_INHERIT
,
5725 parentVisibility
->mVisible
,
5726 NS_STYLE_VISIBILITY_VISIBLE
, 0, 0, 0, 0);
5728 // pointer-events: enum, inherit, initial
5729 SetDiscrete(*aRuleData
->ValueForPointerEvents(), visibility
->mPointerEvents
,
5731 SETDSC_ENUMERATED
| SETDSC_UNSET_INHERIT
,
5732 parentVisibility
->mPointerEvents
,
5733 NS_STYLE_POINTER_EVENTS_AUTO
, 0, 0, 0, 0);
5735 // writing-mode: enum, inherit, initial
5736 SetDiscrete(*aRuleData
->ValueForWritingMode(), visibility
->mWritingMode
,
5738 SETDSC_ENUMERATED
| SETDSC_UNSET_INHERIT
,
5739 parentVisibility
->mWritingMode
,
5740 NS_STYLE_WRITING_MODE_HORIZONTAL_TB
, 0, 0, 0, 0);
5742 // image-orientation: enum, inherit, initial
5743 const nsCSSValue
* orientation
= aRuleData
->ValueForImageOrientation();
5744 if (orientation
->GetUnit() == eCSSUnit_Inherit
||
5745 orientation
->GetUnit() == eCSSUnit_Unset
) {
5746 canStoreInRuleTree
= false;
5747 visibility
->mImageOrientation
= parentVisibility
->mImageOrientation
;
5748 } else if (orientation
->GetUnit() == eCSSUnit_Initial
) {
5749 visibility
->mImageOrientation
= nsStyleImageOrientation();
5750 } else if (orientation
->IsAngularUnit()) {
5751 double angle
= orientation
->GetAngleValueInRadians();
5752 visibility
->mImageOrientation
=
5753 nsStyleImageOrientation::CreateAsAngleAndFlip(angle
, false);
5754 } else if (orientation
->GetUnit() == eCSSUnit_Array
) {
5755 const nsCSSValue::Array
* array
= orientation
->GetArrayValue();
5756 MOZ_ASSERT(array
->Item(0).IsAngularUnit(),
5757 "First image-orientation value is not an angle");
5758 MOZ_ASSERT(array
->Item(1).GetUnit() == eCSSUnit_Enumerated
&&
5759 array
->Item(1).GetIntValue() == NS_STYLE_IMAGE_ORIENTATION_FLIP
,
5760 "Second image-orientation value is not 'flip'");
5761 double angle
= array
->Item(0).GetAngleValueInRadians();
5762 visibility
->mImageOrientation
=
5763 nsStyleImageOrientation::CreateAsAngleAndFlip(angle
, true);
5765 } else if (orientation
->GetUnit() == eCSSUnit_Enumerated
) {
5766 switch (orientation
->GetIntValue()) {
5767 case NS_STYLE_IMAGE_ORIENTATION_FLIP
:
5768 visibility
->mImageOrientation
= nsStyleImageOrientation::CreateAsFlip();
5770 case NS_STYLE_IMAGE_ORIENTATION_FROM_IMAGE
:
5771 visibility
->mImageOrientation
= nsStyleImageOrientation::CreateAsFromImage();
5774 NS_NOTREACHED("Invalid image-orientation enumerated value");
5777 MOZ_ASSERT(orientation
->GetUnit() == eCSSUnit_Null
, "Should be null unit");
5780 COMPUTE_END_INHERITED(Visibility
, visibility
)
5784 nsRuleNode::ComputeColorData(void* aStartStruct
,
5785 const nsRuleData
* aRuleData
,
5786 nsStyleContext
* aContext
,
5787 nsRuleNode
* aHighestNode
,
5788 const RuleDetail aRuleDetail
,
5789 const bool aCanStoreInRuleTree
)
5791 COMPUTE_START_INHERITED(Color
, (mPresContext
), color
, parentColor
)
5793 // color: color, string, inherit
5794 // Special case for currentColor. According to CSS3, setting color to 'currentColor'
5795 // should behave as if it is inherited
5796 const nsCSSValue
* colorValue
= aRuleData
->ValueForColor();
5797 if ((colorValue
->GetUnit() == eCSSUnit_EnumColor
&&
5798 colorValue
->GetIntValue() == NS_COLOR_CURRENTCOLOR
) ||
5799 colorValue
->GetUnit() == eCSSUnit_Unset
) {
5800 color
->mColor
= parentColor
->mColor
;
5801 canStoreInRuleTree
= false;
5803 else if (colorValue
->GetUnit() == eCSSUnit_Initial
) {
5804 color
->mColor
= mPresContext
->DefaultColor();
5807 SetColor(*colorValue
, parentColor
->mColor
, mPresContext
, aContext
,
5808 color
->mColor
, canStoreInRuleTree
);
5811 COMPUTE_END_INHERITED(Color
, color
)
5814 // information about how to compute values for background-* properties
5815 template <class SpecifiedValueItem
, class ComputedValueItem
>
5816 struct BackgroundItemComputer
{
5820 struct BackgroundItemComputer
<nsCSSValueList
, uint8_t>
5822 static void ComputeValue(nsStyleContext
* aStyleContext
,
5823 const nsCSSValueList
* aSpecifiedValue
,
5824 uint8_t& aComputedValue
,
5825 bool& aCanStoreInRuleTree
)
5827 SetDiscrete(aSpecifiedValue
->mValue
, aComputedValue
, aCanStoreInRuleTree
,
5828 SETDSC_ENUMERATED
, uint8_t(0), 0, 0, 0, 0, 0);
5833 struct BackgroundItemComputer
<nsCSSValuePairList
, nsStyleBackground::Repeat
>
5835 static void ComputeValue(nsStyleContext
* aStyleContext
,
5836 const nsCSSValuePairList
* aSpecifiedValue
,
5837 nsStyleBackground::Repeat
& aComputedValue
,
5838 bool& aCanStoreInRuleTree
)
5840 NS_ASSERTION(aSpecifiedValue
->mXValue
.GetUnit() == eCSSUnit_Enumerated
&&
5841 (aSpecifiedValue
->mYValue
.GetUnit() == eCSSUnit_Enumerated
||
5842 aSpecifiedValue
->mYValue
.GetUnit() == eCSSUnit_Null
),
5845 bool hasContraction
= true;
5846 uint8_t value
= aSpecifiedValue
->mXValue
.GetIntValue();
5848 case NS_STYLE_BG_REPEAT_REPEAT_X
:
5849 aComputedValue
.mXRepeat
= NS_STYLE_BG_REPEAT_REPEAT
;
5850 aComputedValue
.mYRepeat
= NS_STYLE_BG_REPEAT_NO_REPEAT
;
5852 case NS_STYLE_BG_REPEAT_REPEAT_Y
:
5853 aComputedValue
.mXRepeat
= NS_STYLE_BG_REPEAT_NO_REPEAT
;
5854 aComputedValue
.mYRepeat
= NS_STYLE_BG_REPEAT_REPEAT
;
5857 aComputedValue
.mXRepeat
= value
;
5858 hasContraction
= false;
5862 if (hasContraction
) {
5863 NS_ASSERTION(aSpecifiedValue
->mYValue
.GetUnit() == eCSSUnit_Null
,
5868 switch (aSpecifiedValue
->mYValue
.GetUnit()) {
5870 aComputedValue
.mYRepeat
= aComputedValue
.mXRepeat
;
5872 case eCSSUnit_Enumerated
:
5873 value
= aSpecifiedValue
->mYValue
.GetIntValue();
5874 NS_ASSERTION(value
== NS_STYLE_BG_REPEAT_NO_REPEAT
||
5875 value
== NS_STYLE_BG_REPEAT_REPEAT
, "Unexpected value");
5876 aComputedValue
.mYRepeat
= value
;
5879 NS_NOTREACHED("Unexpected CSS value");
5886 struct BackgroundItemComputer
<nsCSSValueList
, nsStyleImage
>
5888 static void ComputeValue(nsStyleContext
* aStyleContext
,
5889 const nsCSSValueList
* aSpecifiedValue
,
5890 nsStyleImage
& aComputedValue
,
5891 bool& aCanStoreInRuleTree
)
5893 SetStyleImage(aStyleContext
, aSpecifiedValue
->mValue
, aComputedValue
,
5894 aCanStoreInRuleTree
);
5898 /* Helper function for
5899 * BackgroundItemComputer<nsCSSValue, nsStyleBackground::Position>
5900 * It computes a single PositionCoord from an nsCSSValue object
5901 * (contained in a list).
5903 typedef nsStyleBackground::Position::PositionCoord PositionCoord
;
5905 ComputeBackgroundPositionCoord(nsStyleContext
* aStyleContext
,
5906 const nsCSSValue
& aEdge
,
5907 const nsCSSValue
& aOffset
,
5908 PositionCoord
* aResult
,
5909 bool& aCanStoreInRuleTree
)
5911 if (eCSSUnit_Percent
== aOffset
.GetUnit()) {
5912 aResult
->mLength
= 0;
5913 aResult
->mPercent
= aOffset
.GetPercentValue();
5914 aResult
->mHasPercent
= true;
5915 } else if (aOffset
.IsLengthUnit()) {
5916 aResult
->mLength
= CalcLength(aOffset
, aStyleContext
,
5917 aStyleContext
->PresContext(),
5918 aCanStoreInRuleTree
);
5919 aResult
->mPercent
= 0.0f
;
5920 aResult
->mHasPercent
= false;
5921 } else if (aOffset
.IsCalcUnit()) {
5922 LengthPercentPairCalcOps
ops(aStyleContext
,
5923 aStyleContext
->PresContext(),
5924 aCanStoreInRuleTree
);
5925 nsRuleNode::ComputedCalc vals
= ComputeCalc(aOffset
, ops
);
5926 aResult
->mLength
= vals
.mLength
;
5927 aResult
->mPercent
= vals
.mPercent
;
5928 aResult
->mHasPercent
= ops
.mHasPercent
;
5930 aResult
->mLength
= 0;
5931 aResult
->mPercent
= 0.0f
;
5932 aResult
->mHasPercent
= false;
5933 NS_ASSERTION(aOffset
.GetUnit() == eCSSUnit_Null
, "unexpected unit");
5936 if (eCSSUnit_Enumerated
== aEdge
.GetUnit()) {
5938 if (aEdge
.GetIntValue() & (NS_STYLE_BG_POSITION_BOTTOM
|
5939 NS_STYLE_BG_POSITION_RIGHT
)) {
5944 aResult
->mPercent
= GetFloatFromBoxPosition(aEdge
.GetIntValue()) +
5945 sign
* aResult
->mPercent
;
5946 aResult
->mLength
= sign
* aResult
->mLength
;
5947 aResult
->mHasPercent
= true;
5949 NS_ASSERTION(eCSSUnit_Null
== aEdge
.GetUnit(), "unexpected unit");
5954 struct BackgroundItemComputer
<nsCSSValueList
, nsStyleBackground::Position
>
5956 static void ComputeValue(nsStyleContext
* aStyleContext
,
5957 const nsCSSValueList
* aSpecifiedValue
,
5958 nsStyleBackground::Position
& aComputedValue
,
5959 bool& aCanStoreInRuleTree
)
5961 NS_ASSERTION(aSpecifiedValue
->mValue
.GetUnit() == eCSSUnit_Array
, "bg-position not an array");
5963 nsRefPtr
<nsCSSValue::Array
> bgPositionArray
=
5964 aSpecifiedValue
->mValue
.GetArrayValue();
5965 const nsCSSValue
&xEdge
= bgPositionArray
->Item(0);
5966 const nsCSSValue
&xOffset
= bgPositionArray
->Item(1);
5967 const nsCSSValue
&yEdge
= bgPositionArray
->Item(2);
5968 const nsCSSValue
&yOffset
= bgPositionArray
->Item(3);
5970 NS_ASSERTION((eCSSUnit_Enumerated
== xEdge
.GetUnit() ||
5971 eCSSUnit_Null
== xEdge
.GetUnit()) &&
5972 (eCSSUnit_Enumerated
== yEdge
.GetUnit() ||
5973 eCSSUnit_Null
== yEdge
.GetUnit()) &&
5974 eCSSUnit_Enumerated
!= xOffset
.GetUnit() &&
5975 eCSSUnit_Enumerated
!= yOffset
.GetUnit(),
5976 "Invalid background position");
5978 ComputeBackgroundPositionCoord(aStyleContext
, xEdge
, xOffset
,
5979 &aComputedValue
.mXPosition
,
5980 aCanStoreInRuleTree
);
5982 ComputeBackgroundPositionCoord(aStyleContext
, yEdge
, yOffset
,
5983 &aComputedValue
.mYPosition
,
5984 aCanStoreInRuleTree
);
5989 struct BackgroundSizeAxis
{
5990 nsCSSValue
nsCSSValuePairList::* specified
;
5991 nsStyleBackground::Size::Dimension
nsStyleBackground::Size::* result
;
5992 uint8_t nsStyleBackground::Size::* type
;
5995 static const BackgroundSizeAxis gBGSizeAxes
[] = {
5996 { &nsCSSValuePairList::mXValue
,
5997 &nsStyleBackground::Size::mWidth
,
5998 &nsStyleBackground::Size::mWidthType
},
5999 { &nsCSSValuePairList::mYValue
,
6000 &nsStyleBackground::Size::mHeight
,
6001 &nsStyleBackground::Size::mHeightType
}
6005 struct BackgroundItemComputer
<nsCSSValuePairList
, nsStyleBackground::Size
>
6007 static void ComputeValue(nsStyleContext
* aStyleContext
,
6008 const nsCSSValuePairList
* aSpecifiedValue
,
6009 nsStyleBackground::Size
& aComputedValue
,
6010 bool& aCanStoreInRuleTree
)
6012 nsStyleBackground::Size
&size
= aComputedValue
;
6013 for (const BackgroundSizeAxis
*axis
= gBGSizeAxes
,
6014 *axis_end
= ArrayEnd(gBGSizeAxes
);
6015 axis
< axis_end
; ++axis
) {
6016 const nsCSSValue
&specified
= aSpecifiedValue
->*(axis
->specified
);
6017 if (eCSSUnit_Auto
== specified
.GetUnit()) {
6018 size
.*(axis
->type
) = nsStyleBackground::Size::eAuto
;
6020 else if (eCSSUnit_Enumerated
== specified
.GetUnit()) {
6021 static_assert(nsStyleBackground::Size::eContain
==
6022 NS_STYLE_BG_SIZE_CONTAIN
&&
6023 nsStyleBackground::Size::eCover
==
6024 NS_STYLE_BG_SIZE_COVER
,
6025 "background size constants out of sync");
6026 NS_ABORT_IF_FALSE(specified
.GetIntValue() == NS_STYLE_BG_SIZE_CONTAIN
||
6027 specified
.GetIntValue() == NS_STYLE_BG_SIZE_COVER
,
6028 "invalid enumerated value for size coordinate");
6029 size
.*(axis
->type
) = specified
.GetIntValue();
6031 else if (eCSSUnit_Null
== specified
.GetUnit()) {
6032 NS_ABORT_IF_FALSE(axis
== gBGSizeAxes
+ 1,
6033 "null allowed only as height value, and only "
6034 "for contain/cover/initial/inherit");
6037 const nsCSSValue
&widthValue
= aSpecifiedValue
->mXValue
;
6038 NS_ABORT_IF_FALSE(widthValue
.GetUnit() != eCSSUnit_Inherit
&&
6039 widthValue
.GetUnit() != eCSSUnit_Initial
&&
6040 widthValue
.GetUnit() != eCSSUnit_Unset
,
6041 "initial/inherit/unset should already have been handled");
6042 NS_ABORT_IF_FALSE(widthValue
.GetUnit() == eCSSUnit_Enumerated
&&
6043 (widthValue
.GetIntValue() == NS_STYLE_BG_SIZE_CONTAIN
||
6044 widthValue
.GetIntValue() == NS_STYLE_BG_SIZE_COVER
),
6045 "null height value not corresponding to allowable "
6046 "non-null width value");
6049 size
.*(axis
->type
) = size
.mWidthType
;
6051 else if (eCSSUnit_Percent
== specified
.GetUnit()) {
6052 (size
.*(axis
->result
)).mLength
= 0;
6053 (size
.*(axis
->result
)).mPercent
= specified
.GetPercentValue();
6054 (size
.*(axis
->result
)).mHasPercent
= true;
6055 size
.*(axis
->type
) = nsStyleBackground::Size::eLengthPercentage
;
6057 else if (specified
.IsLengthUnit()) {
6058 (size
.*(axis
->result
)).mLength
=
6059 CalcLength(specified
, aStyleContext
, aStyleContext
->PresContext(),
6060 aCanStoreInRuleTree
);
6061 (size
.*(axis
->result
)).mPercent
= 0.0f
;
6062 (size
.*(axis
->result
)).mHasPercent
= false;
6063 size
.*(axis
->type
) = nsStyleBackground::Size::eLengthPercentage
;
6065 NS_ABORT_IF_FALSE(specified
.IsCalcUnit(), "unexpected unit");
6066 LengthPercentPairCalcOps
ops(aStyleContext
,
6067 aStyleContext
->PresContext(),
6068 aCanStoreInRuleTree
);
6069 nsRuleNode::ComputedCalc vals
= ComputeCalc(specified
, ops
);
6070 (size
.*(axis
->result
)).mLength
= vals
.mLength
;
6071 (size
.*(axis
->result
)).mPercent
= vals
.mPercent
;
6072 (size
.*(axis
->result
)).mHasPercent
= ops
.mHasPercent
;
6073 size
.*(axis
->type
) = nsStyleBackground::Size::eLengthPercentage
;
6077 NS_ABORT_IF_FALSE(size
.mWidthType
< nsStyleBackground::Size::eDimensionType_COUNT
,
6079 NS_ABORT_IF_FALSE(size
.mHeightType
< nsStyleBackground::Size::eDimensionType_COUNT
,
6081 NS_ABORT_IF_FALSE((size
.mWidthType
!= nsStyleBackground::Size::eContain
&&
6082 size
.mWidthType
!= nsStyleBackground::Size::eCover
) ||
6083 size
.mWidthType
== size
.mHeightType
,
6084 "contain/cover apply to both dimensions or to neither");
6088 template <class ComputedValueItem
>
6090 SetBackgroundList(nsStyleContext
* aStyleContext
,
6091 const nsCSSValue
& aValue
,
6092 nsAutoTArray
< nsStyleBackground::Layer
, 1> &aLayers
,
6093 const nsAutoTArray
<nsStyleBackground::Layer
, 1> &aParentLayers
,
6094 ComputedValueItem
nsStyleBackground::Layer::* aResultLocation
,
6095 ComputedValueItem aInitialValue
,
6096 uint32_t aParentItemCount
,
6097 uint32_t& aItemCount
,
6098 uint32_t& aMaxItemCount
,
6100 bool& aCanStoreInRuleTree
)
6102 switch (aValue
.GetUnit()) {
6106 case eCSSUnit_Inherit
:
6108 aCanStoreInRuleTree
= false;
6109 aLayers
.EnsureLengthAtLeast(aParentItemCount
);
6110 aItemCount
= aParentItemCount
;
6111 for (uint32_t i
= 0; i
< aParentItemCount
; ++i
) {
6112 aLayers
[i
].*aResultLocation
= aParentLayers
[i
].*aResultLocation
;
6116 case eCSSUnit_Initial
:
6117 case eCSSUnit_Unset
:
6120 aLayers
[0].*aResultLocation
= aInitialValue
;
6124 case eCSSUnit_ListDep
: {
6127 const nsCSSValueList
* item
= aValue
.GetListValue();
6129 NS_ASSERTION(item
->mValue
.GetUnit() != eCSSUnit_Null
&&
6130 item
->mValue
.GetUnit() != eCSSUnit_Inherit
&&
6131 item
->mValue
.GetUnit() != eCSSUnit_Initial
&&
6132 item
->mValue
.GetUnit() != eCSSUnit_Unset
,
6135 aLayers
.EnsureLengthAtLeast(aItemCount
);
6136 BackgroundItemComputer
<nsCSSValueList
, ComputedValueItem
>
6137 ::ComputeValue(aStyleContext
, item
,
6138 aLayers
[aItemCount
-1].*aResultLocation
,
6139 aCanStoreInRuleTree
);
6146 NS_ABORT_IF_FALSE(false,
6147 nsPrintfCString("unexpected unit %d",
6148 aValue
.GetUnit()).get());
6151 if (aItemCount
> aMaxItemCount
)
6152 aMaxItemCount
= aItemCount
;
6155 template <class ComputedValueItem
>
6157 SetBackgroundPairList(nsStyleContext
* aStyleContext
,
6158 const nsCSSValue
& aValue
,
6159 nsAutoTArray
< nsStyleBackground::Layer
, 1> &aLayers
,
6160 const nsAutoTArray
<nsStyleBackground::Layer
, 1>
6162 ComputedValueItem
nsStyleBackground::Layer::*
6164 ComputedValueItem aInitialValue
,
6165 uint32_t aParentItemCount
,
6166 uint32_t& aItemCount
,
6167 uint32_t& aMaxItemCount
,
6169 bool& aCanStoreInRuleTree
)
6171 switch (aValue
.GetUnit()) {
6175 case eCSSUnit_Inherit
:
6177 aCanStoreInRuleTree
= false;
6178 aLayers
.EnsureLengthAtLeast(aParentItemCount
);
6179 aItemCount
= aParentItemCount
;
6180 for (uint32_t i
= 0; i
< aParentItemCount
; ++i
) {
6181 aLayers
[i
].*aResultLocation
= aParentLayers
[i
].*aResultLocation
;
6185 case eCSSUnit_Initial
:
6186 case eCSSUnit_Unset
:
6189 aLayers
[0].*aResultLocation
= aInitialValue
;
6192 case eCSSUnit_PairList
:
6193 case eCSSUnit_PairListDep
: {
6196 const nsCSSValuePairList
* item
= aValue
.GetPairListValue();
6198 NS_ASSERTION(item
->mXValue
.GetUnit() != eCSSUnit_Inherit
&&
6199 item
->mXValue
.GetUnit() != eCSSUnit_Initial
&&
6200 item
->mXValue
.GetUnit() != eCSSUnit_Unset
&&
6201 item
->mYValue
.GetUnit() != eCSSUnit_Inherit
&&
6202 item
->mYValue
.GetUnit() != eCSSUnit_Initial
&&
6203 item
->mYValue
.GetUnit() != eCSSUnit_Unset
,
6206 aLayers
.EnsureLengthAtLeast(aItemCount
);
6207 BackgroundItemComputer
<nsCSSValuePairList
, ComputedValueItem
>
6208 ::ComputeValue(aStyleContext
, item
,
6209 aLayers
[aItemCount
-1].*aResultLocation
,
6210 aCanStoreInRuleTree
);
6217 NS_ABORT_IF_FALSE(false,
6218 nsPrintfCString("unexpected unit %d",
6219 aValue
.GetUnit()).get());
6222 if (aItemCount
> aMaxItemCount
)
6223 aMaxItemCount
= aItemCount
;
6226 template <class ComputedValueItem
>
6228 FillBackgroundList(nsAutoTArray
< nsStyleBackground::Layer
, 1> &aLayers
,
6229 ComputedValueItem
nsStyleBackground::Layer::* aResultLocation
,
6230 uint32_t aItemCount
, uint32_t aFillCount
)
6232 NS_PRECONDITION(aFillCount
<= aLayers
.Length(), "unexpected array length");
6233 for (uint32_t sourceLayer
= 0, destLayer
= aItemCount
;
6234 destLayer
< aFillCount
;
6235 ++sourceLayer
, ++destLayer
) {
6236 aLayers
[destLayer
].*aResultLocation
=
6237 aLayers
[sourceLayer
].*aResultLocation
;
6242 nsRuleNode::ComputeBackgroundData(void* aStartStruct
,
6243 const nsRuleData
* aRuleData
,
6244 nsStyleContext
* aContext
,
6245 nsRuleNode
* aHighestNode
,
6246 const RuleDetail aRuleDetail
,
6247 const bool aCanStoreInRuleTree
)
6249 COMPUTE_START_RESET(Background
, (), bg
, parentBG
)
6251 // background-color: color, string, inherit
6252 const nsCSSValue
* backColorValue
= aRuleData
->ValueForBackgroundColor();
6253 if (eCSSUnit_Initial
== backColorValue
->GetUnit() ||
6254 eCSSUnit_Unset
== backColorValue
->GetUnit()) {
6255 bg
->mBackgroundColor
= NS_RGBA(0, 0, 0, 0);
6256 } else if (!SetColor(*backColorValue
, parentBG
->mBackgroundColor
,
6257 mPresContext
, aContext
, bg
->mBackgroundColor
,
6258 canStoreInRuleTree
)) {
6259 NS_ASSERTION(eCSSUnit_Null
== backColorValue
->GetUnit(),
6260 "unexpected color unit");
6263 uint32_t maxItemCount
= 1;
6264 bool rebuild
= false;
6266 // background-image: url (stored as image), none, inherit [list]
6267 nsStyleImage initialImage
;
6268 SetBackgroundList(aContext
, *aRuleData
->ValueForBackgroundImage(),
6270 parentBG
->mLayers
, &nsStyleBackground::Layer::mImage
,
6271 initialImage
, parentBG
->mImageCount
, bg
->mImageCount
,
6272 maxItemCount
, rebuild
, canStoreInRuleTree
);
6274 // background-repeat: enum, inherit, initial [pair list]
6275 nsStyleBackground::Repeat initialRepeat
;
6276 initialRepeat
.SetInitialValues();
6277 SetBackgroundPairList(aContext
, *aRuleData
->ValueForBackgroundRepeat(),
6279 parentBG
->mLayers
, &nsStyleBackground::Layer::mRepeat
,
6280 initialRepeat
, parentBG
->mRepeatCount
,
6281 bg
->mRepeatCount
, maxItemCount
, rebuild
,
6282 canStoreInRuleTree
);
6284 // background-attachment: enum, inherit, initial [list]
6285 SetBackgroundList(aContext
, *aRuleData
->ValueForBackgroundAttachment(),
6286 bg
->mLayers
, parentBG
->mLayers
,
6287 &nsStyleBackground::Layer::mAttachment
,
6288 uint8_t(NS_STYLE_BG_ATTACHMENT_SCROLL
),
6289 parentBG
->mAttachmentCount
,
6290 bg
->mAttachmentCount
, maxItemCount
, rebuild
,
6291 canStoreInRuleTree
);
6293 // background-clip: enum, inherit, initial [list]
6294 SetBackgroundList(aContext
, *aRuleData
->ValueForBackgroundClip(),
6296 parentBG
->mLayers
, &nsStyleBackground::Layer::mClip
,
6297 uint8_t(NS_STYLE_BG_CLIP_BORDER
), parentBG
->mClipCount
,
6298 bg
->mClipCount
, maxItemCount
, rebuild
, canStoreInRuleTree
);
6300 // background-blend-mode: enum, inherit, initial [list]
6301 SetBackgroundList(aContext
, *aRuleData
->ValueForBackgroundBlendMode(),
6303 parentBG
->mLayers
, &nsStyleBackground::Layer::mBlendMode
,
6304 uint8_t(NS_STYLE_BLEND_NORMAL
), parentBG
->mBlendModeCount
,
6305 bg
->mBlendModeCount
, maxItemCount
, rebuild
,
6306 canStoreInRuleTree
);
6308 // background-origin: enum, inherit, initial [list]
6309 SetBackgroundList(aContext
, *aRuleData
->ValueForBackgroundOrigin(),
6311 parentBG
->mLayers
, &nsStyleBackground::Layer::mOrigin
,
6312 uint8_t(NS_STYLE_BG_ORIGIN_PADDING
), parentBG
->mOriginCount
,
6313 bg
->mOriginCount
, maxItemCount
, rebuild
,
6314 canStoreInRuleTree
);
6316 // background-position: enum, length, percent (flags), inherit [pair list]
6317 nsStyleBackground::Position initialPosition
;
6318 initialPosition
.SetInitialValues();
6319 SetBackgroundList(aContext
, *aRuleData
->ValueForBackgroundPosition(),
6321 parentBG
->mLayers
, &nsStyleBackground::Layer::mPosition
,
6322 initialPosition
, parentBG
->mPositionCount
,
6323 bg
->mPositionCount
, maxItemCount
, rebuild
,
6324 canStoreInRuleTree
);
6326 // background-size: enum, length, auto, inherit, initial [pair list]
6327 nsStyleBackground::Size initialSize
;
6328 initialSize
.SetInitialValues();
6329 SetBackgroundPairList(aContext
, *aRuleData
->ValueForBackgroundSize(),
6331 parentBG
->mLayers
, &nsStyleBackground::Layer::mSize
,
6332 initialSize
, parentBG
->mSizeCount
,
6333 bg
->mSizeCount
, maxItemCount
, rebuild
,
6334 canStoreInRuleTree
);
6337 // Delete any extra items. We need to keep layers in which any
6338 // property was specified.
6339 bg
->mLayers
.TruncateLength(maxItemCount
);
6341 uint32_t fillCount
= bg
->mImageCount
;
6342 FillBackgroundList(bg
->mLayers
, &nsStyleBackground::Layer::mImage
,
6343 bg
->mImageCount
, fillCount
);
6344 FillBackgroundList(bg
->mLayers
, &nsStyleBackground::Layer::mRepeat
,
6345 bg
->mRepeatCount
, fillCount
);
6346 FillBackgroundList(bg
->mLayers
, &nsStyleBackground::Layer::mAttachment
,
6347 bg
->mAttachmentCount
, fillCount
);
6348 FillBackgroundList(bg
->mLayers
, &nsStyleBackground::Layer::mClip
,
6349 bg
->mClipCount
, fillCount
);
6350 FillBackgroundList(bg
->mLayers
, &nsStyleBackground::Layer::mBlendMode
,
6351 bg
->mBlendModeCount
, fillCount
);
6352 FillBackgroundList(bg
->mLayers
, &nsStyleBackground::Layer::mOrigin
,
6353 bg
->mOriginCount
, fillCount
);
6354 FillBackgroundList(bg
->mLayers
, &nsStyleBackground::Layer::mPosition
,
6355 bg
->mPositionCount
, fillCount
);
6356 FillBackgroundList(bg
->mLayers
, &nsStyleBackground::Layer::mSize
,
6357 bg
->mSizeCount
, fillCount
);
6360 // Now that the dust has settled, register the images with the document
6361 for (uint32_t i
= 0; i
< bg
->mImageCount
; ++i
)
6362 bg
->mLayers
[i
].TrackImages(aContext
->PresContext());
6364 COMPUTE_END_RESET(Background
, bg
)
6368 nsRuleNode::ComputeMarginData(void* aStartStruct
,
6369 const nsRuleData
* aRuleData
,
6370 nsStyleContext
* aContext
,
6371 nsRuleNode
* aHighestNode
,
6372 const RuleDetail aRuleDetail
,
6373 const bool aCanStoreInRuleTree
)
6375 COMPUTE_START_RESET(Margin
, (), margin
, parentMargin
)
6377 // margin: length, percent, auto, inherit
6379 nsCSSRect ourMargin
;
6380 ourMargin
.mTop
= *aRuleData
->ValueForMarginTop();
6381 ourMargin
.mRight
= *aRuleData
->ValueForMarginRightValue();
6382 ourMargin
.mBottom
= *aRuleData
->ValueForMarginBottom();
6383 ourMargin
.mLeft
= *aRuleData
->ValueForMarginLeftValue();
6384 AdjustLogicalBoxProp(aContext
,
6385 *aRuleData
->ValueForMarginLeftLTRSource(),
6386 *aRuleData
->ValueForMarginLeftRTLSource(),
6387 *aRuleData
->ValueForMarginStartValue(),
6388 *aRuleData
->ValueForMarginEndValue(),
6389 NS_SIDE_LEFT
, ourMargin
, canStoreInRuleTree
);
6390 AdjustLogicalBoxProp(aContext
,
6391 *aRuleData
->ValueForMarginRightLTRSource(),
6392 *aRuleData
->ValueForMarginRightRTLSource(),
6393 *aRuleData
->ValueForMarginEndValue(),
6394 *aRuleData
->ValueForMarginStartValue(),
6395 NS_SIDE_RIGHT
, ourMargin
, canStoreInRuleTree
);
6396 NS_FOR_CSS_SIDES(side
) {
6397 nsStyleCoord parentCoord
= parentMargin
->mMargin
.Get(side
);
6398 if (SetCoord(ourMargin
.*(nsCSSRect::sides
[side
]),
6400 SETCOORD_LPAH
| SETCOORD_INITIAL_ZERO
| SETCOORD_STORE_CALC
|
6401 SETCOORD_UNSET_INITIAL
,
6402 aContext
, mPresContext
, canStoreInRuleTree
)) {
6403 margin
->mMargin
.Set(side
, coord
);
6407 margin
->RecalcData();
6408 COMPUTE_END_RESET(Margin
, margin
)
6412 SetBorderImageRect(const nsCSSValue
& aValue
,
6413 /** outparam */ nsCSSRect
& aRect
)
6415 switch (aValue
.GetUnit()) {
6420 aRect
= aValue
.GetRectValue();
6422 case eCSSUnit_Inherit
:
6423 case eCSSUnit_Initial
:
6424 case eCSSUnit_Unset
:
6425 aRect
.SetAllSidesTo(aValue
);
6428 NS_ASSERTION(false, "Unexpected border image value for rect.");
6433 SetBorderImagePair(const nsCSSValue
& aValue
,
6434 /** outparam */ nsCSSValuePair
& aPair
)
6436 switch (aValue
.GetUnit()) {
6441 aPair
= aValue
.GetPairValue();
6443 case eCSSUnit_Inherit
:
6444 case eCSSUnit_Initial
:
6445 case eCSSUnit_Unset
:
6446 aPair
.SetBothValuesTo(aValue
);
6449 NS_ASSERTION(false, "Unexpected border image value for pair.");
6454 SetBorderImageSlice(const nsCSSValue
& aValue
,
6455 /** outparam */ nsCSSValue
& aSlice
,
6456 /** outparam */ nsCSSValue
& aFill
)
6458 const nsCSSValueList
* valueList
;
6459 switch (aValue
.GetUnit()) {
6465 // Get slice dimensions.
6466 valueList
= aValue
.GetListValue();
6467 aSlice
= valueList
->mValue
;
6469 // Get "fill" keyword.
6470 valueList
= valueList
->mNext
;
6472 aFill
= valueList
->mValue
;
6474 aFill
.SetInitialValue();
6477 case eCSSUnit_Inherit
:
6478 case eCSSUnit_Initial
:
6479 case eCSSUnit_Unset
:
6484 NS_ASSERTION(false, "Unexpected border image value for pair.");
6489 nsRuleNode::ComputeBorderData(void* aStartStruct
,
6490 const nsRuleData
* aRuleData
,
6491 nsStyleContext
* aContext
,
6492 nsRuleNode
* aHighestNode
,
6493 const RuleDetail aRuleDetail
,
6494 const bool aCanStoreInRuleTree
)
6496 COMPUTE_START_RESET(Border
, (mPresContext
), border
, parentBorder
)
6498 // box-decoration-break: enum, inherit, initial
6499 SetDiscrete(*aRuleData
->ValueForBoxDecorationBreak(),
6500 border
->mBoxDecorationBreak
, canStoreInRuleTree
,
6501 SETDSC_ENUMERATED
| SETDSC_UNSET_INITIAL
,
6502 parentBorder
->mBoxDecorationBreak
,
6503 NS_STYLE_BOX_DECORATION_BREAK_SLICE
, 0, 0, 0, 0);
6505 // box-shadow: none, list, inherit, initial
6506 const nsCSSValue
* boxShadowValue
= aRuleData
->ValueForBoxShadow();
6507 switch (boxShadowValue
->GetUnit()) {
6511 case eCSSUnit_Initial
:
6512 case eCSSUnit_Unset
:
6514 border
->mBoxShadow
= nullptr;
6517 case eCSSUnit_Inherit
:
6518 border
->mBoxShadow
= parentBorder
->mBoxShadow
;
6519 canStoreInRuleTree
= false;
6523 case eCSSUnit_ListDep
:
6524 border
->mBoxShadow
= GetShadowData(boxShadowValue
->GetListValue(),
6525 aContext
, true, canStoreInRuleTree
);
6529 NS_ABORT_IF_FALSE(false,
6530 nsPrintfCString("unrecognized shadow unit %d",
6531 boxShadowValue
->GetUnit()).get());
6534 // border-width, border-*-width: length, enum, inherit
6536 nsCSSRect ourBorderWidth
;
6537 ourBorderWidth
.mTop
= *aRuleData
->ValueForBorderTopWidth();
6538 ourBorderWidth
.mRight
= *aRuleData
->ValueForBorderRightWidthValue();
6539 ourBorderWidth
.mBottom
= *aRuleData
->ValueForBorderBottomWidth();
6540 ourBorderWidth
.mLeft
= *aRuleData
->ValueForBorderLeftWidthValue();
6541 AdjustLogicalBoxProp(aContext
,
6542 *aRuleData
->ValueForBorderLeftWidthLTRSource(),
6543 *aRuleData
->ValueForBorderLeftWidthRTLSource(),
6544 *aRuleData
->ValueForBorderStartWidthValue(),
6545 *aRuleData
->ValueForBorderEndWidthValue(),
6546 NS_SIDE_LEFT
, ourBorderWidth
, canStoreInRuleTree
);
6547 AdjustLogicalBoxProp(aContext
,
6548 *aRuleData
->ValueForBorderRightWidthLTRSource(),
6549 *aRuleData
->ValueForBorderRightWidthRTLSource(),
6550 *aRuleData
->ValueForBorderEndWidthValue(),
6551 *aRuleData
->ValueForBorderStartWidthValue(),
6552 NS_SIDE_RIGHT
, ourBorderWidth
, canStoreInRuleTree
);
6553 { // scope for compilers with broken |for| loop scoping
6554 NS_FOR_CSS_SIDES(side
) {
6555 const nsCSSValue
&value
= ourBorderWidth
.*(nsCSSRect::sides
[side
]);
6556 NS_ASSERTION(eCSSUnit_Percent
!= value
.GetUnit(),
6557 "Percentage borders not implemented yet "
6558 "If implementing, make sure to fix all consumers of "
6559 "nsStyleBorder, the IsPercentageAwareChild method, "
6560 "the nsAbsoluteContainingBlock::FrameDependsOnContainer "
6562 "nsLineLayout::IsPercentageAwareReplacedElement method "
6563 "and probably some other places");
6564 if (eCSSUnit_Enumerated
== value
.GetUnit()) {
6565 NS_ASSERTION(value
.GetIntValue() == NS_STYLE_BORDER_WIDTH_THIN
||
6566 value
.GetIntValue() == NS_STYLE_BORDER_WIDTH_MEDIUM
||
6567 value
.GetIntValue() == NS_STYLE_BORDER_WIDTH_THICK
,
6568 "Unexpected enum value");
6569 border
->SetBorderWidth(side
,
6570 (mPresContext
->GetBorderWidthTable())[value
.GetIntValue()]);
6572 // OK to pass bad aParentCoord since we're not passing SETCOORD_INHERIT
6573 else if (SetCoord(value
, coord
, nsStyleCoord(),
6574 SETCOORD_LENGTH
| SETCOORD_CALC_LENGTH_ONLY
,
6575 aContext
, mPresContext
, canStoreInRuleTree
)) {
6576 NS_ASSERTION(coord
.GetUnit() == eStyleUnit_Coord
, "unexpected unit");
6577 // clamp negative calc() to 0.
6578 border
->SetBorderWidth(side
, std::max(coord
.GetCoordValue(), 0));
6580 else if (eCSSUnit_Inherit
== value
.GetUnit()) {
6581 canStoreInRuleTree
= false;
6582 border
->SetBorderWidth(side
,
6583 parentBorder
->GetComputedBorder().Side(side
));
6585 else if (eCSSUnit_Initial
== value
.GetUnit() ||
6586 eCSSUnit_Unset
== value
.GetUnit()) {
6587 border
->SetBorderWidth(side
,
6588 (mPresContext
->GetBorderWidthTable())[NS_STYLE_BORDER_WIDTH_MEDIUM
]);
6591 NS_ASSERTION(eCSSUnit_Null
== value
.GetUnit(),
6592 "missing case handling border width");
6597 // border-style, border-*-style: enum, inherit
6598 nsCSSRect ourBorderStyle
;
6599 ourBorderStyle
.mTop
= *aRuleData
->ValueForBorderTopStyle();
6600 ourBorderStyle
.mRight
= *aRuleData
->ValueForBorderRightStyleValue();
6601 ourBorderStyle
.mBottom
= *aRuleData
->ValueForBorderBottomStyle();
6602 ourBorderStyle
.mLeft
= *aRuleData
->ValueForBorderLeftStyleValue();
6603 AdjustLogicalBoxProp(aContext
,
6604 *aRuleData
->ValueForBorderLeftStyleLTRSource(),
6605 *aRuleData
->ValueForBorderLeftStyleRTLSource(),
6606 *aRuleData
->ValueForBorderStartStyleValue(),
6607 *aRuleData
->ValueForBorderEndStyleValue(),
6608 NS_SIDE_LEFT
, ourBorderStyle
, canStoreInRuleTree
);
6609 AdjustLogicalBoxProp(aContext
,
6610 *aRuleData
->ValueForBorderRightStyleLTRSource(),
6611 *aRuleData
->ValueForBorderRightStyleRTLSource(),
6612 *aRuleData
->ValueForBorderEndStyleValue(),
6613 *aRuleData
->ValueForBorderStartStyleValue(),
6614 NS_SIDE_RIGHT
, ourBorderStyle
, canStoreInRuleTree
);
6615 { // scope for compilers with broken |for| loop scoping
6616 NS_FOR_CSS_SIDES(side
) {
6617 const nsCSSValue
&value
= ourBorderStyle
.*(nsCSSRect::sides
[side
]);
6618 nsCSSUnit unit
= value
.GetUnit();
6619 NS_ABORT_IF_FALSE(eCSSUnit_None
!= unit
,
6620 "'none' should be handled as enumerated value");
6621 if (eCSSUnit_Enumerated
== unit
) {
6622 border
->SetBorderStyle(side
, value
.GetIntValue());
6624 else if (eCSSUnit_Initial
== unit
||
6625 eCSSUnit_Unset
== unit
) {
6626 border
->SetBorderStyle(side
, NS_STYLE_BORDER_STYLE_NONE
);
6628 else if (eCSSUnit_Inherit
== unit
) {
6629 canStoreInRuleTree
= false;
6630 border
->SetBorderStyle(side
, parentBorder
->GetBorderStyle(side
));
6635 // -moz-border-*-colors: color, string, enum, none, inherit/initial
6636 nscolor borderColor
;
6637 nscolor unused
= NS_RGB(0,0,0);
6639 static const nsCSSProperty borderColorsProps
[] = {
6640 eCSSProperty_border_top_colors
,
6641 eCSSProperty_border_right_colors
,
6642 eCSSProperty_border_bottom_colors
,
6643 eCSSProperty_border_left_colors
6646 NS_FOR_CSS_SIDES(side
) {
6647 const nsCSSValue
& value
= *aRuleData
->ValueFor(borderColorsProps
[side
]);
6648 switch (value
.GetUnit()) {
6652 case eCSSUnit_Initial
:
6653 case eCSSUnit_Unset
:
6655 border
->ClearBorderColors(side
);
6658 case eCSSUnit_Inherit
: {
6659 canStoreInRuleTree
= false;
6660 border
->ClearBorderColors(side
);
6661 if (parentContext
) {
6662 nsBorderColors
*parentColors
;
6663 parentBorder
->GetCompositeColors(side
, &parentColors
);
6665 border
->EnsureBorderColors();
6666 border
->mBorderColors
[side
] = parentColors
->Clone();
6673 case eCSSUnit_ListDep
: {
6674 // Some composite border color information has been specified for this
6676 border
->EnsureBorderColors();
6677 border
->ClearBorderColors(side
);
6678 const nsCSSValueList
* list
= value
.GetListValue();
6680 if (SetColor(list
->mValue
, unused
, mPresContext
,
6681 aContext
, borderColor
, canStoreInRuleTree
))
6682 border
->AppendBorderColor(side
, borderColor
);
6684 NS_NOTREACHED("unexpected item in -moz-border-*-colors list");
6692 NS_ABORT_IF_FALSE(false, "unrecognized border color unit");
6696 // border-color, border-*-color: color, string, enum, inherit
6698 nsCSSRect ourBorderColor
;
6699 ourBorderColor
.mTop
= *aRuleData
->ValueForBorderTopColor();
6700 ourBorderColor
.mRight
= *aRuleData
->ValueForBorderRightColorValue();
6701 ourBorderColor
.mBottom
= *aRuleData
->ValueForBorderBottomColor();
6702 ourBorderColor
.mLeft
= *aRuleData
->ValueForBorderLeftColorValue();
6703 AdjustLogicalBoxProp(aContext
,
6704 *aRuleData
->ValueForBorderLeftColorLTRSource(),
6705 *aRuleData
->ValueForBorderLeftColorRTLSource(),
6706 *aRuleData
->ValueForBorderStartColorValue(),
6707 *aRuleData
->ValueForBorderEndColorValue(),
6708 NS_SIDE_LEFT
, ourBorderColor
, canStoreInRuleTree
);
6709 AdjustLogicalBoxProp(aContext
,
6710 *aRuleData
->ValueForBorderRightColorLTRSource(),
6711 *aRuleData
->ValueForBorderRightColorRTLSource(),
6712 *aRuleData
->ValueForBorderEndColorValue(),
6713 *aRuleData
->ValueForBorderStartColorValue(),
6714 NS_SIDE_RIGHT
, ourBorderColor
, canStoreInRuleTree
);
6715 { // scope for compilers with broken |for| loop scoping
6716 NS_FOR_CSS_SIDES(side
) {
6717 const nsCSSValue
&value
= ourBorderColor
.*(nsCSSRect::sides
[side
]);
6718 if (eCSSUnit_Inherit
== value
.GetUnit()) {
6719 canStoreInRuleTree
= false;
6720 if (parentContext
) {
6721 parentBorder
->GetBorderColor(side
, borderColor
, foreground
);
6723 // We want to inherit the color from the parent, not use the
6724 // color on the element where this chunk of style data will be
6725 // used. We can ensure that the data for the parent are fully
6726 // computed (unlike for the element where this will be used, for
6727 // which the color could be specified on a more specific rule).
6728 border
->SetBorderColor(side
, parentContext
->StyleColor()->mColor
);
6730 border
->SetBorderColor(side
, borderColor
);
6733 border
->SetBorderToForeground(side
);
6736 else if (SetColor(value
, unused
, mPresContext
, aContext
, borderColor
,
6737 canStoreInRuleTree
)) {
6738 border
->SetBorderColor(side
, borderColor
);
6740 else if (eCSSUnit_Enumerated
== value
.GetUnit()) {
6741 switch (value
.GetIntValue()) {
6742 case NS_STYLE_COLOR_MOZ_USE_TEXT_COLOR
:
6743 border
->SetBorderToForeground(side
);
6746 NS_NOTREACHED("Unexpected enumerated color");
6750 else if (eCSSUnit_Initial
== value
.GetUnit() ||
6751 eCSSUnit_Unset
== value
.GetUnit()) {
6752 border
->SetBorderToForeground(side
);
6757 // border-radius: length, percent, inherit
6759 const nsCSSProperty
* subprops
=
6760 nsCSSProps::SubpropertyEntryFor(eCSSProperty_border_radius
);
6761 NS_FOR_CSS_FULL_CORNERS(corner
) {
6762 int cx
= NS_FULL_TO_HALF_CORNER(corner
, false);
6763 int cy
= NS_FULL_TO_HALF_CORNER(corner
, true);
6764 const nsCSSValue
& radius
= *aRuleData
->ValueFor(subprops
[corner
]);
6765 nsStyleCoord parentX
= parentBorder
->mBorderRadius
.Get(cx
);
6766 nsStyleCoord parentY
= parentBorder
->mBorderRadius
.Get(cy
);
6767 nsStyleCoord coordX
, coordY
;
6769 if (SetPairCoords(radius
, coordX
, coordY
, parentX
, parentY
,
6770 SETCOORD_LPH
| SETCOORD_INITIAL_ZERO
|
6771 SETCOORD_STORE_CALC
| SETCOORD_UNSET_INITIAL
,
6772 aContext
, mPresContext
, canStoreInRuleTree
)) {
6773 border
->mBorderRadius
.Set(cx
, coordX
);
6774 border
->mBorderRadius
.Set(cy
, coordY
);
6779 // float-edge: enum, inherit, initial
6780 SetDiscrete(*aRuleData
->ValueForFloatEdge(),
6781 border
->mFloatEdge
, canStoreInRuleTree
,
6782 SETDSC_ENUMERATED
| SETDSC_UNSET_INITIAL
,
6783 parentBorder
->mFloatEdge
,
6784 NS_STYLE_FLOAT_EDGE_CONTENT
, 0, 0, 0, 0);
6786 // border-image-source
6787 const nsCSSValue
* borderImageSource
= aRuleData
->ValueForBorderImageSource();
6788 if (borderImageSource
->GetUnit() == eCSSUnit_Inherit
) {
6789 canStoreInRuleTree
= false;
6790 border
->mBorderImageSource
= parentBorder
->mBorderImageSource
;
6792 SetStyleImage(aContext
,
6794 border
->mBorderImageSource
,
6795 canStoreInRuleTree
);
6798 nsCSSValue borderImageSliceValue
;
6799 nsCSSValue borderImageSliceFill
;
6800 SetBorderImageSlice(*aRuleData
->ValueForBorderImageSlice(),
6801 borderImageSliceValue
, borderImageSliceFill
);
6803 // border-image-slice: fill
6804 SetDiscrete(borderImageSliceFill
,
6805 border
->mBorderImageFill
,
6807 SETDSC_ENUMERATED
| SETDSC_UNSET_INITIAL
,
6808 parentBorder
->mBorderImageFill
,
6809 NS_STYLE_BORDER_IMAGE_SLICE_NOFILL
, 0, 0, 0, 0);
6811 nsCSSRect borderImageSlice
;
6812 SetBorderImageRect(borderImageSliceValue
, borderImageSlice
);
6814 nsCSSRect borderImageWidth
;
6815 SetBorderImageRect(*aRuleData
->ValueForBorderImageWidth(),
6818 nsCSSRect borderImageOutset
;
6819 SetBorderImageRect(*aRuleData
->ValueForBorderImageOutset(),
6822 NS_FOR_CSS_SIDES (side
) {
6823 // border-image-slice
6824 if (SetCoord(borderImageSlice
.*(nsCSSRect::sides
[side
]), coord
,
6825 parentBorder
->mBorderImageSlice
.Get(side
),
6826 SETCOORD_FACTOR
| SETCOORD_PERCENT
|
6827 SETCOORD_INHERIT
| SETCOORD_INITIAL_HUNDRED_PCT
|
6828 SETCOORD_UNSET_INITIAL
,
6829 aContext
, mPresContext
, canStoreInRuleTree
)) {
6830 border
->mBorderImageSlice
.Set(side
, coord
);
6833 // border-image-width
6834 // 'auto' here means "same as slice"
6835 if (SetCoord(borderImageWidth
.*(nsCSSRect::sides
[side
]), coord
,
6836 parentBorder
->mBorderImageWidth
.Get(side
),
6837 SETCOORD_LPAH
| SETCOORD_FACTOR
| SETCOORD_INITIAL_FACTOR_ONE
|
6838 SETCOORD_UNSET_INITIAL
,
6839 aContext
, mPresContext
, canStoreInRuleTree
)) {
6840 border
->mBorderImageWidth
.Set(side
, coord
);
6843 // border-image-outset
6844 if (SetCoord(borderImageOutset
.*(nsCSSRect::sides
[side
]), coord
,
6845 parentBorder
->mBorderImageOutset
.Get(side
),
6846 SETCOORD_LENGTH
| SETCOORD_FACTOR
|
6847 SETCOORD_INHERIT
| SETCOORD_INITIAL_FACTOR_ZERO
|
6848 SETCOORD_UNSET_INITIAL
,
6849 aContext
, mPresContext
, canStoreInRuleTree
)) {
6850 border
->mBorderImageOutset
.Set(side
, coord
);
6854 // border-image-repeat
6855 nsCSSValuePair borderImageRepeat
;
6856 SetBorderImagePair(*aRuleData
->ValueForBorderImageRepeat(),
6859 SetDiscrete(borderImageRepeat
.mXValue
,
6860 border
->mBorderImageRepeatH
,
6862 SETDSC_ENUMERATED
| SETDSC_UNSET_INITIAL
,
6863 parentBorder
->mBorderImageRepeatH
,
6864 NS_STYLE_BORDER_IMAGE_REPEAT_STRETCH
, 0, 0, 0, 0);
6866 SetDiscrete(borderImageRepeat
.mYValue
,
6867 border
->mBorderImageRepeatV
,
6869 SETDSC_ENUMERATED
| SETDSC_UNSET_INITIAL
,
6870 parentBorder
->mBorderImageRepeatV
,
6871 NS_STYLE_BORDER_IMAGE_REPEAT_STRETCH
, 0, 0, 0, 0);
6873 border
->TrackImage(aContext
->PresContext());
6875 COMPUTE_END_RESET(Border
, border
)
6879 nsRuleNode::ComputePaddingData(void* aStartStruct
,
6880 const nsRuleData
* aRuleData
,
6881 nsStyleContext
* aContext
,
6882 nsRuleNode
* aHighestNode
,
6883 const RuleDetail aRuleDetail
,
6884 const bool aCanStoreInRuleTree
)
6886 COMPUTE_START_RESET(Padding
, (), padding
, parentPadding
)
6888 // padding: length, percent, inherit
6890 nsCSSRect ourPadding
;
6891 ourPadding
.mTop
= *aRuleData
->ValueForPaddingTop();
6892 ourPadding
.mRight
= *aRuleData
->ValueForPaddingRightValue();
6893 ourPadding
.mBottom
= *aRuleData
->ValueForPaddingBottom();
6894 ourPadding
.mLeft
= *aRuleData
->ValueForPaddingLeftValue();
6895 AdjustLogicalBoxProp(aContext
,
6896 *aRuleData
->ValueForPaddingLeftLTRSource(),
6897 *aRuleData
->ValueForPaddingLeftRTLSource(),
6898 *aRuleData
->ValueForPaddingStartValue(),
6899 *aRuleData
->ValueForPaddingEndValue(),
6900 NS_SIDE_LEFT
, ourPadding
, canStoreInRuleTree
);
6901 AdjustLogicalBoxProp(aContext
,
6902 *aRuleData
->ValueForPaddingRightLTRSource(),
6903 *aRuleData
->ValueForPaddingRightRTLSource(),
6904 *aRuleData
->ValueForPaddingEndValue(),
6905 *aRuleData
->ValueForPaddingStartValue(),
6906 NS_SIDE_RIGHT
, ourPadding
, canStoreInRuleTree
);
6907 NS_FOR_CSS_SIDES(side
) {
6908 nsStyleCoord parentCoord
= parentPadding
->mPadding
.Get(side
);
6909 if (SetCoord(ourPadding
.*(nsCSSRect::sides
[side
]),
6911 SETCOORD_LPH
| SETCOORD_INITIAL_ZERO
| SETCOORD_STORE_CALC
|
6912 SETCOORD_UNSET_INITIAL
,
6913 aContext
, mPresContext
, canStoreInRuleTree
)) {
6914 padding
->mPadding
.Set(side
, coord
);
6918 padding
->RecalcData();
6919 COMPUTE_END_RESET(Padding
, padding
)
6923 nsRuleNode::ComputeOutlineData(void* aStartStruct
,
6924 const nsRuleData
* aRuleData
,
6925 nsStyleContext
* aContext
,
6926 nsRuleNode
* aHighestNode
,
6927 const RuleDetail aRuleDetail
,
6928 const bool aCanStoreInRuleTree
)
6930 COMPUTE_START_RESET(Outline
, (mPresContext
), outline
, parentOutline
)
6932 // outline-width: length, enum, inherit
6933 const nsCSSValue
* outlineWidthValue
= aRuleData
->ValueForOutlineWidth();
6934 if (eCSSUnit_Initial
== outlineWidthValue
->GetUnit() ||
6935 eCSSUnit_Unset
== outlineWidthValue
->GetUnit()) {
6936 outline
->mOutlineWidth
=
6937 nsStyleCoord(NS_STYLE_BORDER_WIDTH_MEDIUM
, eStyleUnit_Enumerated
);
6940 SetCoord(*outlineWidthValue
, outline
->mOutlineWidth
,
6941 parentOutline
->mOutlineWidth
,
6942 SETCOORD_LEH
| SETCOORD_CALC_LENGTH_ONLY
, aContext
,
6943 mPresContext
, canStoreInRuleTree
);
6946 // outline-offset: length, inherit
6947 nsStyleCoord tempCoord
;
6948 const nsCSSValue
* outlineOffsetValue
= aRuleData
->ValueForOutlineOffset();
6949 if (SetCoord(*outlineOffsetValue
, tempCoord
,
6950 nsStyleCoord(parentOutline
->mOutlineOffset
,
6951 nsStyleCoord::CoordConstructor
),
6952 SETCOORD_LH
| SETCOORD_INITIAL_ZERO
| SETCOORD_CALC_LENGTH_ONLY
|
6953 SETCOORD_UNSET_INITIAL
,
6954 aContext
, mPresContext
, canStoreInRuleTree
)) {
6955 outline
->mOutlineOffset
= tempCoord
.GetCoordValue();
6957 NS_ASSERTION(outlineOffsetValue
->GetUnit() == eCSSUnit_Null
,
6961 // outline-color: color, string, enum, inherit
6962 nscolor outlineColor
;
6963 nscolor unused
= NS_RGB(0,0,0);
6964 const nsCSSValue
* outlineColorValue
= aRuleData
->ValueForOutlineColor();
6965 if (eCSSUnit_Inherit
== outlineColorValue
->GetUnit()) {
6966 canStoreInRuleTree
= false;
6967 if (parentContext
) {
6968 if (parentOutline
->GetOutlineColor(outlineColor
))
6969 outline
->SetOutlineColor(outlineColor
);
6971 // We want to inherit the color from the parent, not use the
6972 // color on the element where this chunk of style data will be
6973 // used. We can ensure that the data for the parent are fully
6974 // computed (unlike for the element where this will be used, for
6975 // which the color could be specified on a more specific rule).
6976 outline
->SetOutlineColor(parentContext
->StyleColor()->mColor
);
6979 outline
->SetOutlineInitialColor();
6982 else if (SetColor(*outlineColorValue
, unused
, mPresContext
,
6983 aContext
, outlineColor
, canStoreInRuleTree
))
6984 outline
->SetOutlineColor(outlineColor
);
6985 else if (eCSSUnit_Enumerated
== outlineColorValue
->GetUnit() ||
6986 eCSSUnit_Initial
== outlineColorValue
->GetUnit() ||
6987 eCSSUnit_Unset
== outlineColorValue
->GetUnit()) {
6988 outline
->SetOutlineInitialColor();
6991 // -moz-outline-radius: length, percent, inherit
6993 const nsCSSProperty
* subprops
=
6994 nsCSSProps::SubpropertyEntryFor(eCSSProperty__moz_outline_radius
);
6995 NS_FOR_CSS_FULL_CORNERS(corner
) {
6996 int cx
= NS_FULL_TO_HALF_CORNER(corner
, false);
6997 int cy
= NS_FULL_TO_HALF_CORNER(corner
, true);
6998 const nsCSSValue
& radius
= *aRuleData
->ValueFor(subprops
[corner
]);
6999 nsStyleCoord parentX
= parentOutline
->mOutlineRadius
.Get(cx
);
7000 nsStyleCoord parentY
= parentOutline
->mOutlineRadius
.Get(cy
);
7001 nsStyleCoord coordX
, coordY
;
7003 if (SetPairCoords(radius
, coordX
, coordY
, parentX
, parentY
,
7004 SETCOORD_LPH
| SETCOORD_INITIAL_ZERO
|
7005 SETCOORD_STORE_CALC
| SETCOORD_UNSET_INITIAL
,
7006 aContext
, mPresContext
, canStoreInRuleTree
)) {
7007 outline
->mOutlineRadius
.Set(cx
, coordX
);
7008 outline
->mOutlineRadius
.Set(cy
, coordY
);
7013 // outline-style: enum, inherit, initial
7014 // cannot use SetDiscrete because of SetOutlineStyle
7015 const nsCSSValue
* outlineStyleValue
= aRuleData
->ValueForOutlineStyle();
7016 nsCSSUnit unit
= outlineStyleValue
->GetUnit();
7017 NS_ABORT_IF_FALSE(eCSSUnit_None
!= unit
&& eCSSUnit_Auto
!= unit
,
7018 "'none' and 'auto' should be handled as enumerated values");
7019 if (eCSSUnit_Enumerated
== unit
) {
7020 outline
->SetOutlineStyle(outlineStyleValue
->GetIntValue());
7021 } else if (eCSSUnit_Initial
== unit
||
7022 eCSSUnit_Unset
== unit
) {
7023 outline
->SetOutlineStyle(NS_STYLE_BORDER_STYLE_NONE
);
7024 } else if (eCSSUnit_Inherit
== unit
) {
7025 canStoreInRuleTree
= false;
7026 outline
->SetOutlineStyle(parentOutline
->GetOutlineStyle());
7029 outline
->RecalcData(mPresContext
);
7030 COMPUTE_END_RESET(Outline
, outline
)
7034 nsRuleNode::ComputeListData(void* aStartStruct
,
7035 const nsRuleData
* aRuleData
,
7036 nsStyleContext
* aContext
,
7037 nsRuleNode
* aHighestNode
,
7038 const RuleDetail aRuleDetail
,
7039 const bool aCanStoreInRuleTree
)
7041 COMPUTE_START_INHERITED(List
, (mPresContext
), list
, parentList
)
7043 // list-style-type: string, none, inherit, initial
7044 const nsCSSValue
* typeValue
= aRuleData
->ValueForListStyleType();
7045 switch (typeValue
->GetUnit()) {
7046 case eCSSUnit_Unset
:
7047 case eCSSUnit_Inherit
: {
7048 canStoreInRuleTree
= false;
7050 parentList
->GetListStyleType(type
);
7051 list
->SetListStyleType(type
, parentList
->GetCounterStyle());
7054 case eCSSUnit_Initial
:
7055 list
->SetListStyleType(NS_LITERAL_STRING("disc"), mPresContext
);
7057 case eCSSUnit_Ident
: {
7059 typeValue
->GetStringValue(typeIdent
);
7060 list
->SetListStyleType(typeIdent
, mPresContext
);
7063 case eCSSUnit_Enumerated
: {
7064 // For compatibility with html attribute map.
7065 // This branch should never be called for value from CSS.
7066 int32_t intValue
= typeValue
->GetIntValue();
7069 case NS_STYLE_LIST_STYLE_LOWER_ROMAN
:
7070 name
.AssignLiteral(MOZ_UTF16("lower-roman"));
7072 case NS_STYLE_LIST_STYLE_UPPER_ROMAN
:
7073 name
.AssignLiteral(MOZ_UTF16("upper-roman"));
7075 case NS_STYLE_LIST_STYLE_LOWER_ALPHA
:
7076 name
.AssignLiteral(MOZ_UTF16("lower-alpha"));
7078 case NS_STYLE_LIST_STYLE_UPPER_ALPHA
:
7079 name
.AssignLiteral(MOZ_UTF16("upper-alpha"));
7082 CopyASCIItoUTF16(nsCSSProps::ValueToKeyword(
7083 intValue
, nsCSSProps::kListStyleKTable
), name
);
7086 list
->SetListStyleType(name
, mPresContext
);
7092 NS_NOTREACHED("Unexpected value unit");
7095 // list-style-image: url, none, inherit
7096 const nsCSSValue
* imageValue
= aRuleData
->ValueForListStyleImage();
7097 if (eCSSUnit_Image
== imageValue
->GetUnit()) {
7098 NS_SET_IMAGE_REQUEST_WITH_DOC(list
->SetListStyleImage
,
7100 imageValue
->GetImageValue
)
7102 else if (eCSSUnit_None
== imageValue
->GetUnit() ||
7103 eCSSUnit_Initial
== imageValue
->GetUnit()) {
7104 list
->SetListStyleImage(nullptr);
7106 else if (eCSSUnit_Inherit
== imageValue
->GetUnit() ||
7107 eCSSUnit_Unset
== imageValue
->GetUnit()) {
7108 canStoreInRuleTree
= false;
7109 NS_SET_IMAGE_REQUEST(list
->SetListStyleImage
,
7111 parentList
->GetListStyleImage())
7114 // list-style-position: enum, inherit, initial
7115 SetDiscrete(*aRuleData
->ValueForListStylePosition(),
7116 list
->mListStylePosition
, canStoreInRuleTree
,
7117 SETDSC_ENUMERATED
| SETDSC_UNSET_INHERIT
,
7118 parentList
->mListStylePosition
,
7119 NS_STYLE_LIST_STYLE_POSITION_OUTSIDE
, 0, 0, 0, 0);
7121 // image region property: length, auto, inherit
7122 const nsCSSValue
* imageRegionValue
= aRuleData
->ValueForImageRegion();
7123 switch (imageRegionValue
->GetUnit()) {
7124 case eCSSUnit_Inherit
:
7125 case eCSSUnit_Unset
:
7126 canStoreInRuleTree
= false;
7127 list
->mImageRegion
= parentList
->mImageRegion
;
7130 case eCSSUnit_Initial
:
7132 list
->mImageRegion
.SetRect(0,0,0,0);
7138 case eCSSUnit_Rect
: {
7139 const nsCSSRect
& rgnRect
= imageRegionValue
->GetRectValue();
7141 if (rgnRect
.mTop
.GetUnit() == eCSSUnit_Auto
)
7142 list
->mImageRegion
.y
= 0;
7143 else if (rgnRect
.mTop
.IsLengthUnit())
7144 list
->mImageRegion
.y
=
7145 CalcLength(rgnRect
.mTop
, aContext
, mPresContext
, canStoreInRuleTree
);
7147 if (rgnRect
.mBottom
.GetUnit() == eCSSUnit_Auto
)
7148 list
->mImageRegion
.height
= 0;
7149 else if (rgnRect
.mBottom
.IsLengthUnit())
7150 list
->mImageRegion
.height
=
7151 CalcLength(rgnRect
.mBottom
, aContext
, mPresContext
,
7152 canStoreInRuleTree
) - list
->mImageRegion
.y
;
7154 if (rgnRect
.mLeft
.GetUnit() == eCSSUnit_Auto
)
7155 list
->mImageRegion
.x
= 0;
7156 else if (rgnRect
.mLeft
.IsLengthUnit())
7157 list
->mImageRegion
.x
=
7158 CalcLength(rgnRect
.mLeft
, aContext
, mPresContext
, canStoreInRuleTree
);
7160 if (rgnRect
.mRight
.GetUnit() == eCSSUnit_Auto
)
7161 list
->mImageRegion
.width
= 0;
7162 else if (rgnRect
.mRight
.IsLengthUnit())
7163 list
->mImageRegion
.width
=
7164 CalcLength(rgnRect
.mRight
, aContext
, mPresContext
,
7165 canStoreInRuleTree
) - list
->mImageRegion
.x
;
7170 NS_ABORT_IF_FALSE(false, "unrecognized image-region unit");
7173 COMPUTE_END_INHERITED(List
, list
)
7177 SetGridTrackBreadth(const nsCSSValue
& aValue
,
7178 nsStyleCoord
& aResult
,
7179 nsStyleContext
* aStyleContext
,
7180 nsPresContext
* aPresContext
,
7181 bool& aCanStoreInRuleTree
)
7183 nsCSSUnit unit
= aValue
.GetUnit();
7184 if (unit
== eCSSUnit_FlexFraction
) {
7185 aResult
.SetFlexFractionValue(aValue
.GetFloatValue());
7187 MOZ_ASSERT(unit
!= eCSSUnit_Inherit
&& unit
!= eCSSUnit_Unset
,
7188 "Unexpected value that would use dummyParentCoord");
7189 const nsStyleCoord dummyParentCoord
;
7190 SetCoord(aValue
, aResult
, dummyParentCoord
,
7191 SETCOORD_LPE
| SETCOORD_STORE_CALC
,
7192 aStyleContext
, aPresContext
, aCanStoreInRuleTree
);
7197 SetGridTrackSize(const nsCSSValue
& aValue
,
7198 nsStyleCoord
& aResultMin
,
7199 nsStyleCoord
& aResultMax
,
7200 nsStyleContext
* aStyleContext
,
7201 nsPresContext
* aPresContext
,
7202 bool& aCanStoreInRuleTree
)
7204 if (aValue
.GetUnit() == eCSSUnit_Function
) {
7205 // A minmax() function.
7206 nsCSSValue::Array
* func
= aValue
.GetArrayValue();
7207 NS_ASSERTION(func
->Item(0).GetKeywordValue() == eCSSKeyword_minmax
,
7208 "Expected minmax(), got another function name");
7209 SetGridTrackBreadth(func
->Item(1), aResultMin
,
7210 aStyleContext
, aPresContext
, aCanStoreInRuleTree
);
7211 SetGridTrackBreadth(func
->Item(2), aResultMax
,
7212 aStyleContext
, aPresContext
, aCanStoreInRuleTree
);
7213 } else if (aValue
.GetUnit() == eCSSUnit_Auto
) {
7214 // 'auto' computes to 'minmax(min-content, max-content)'
7215 aResultMin
.SetIntValue(NS_STYLE_GRID_TRACK_BREADTH_MIN_CONTENT
,
7216 eStyleUnit_Enumerated
);
7217 aResultMax
.SetIntValue(NS_STYLE_GRID_TRACK_BREADTH_MAX_CONTENT
,
7218 eStyleUnit_Enumerated
);
7220 // A single <track-breadth>,
7221 // specifies identical min and max sizing functions.
7222 SetGridTrackBreadth(aValue
, aResultMin
,
7223 aStyleContext
, aPresContext
, aCanStoreInRuleTree
);
7224 aResultMax
= aResultMin
;
7229 SetGridAutoColumnsRows(const nsCSSValue
& aValue
,
7230 nsStyleCoord
& aResultMin
,
7231 nsStyleCoord
& aResultMax
,
7232 const nsStyleCoord
& aParentValueMin
,
7233 const nsStyleCoord
& aParentValueMax
,
7234 nsStyleContext
* aStyleContext
,
7235 nsPresContext
* aPresContext
,
7236 bool& aCanStoreInRuleTree
)
7239 switch (aValue
.GetUnit()) {
7243 case eCSSUnit_Inherit
:
7244 aCanStoreInRuleTree
= false;
7245 aResultMin
= aParentValueMin
;
7246 aResultMax
= aParentValueMax
;
7249 case eCSSUnit_Initial
:
7250 case eCSSUnit_Unset
:
7251 // The initial value is 'auto',
7252 // which computes to 'minmax(min-content, max-content)'.
7253 // (Explicitly-specified 'auto' values are handled in SetGridTrackSize.)
7254 aResultMin
.SetIntValue(NS_STYLE_GRID_TRACK_BREADTH_MIN_CONTENT
,
7255 eStyleUnit_Enumerated
);
7256 aResultMax
.SetIntValue(NS_STYLE_GRID_TRACK_BREADTH_MAX_CONTENT
,
7257 eStyleUnit_Enumerated
);
7261 SetGridTrackSize(aValue
, aResultMin
, aResultMax
,
7262 aStyleContext
, aPresContext
, aCanStoreInRuleTree
);
7267 AppendGridLineNames(const nsCSSValue
& aValue
,
7268 nsStyleGridTemplate
& aResult
)
7270 // Compute a <line-names> value
7271 nsTArray
<nsString
>* nameList
= aResult
.mLineNameLists
.AppendElement();
7272 // Null unit means empty list, nothing more to do.
7273 if (aValue
.GetUnit() != eCSSUnit_Null
) {
7274 const nsCSSValueList
* item
= aValue
.GetListValue();
7276 nsString
* name
= nameList
->AppendElement();
7277 item
->mValue
.GetStringValue(*name
);
7284 SetGridTrackList(const nsCSSValue
& aValue
,
7285 nsStyleGridTemplate
& aResult
,
7286 const nsStyleGridTemplate
& aParentValue
,
7287 nsStyleContext
* aStyleContext
,
7288 nsPresContext
* aPresContext
,
7289 bool& aCanStoreInRuleTree
)
7292 switch (aValue
.GetUnit()) {
7296 case eCSSUnit_Inherit
:
7297 aCanStoreInRuleTree
= false;
7298 aResult
.mIsSubgrid
= aParentValue
.mIsSubgrid
;
7299 aResult
.mLineNameLists
= aParentValue
.mLineNameLists
;
7300 aResult
.mMinTrackSizingFunctions
= aParentValue
.mMinTrackSizingFunctions
;
7301 aResult
.mMaxTrackSizingFunctions
= aParentValue
.mMaxTrackSizingFunctions
;
7304 case eCSSUnit_Initial
:
7305 case eCSSUnit_Unset
:
7307 aResult
.mIsSubgrid
= false;
7308 aResult
.mLineNameLists
.Clear();
7309 aResult
.mMinTrackSizingFunctions
.Clear();
7310 aResult
.mMaxTrackSizingFunctions
.Clear();
7314 aResult
.mLineNameLists
.Clear();
7315 aResult
.mMinTrackSizingFunctions
.Clear();
7316 aResult
.mMaxTrackSizingFunctions
.Clear();
7317 const nsCSSValueList
* item
= aValue
.GetListValue();
7318 if (item
->mValue
.GetUnit() == eCSSUnit_Enumerated
&&
7319 item
->mValue
.GetIntValue() == NS_STYLE_GRID_TEMPLATE_SUBGRID
) {
7320 // subgrid <line-name-list>?
7321 aResult
.mIsSubgrid
= true;
7324 AppendGridLineNames(item
->mValue
, aResult
);
7329 // The list is expected to have odd number of items, at least 3
7330 // starting with a <line-names> (sub list of identifiers),
7331 // and alternating between that and <track-size>.
7332 aResult
.mIsSubgrid
= false;
7334 AppendGridLineNames(item
->mValue
, aResult
);
7341 nsStyleCoord
& min
= *aResult
.mMinTrackSizingFunctions
.AppendElement();
7342 nsStyleCoord
& max
= *aResult
.mMaxTrackSizingFunctions
.AppendElement();
7343 SetGridTrackSize(item
->mValue
, min
, max
,
7344 aStyleContext
, aPresContext
, aCanStoreInRuleTree
);
7347 MOZ_ASSERT(item
, "Expected a eCSSUnit_List of odd length");
7349 MOZ_ASSERT(!aResult
.mMinTrackSizingFunctions
.IsEmpty() &&
7350 aResult
.mMinTrackSizingFunctions
.Length() ==
7351 aResult
.mMaxTrackSizingFunctions
.Length() &&
7352 aResult
.mMinTrackSizingFunctions
.Length() + 1 ==
7353 aResult
.mLineNameLists
.Length(),
7354 "Inconstistent array lengths for nsStyleGridTemplate");
7360 SetGridTemplateAreas(const nsCSSValue
& aValue
,
7361 nsRefPtr
<css::GridTemplateAreasValue
>* aResult
,
7362 css::GridTemplateAreasValue
* aParentValue
,
7363 bool& aCanStoreInRuleTree
)
7365 switch (aValue
.GetUnit()) {
7369 case eCSSUnit_Inherit
:
7370 aCanStoreInRuleTree
= false;
7371 *aResult
= aParentValue
;
7374 case eCSSUnit_Initial
:
7375 case eCSSUnit_Unset
:
7381 *aResult
= aValue
.GetGridTemplateAreas();
7386 SetGridLine(const nsCSSValue
& aValue
,
7387 nsStyleGridLine
& aResult
,
7388 const nsStyleGridLine
& aParentValue
,
7389 bool& aCanStoreInRuleTree
)
7392 switch (aValue
.GetUnit()) {
7396 case eCSSUnit_Inherit
:
7397 aCanStoreInRuleTree
= false;
7398 aResult
= aParentValue
;
7401 case eCSSUnit_Initial
:
7402 case eCSSUnit_Unset
:
7408 aResult
.SetAuto(); // Reset any existing value.
7409 const nsCSSValueList
* item
= aValue
.GetListValue();
7411 if (item
->mValue
.GetUnit() == eCSSUnit_Enumerated
) {
7412 aResult
.mHasSpan
= true;
7413 } else if (item
->mValue
.GetUnit() == eCSSUnit_Integer
) {
7414 aResult
.mInteger
= item
->mValue
.GetIntValue();
7415 } else if (item
->mValue
.GetUnit() == eCSSUnit_Ident
) {
7416 item
->mValue
.GetStringValue(aResult
.mLineName
);
7418 NS_ASSERTION(false, "Unexpected unit");
7422 MOZ_ASSERT(!aResult
.IsAuto(),
7423 "should have set something away from default value");
7428 nsRuleNode::ComputePositionData(void* aStartStruct
,
7429 const nsRuleData
* aRuleData
,
7430 nsStyleContext
* aContext
,
7431 nsRuleNode
* aHighestNode
,
7432 const RuleDetail aRuleDetail
,
7433 const bool aCanStoreInRuleTree
)
7435 COMPUTE_START_RESET(Position
, (), pos
, parentPos
)
7437 // box offsets: length, percent, calc, auto, inherit
7438 static const nsCSSProperty offsetProps
[] = {
7441 eCSSProperty_bottom
,
7445 NS_FOR_CSS_SIDES(side
) {
7446 nsStyleCoord parentCoord
= parentPos
->mOffset
.Get(side
);
7447 if (SetCoord(*aRuleData
->ValueFor(offsetProps
[side
]),
7449 SETCOORD_LPAH
| SETCOORD_INITIAL_AUTO
| SETCOORD_STORE_CALC
|
7450 SETCOORD_UNSET_INITIAL
,
7451 aContext
, mPresContext
, canStoreInRuleTree
)) {
7452 pos
->mOffset
.Set(side
, coord
);
7456 SetCoord(*aRuleData
->ValueForWidth(), pos
->mWidth
, parentPos
->mWidth
,
7457 SETCOORD_LPAEH
| SETCOORD_INITIAL_AUTO
| SETCOORD_STORE_CALC
|
7458 SETCOORD_UNSET_INITIAL
,
7459 aContext
, mPresContext
, canStoreInRuleTree
);
7460 SetCoord(*aRuleData
->ValueForMinWidth(), pos
->mMinWidth
, parentPos
->mMinWidth
,
7461 SETCOORD_LPAEH
| SETCOORD_INITIAL_AUTO
| SETCOORD_STORE_CALC
|
7462 SETCOORD_UNSET_INITIAL
,
7463 aContext
, mPresContext
, canStoreInRuleTree
);
7464 SetCoord(*aRuleData
->ValueForMaxWidth(), pos
->mMaxWidth
, parentPos
->mMaxWidth
,
7465 SETCOORD_LPOEH
| SETCOORD_INITIAL_NONE
| SETCOORD_STORE_CALC
|
7466 SETCOORD_UNSET_INITIAL
,
7467 aContext
, mPresContext
, canStoreInRuleTree
);
7469 SetCoord(*aRuleData
->ValueForHeight(), pos
->mHeight
, parentPos
->mHeight
,
7470 SETCOORD_LPAH
| SETCOORD_INITIAL_AUTO
| SETCOORD_STORE_CALC
|
7471 SETCOORD_UNSET_INITIAL
,
7472 aContext
, mPresContext
, canStoreInRuleTree
);
7473 SetCoord(*aRuleData
->ValueForMinHeight(), pos
->mMinHeight
, parentPos
->mMinHeight
,
7474 SETCOORD_LPAH
| SETCOORD_INITIAL_AUTO
| SETCOORD_STORE_CALC
|
7475 SETCOORD_UNSET_INITIAL
,
7476 aContext
, mPresContext
, canStoreInRuleTree
);
7477 SetCoord(*aRuleData
->ValueForMaxHeight(), pos
->mMaxHeight
, parentPos
->mMaxHeight
,
7478 SETCOORD_LPOH
| SETCOORD_INITIAL_NONE
| SETCOORD_STORE_CALC
|
7479 SETCOORD_UNSET_INITIAL
,
7480 aContext
, mPresContext
, canStoreInRuleTree
);
7482 // box-sizing: enum, inherit, initial
7483 SetDiscrete(*aRuleData
->ValueForBoxSizing(),
7484 pos
->mBoxSizing
, canStoreInRuleTree
,
7485 SETDSC_ENUMERATED
| SETDSC_UNSET_INITIAL
,
7486 parentPos
->mBoxSizing
,
7487 NS_STYLE_BOX_SIZING_CONTENT
, 0, 0, 0, 0);
7489 // align-content: enum, inherit, initial
7490 SetDiscrete(*aRuleData
->ValueForAlignContent(),
7491 pos
->mAlignContent
, canStoreInRuleTree
,
7492 SETDSC_ENUMERATED
| SETDSC_UNSET_INITIAL
,
7493 parentPos
->mAlignContent
,
7494 NS_STYLE_ALIGN_CONTENT_STRETCH
, 0, 0, 0, 0);
7496 // align-items: enum, inherit, initial
7497 SetDiscrete(*aRuleData
->ValueForAlignItems(),
7498 pos
->mAlignItems
, canStoreInRuleTree
,
7499 SETDSC_ENUMERATED
| SETDSC_UNSET_INITIAL
,
7500 parentPos
->mAlignItems
,
7501 NS_STYLE_ALIGN_ITEMS_INITIAL_VALUE
, 0, 0, 0, 0);
7503 // align-self: enum, inherit, initial
7504 // NOTE: align-self's initial value is the special keyword "auto", which is
7505 // supposed to compute to our parent's computed value of "align-items". So
7506 // technically, "auto" itself is never a valid computed value for align-self,
7507 // since it always computes to something else. Despite that, we do actually
7508 // store "auto" in nsStylePosition::mAlignSelf, as NS_STYLE_ALIGN_SELF_AUTO
7509 // (and then resolve it as-necessary). We do this because "auto" is the
7510 // initial value for this property, so if we were to actually resolve it in
7511 // nsStylePosition, we'd never be able to share any nsStylePosition structs
7512 // in the rule tree, since their mAlignSelf values would depend on the parent
7513 // style, by default.
7514 if (aRuleData
->ValueForAlignSelf()->GetUnit() == eCSSUnit_Inherit
) {
7515 // Special handling for "align-self: inherit", in case we're inheriting
7516 // "align-self: auto", in which case we need to resolve the parent's "auto"
7517 // and inherit that resolved value.
7518 uint8_t inheritedAlignSelf
= parentPos
->mAlignSelf
;
7519 if (inheritedAlignSelf
== NS_STYLE_ALIGN_SELF_AUTO
) {
7520 if (!parentContext
) {
7521 // We're the root node. Nothing to inherit from --> just use default
7523 inheritedAlignSelf
= NS_STYLE_ALIGN_ITEMS_INITIAL_VALUE
;
7525 // Our parent's "auto" value should resolve to our grandparent's value
7526 // for "align-items". So, that's what we're supposed to inherit.
7527 nsStyleContext
* grandparentContext
= parentContext
->GetParent();
7528 if (!grandparentContext
) {
7529 // No grandparent --> our parent is the root node, so its
7530 // "align-self: auto" computes to the default "align-items" value:
7531 inheritedAlignSelf
= NS_STYLE_ALIGN_ITEMS_INITIAL_VALUE
;
7533 // Normal case -- we have a grandparent.
7534 // Its "align-items" value is what we should end up inheriting.
7535 const nsStylePosition
* grandparentPos
=
7536 grandparentContext
->StylePosition();
7537 inheritedAlignSelf
= grandparentPos
->mAlignItems
;
7542 pos
->mAlignSelf
= inheritedAlignSelf
;
7543 canStoreInRuleTree
= false;
7545 SetDiscrete(*aRuleData
->ValueForAlignSelf(),
7546 pos
->mAlignSelf
, canStoreInRuleTree
,
7547 SETDSC_ENUMERATED
| SETDSC_UNSET_INITIAL
,
7548 parentPos
->mAlignSelf
, // (unused -- we handled inherit above)
7549 NS_STYLE_ALIGN_SELF_AUTO
, // initial == auto
7553 // flex-basis: auto, length, percent, enum, calc, inherit, initial
7554 // (Note: The flags here should match those used for 'width' property above.)
7555 SetCoord(*aRuleData
->ValueForFlexBasis(), pos
->mFlexBasis
, parentPos
->mFlexBasis
,
7556 SETCOORD_LPAEH
| SETCOORD_INITIAL_AUTO
| SETCOORD_STORE_CALC
|
7557 SETCOORD_UNSET_INITIAL
,
7558 aContext
, mPresContext
, canStoreInRuleTree
);
7560 // flex-direction: enum, inherit, initial
7561 SetDiscrete(*aRuleData
->ValueForFlexDirection(),
7562 pos
->mFlexDirection
, canStoreInRuleTree
,
7563 SETDSC_ENUMERATED
| SETDSC_UNSET_INITIAL
,
7564 parentPos
->mFlexDirection
,
7565 NS_STYLE_FLEX_DIRECTION_ROW
, 0, 0, 0, 0);
7567 // flex-grow: float, inherit, initial
7568 SetFactor(*aRuleData
->ValueForFlexGrow(),
7569 pos
->mFlexGrow
, canStoreInRuleTree
,
7570 parentPos
->mFlexGrow
, 0.0f
,
7571 SETFCT_UNSET_INITIAL
);
7573 // flex-shrink: float, inherit, initial
7574 SetFactor(*aRuleData
->ValueForFlexShrink(),
7575 pos
->mFlexShrink
, canStoreInRuleTree
,
7576 parentPos
->mFlexShrink
, 1.0f
,
7577 SETFCT_UNSET_INITIAL
);
7579 // flex-wrap: enum, inherit, initial
7580 SetDiscrete(*aRuleData
->ValueForFlexWrap(),
7581 pos
->mFlexWrap
, canStoreInRuleTree
,
7582 SETDSC_ENUMERATED
| SETDSC_UNSET_INITIAL
,
7583 parentPos
->mFlexWrap
,
7584 NS_STYLE_FLEX_WRAP_NOWRAP
, 0, 0, 0, 0);
7586 // order: integer, inherit, initial
7587 SetDiscrete(*aRuleData
->ValueForOrder(),
7588 pos
->mOrder
, canStoreInRuleTree
,
7589 SETDSC_INTEGER
| SETDSC_UNSET_INITIAL
,
7591 NS_STYLE_ORDER_INITIAL
, 0, 0, 0, 0);
7593 // justify-content: enum, inherit, initial
7594 SetDiscrete(*aRuleData
->ValueForJustifyContent(),
7595 pos
->mJustifyContent
, canStoreInRuleTree
,
7596 SETDSC_ENUMERATED
| SETDSC_UNSET_INITIAL
,
7597 parentPos
->mJustifyContent
,
7598 NS_STYLE_JUSTIFY_CONTENT_FLEX_START
, 0, 0, 0, 0);
7601 const nsCSSValue
& gridAutoFlow
= *aRuleData
->ValueForGridAutoFlow();
7602 switch (gridAutoFlow
.GetUnit()) {
7605 case eCSSUnit_Inherit
:
7606 canStoreInRuleTree
= false;
7607 pos
->mGridAutoFlow
= parentPos
->mGridAutoFlow
;
7609 case eCSSUnit_Initial
:
7610 case eCSSUnit_Unset
:
7611 pos
->mGridAutoFlow
= NS_STYLE_GRID_AUTO_FLOW_ROW
;
7614 NS_ASSERTION(gridAutoFlow
.GetUnit() == eCSSUnit_Enumerated
,
7616 pos
->mGridAutoFlow
= gridAutoFlow
.GetIntValue();
7619 // grid-auto-columns
7620 SetGridAutoColumnsRows(*aRuleData
->ValueForGridAutoColumns(),
7621 pos
->mGridAutoColumnsMin
,
7622 pos
->mGridAutoColumnsMax
,
7623 parentPos
->mGridAutoColumnsMin
,
7624 parentPos
->mGridAutoColumnsMax
,
7625 aContext
, mPresContext
, canStoreInRuleTree
);
7628 SetGridAutoColumnsRows(*aRuleData
->ValueForGridAutoRows(),
7629 pos
->mGridAutoRowsMin
,
7630 pos
->mGridAutoRowsMax
,
7631 parentPos
->mGridAutoRowsMin
,
7632 parentPos
->mGridAutoRowsMax
,
7633 aContext
, mPresContext
, canStoreInRuleTree
);
7635 // grid-template-columns
7636 SetGridTrackList(*aRuleData
->ValueForGridTemplateColumns(),
7637 pos
->mGridTemplateColumns
, parentPos
->mGridTemplateColumns
,
7638 aContext
, mPresContext
, canStoreInRuleTree
);
7640 // grid-template-rows
7641 SetGridTrackList(*aRuleData
->ValueForGridTemplateRows(),
7642 pos
->mGridTemplateRows
, parentPos
->mGridTemplateRows
,
7643 aContext
, mPresContext
, canStoreInRuleTree
);
7645 // grid-tempate-areas
7646 SetGridTemplateAreas(*aRuleData
->ValueForGridTemplateAreas(),
7647 &pos
->mGridTemplateAreas
,
7648 parentPos
->mGridTemplateAreas
,
7649 canStoreInRuleTree
);
7651 // grid-column-start
7652 SetGridLine(*aRuleData
->ValueForGridColumnStart(),
7653 pos
->mGridColumnStart
,
7654 parentPos
->mGridColumnStart
,
7655 canStoreInRuleTree
);
7658 SetGridLine(*aRuleData
->ValueForGridColumnEnd(),
7659 pos
->mGridColumnEnd
,
7660 parentPos
->mGridColumnEnd
,
7661 canStoreInRuleTree
);
7664 SetGridLine(*aRuleData
->ValueForGridRowStart(),
7666 parentPos
->mGridRowStart
,
7667 canStoreInRuleTree
);
7670 SetGridLine(*aRuleData
->ValueForGridRowEnd(),
7672 parentPos
->mGridRowEnd
,
7673 canStoreInRuleTree
);
7676 const nsCSSValue
* zIndexValue
= aRuleData
->ValueForZIndex();
7677 if (! SetCoord(*zIndexValue
, pos
->mZIndex
, parentPos
->mZIndex
,
7678 SETCOORD_IA
| SETCOORD_INITIAL_AUTO
| SETCOORD_UNSET_INITIAL
,
7679 aContext
, nullptr, canStoreInRuleTree
)) {
7680 if (eCSSUnit_Inherit
== zIndexValue
->GetUnit()) {
7681 // handle inherit, because it's ok to inherit 'auto' here
7682 canStoreInRuleTree
= false;
7683 pos
->mZIndex
= parentPos
->mZIndex
;
7687 COMPUTE_END_RESET(Position
, pos
)
7691 nsRuleNode::ComputeTableData(void* aStartStruct
,
7692 const nsRuleData
* aRuleData
,
7693 nsStyleContext
* aContext
,
7694 nsRuleNode
* aHighestNode
,
7695 const RuleDetail aRuleDetail
,
7696 const bool aCanStoreInRuleTree
)
7698 COMPUTE_START_RESET(Table
, (), table
, parentTable
)
7700 // table-layout: enum, inherit, initial
7701 SetDiscrete(*aRuleData
->ValueForTableLayout(),
7702 table
->mLayoutStrategy
, canStoreInRuleTree
,
7703 SETDSC_ENUMERATED
| SETDSC_UNSET_INITIAL
,
7704 parentTable
->mLayoutStrategy
,
7705 NS_STYLE_TABLE_LAYOUT_AUTO
, 0, 0, 0, 0);
7707 // span: pixels (not a real CSS prop)
7708 const nsCSSValue
* spanValue
= aRuleData
->ValueForSpan();
7709 if (eCSSUnit_Enumerated
== spanValue
->GetUnit() ||
7710 eCSSUnit_Integer
== spanValue
->GetUnit())
7711 table
->mSpan
= spanValue
->GetIntValue();
7713 COMPUTE_END_RESET(Table
, table
)
7717 nsRuleNode::ComputeTableBorderData(void* aStartStruct
,
7718 const nsRuleData
* aRuleData
,
7719 nsStyleContext
* aContext
,
7720 nsRuleNode
* aHighestNode
,
7721 const RuleDetail aRuleDetail
,
7722 const bool aCanStoreInRuleTree
)
7724 COMPUTE_START_INHERITED(TableBorder
, (mPresContext
), table
, parentTable
)
7726 // border-collapse: enum, inherit, initial
7727 SetDiscrete(*aRuleData
->ValueForBorderCollapse(), table
->mBorderCollapse
,
7729 SETDSC_ENUMERATED
| SETDSC_UNSET_INHERIT
,
7730 parentTable
->mBorderCollapse
,
7731 NS_STYLE_BORDER_SEPARATE
, 0, 0, 0, 0);
7733 const nsCSSValue
* borderSpacingValue
= aRuleData
->ValueForBorderSpacing();
7734 if (borderSpacingValue
->GetUnit() != eCSSUnit_Null
) {
7735 // border-spacing-x/y: length, inherit
7736 nsStyleCoord
parentX(parentTable
->mBorderSpacingX
,
7737 nsStyleCoord::CoordConstructor
);
7738 nsStyleCoord
parentY(parentTable
->mBorderSpacingY
,
7739 nsStyleCoord::CoordConstructor
);
7740 nsStyleCoord coordX
, coordY
;
7745 SetPairCoords(*borderSpacingValue
,
7746 coordX
, coordY
, parentX
, parentY
,
7747 SETCOORD_LH
| SETCOORD_INITIAL_ZERO
|
7748 SETCOORD_CALC_LENGTH_ONLY
|
7749 SETCOORD_CALC_CLAMP_NONNEGATIVE
| SETCOORD_UNSET_INHERIT
,
7750 aContext
, mPresContext
, canStoreInRuleTree
);
7751 NS_ASSERTION(result
, "malformed table border value");
7752 table
->mBorderSpacingX
= coordX
.GetCoordValue();
7753 table
->mBorderSpacingY
= coordY
.GetCoordValue();
7756 // caption-side: enum, inherit, initial
7757 SetDiscrete(*aRuleData
->ValueForCaptionSide(),
7758 table
->mCaptionSide
, canStoreInRuleTree
,
7759 SETDSC_ENUMERATED
| SETDSC_UNSET_INHERIT
,
7760 parentTable
->mCaptionSide
,
7761 NS_STYLE_CAPTION_SIDE_TOP
, 0, 0, 0, 0);
7763 // empty-cells: enum, inherit, initial
7764 SetDiscrete(*aRuleData
->ValueForEmptyCells(),
7765 table
->mEmptyCells
, canStoreInRuleTree
,
7766 SETDSC_ENUMERATED
| SETDSC_UNSET_INHERIT
,
7767 parentTable
->mEmptyCells
,
7768 (mPresContext
->CompatibilityMode() == eCompatibility_NavQuirks
)
7769 ? NS_STYLE_TABLE_EMPTY_CELLS_SHOW_BACKGROUND
7770 : NS_STYLE_TABLE_EMPTY_CELLS_SHOW
,
7773 COMPUTE_END_INHERITED(TableBorder
, table
)
7777 nsRuleNode::ComputeContentData(void* aStartStruct
,
7778 const nsRuleData
* aRuleData
,
7779 nsStyleContext
* aContext
,
7780 nsRuleNode
* aHighestNode
,
7781 const RuleDetail aRuleDetail
,
7782 const bool aCanStoreInRuleTree
)
7785 nsAutoString buffer
;
7787 COMPUTE_START_RESET(Content
, (), content
, parentContent
)
7789 // content: [string, url, counter, attr, enum]+, normal, none, inherit
7790 const nsCSSValue
* contentValue
= aRuleData
->ValueForContent();
7791 switch (contentValue
->GetUnit()) {
7795 case eCSSUnit_Normal
:
7797 case eCSSUnit_Initial
:
7798 case eCSSUnit_Unset
:
7799 // "normal", "none", "initial" and "unset" all mean no content
7800 content
->AllocateContents(0);
7803 case eCSSUnit_Inherit
:
7804 canStoreInRuleTree
= false;
7805 count
= parentContent
->ContentCount();
7806 if (NS_SUCCEEDED(content
->AllocateContents(count
))) {
7807 while (0 < count
--) {
7808 content
->ContentAt(count
) = parentContent
->ContentAt(count
);
7813 case eCSSUnit_Enumerated
: {
7814 NS_ABORT_IF_FALSE(contentValue
->GetIntValue() ==
7815 NS_STYLE_CONTENT_ALT_CONTENT
,
7816 "unrecognized solitary content keyword");
7817 content
->AllocateContents(1);
7818 nsStyleContentData
& data
= content
->ContentAt(0);
7819 data
.mType
= eStyleContentType_AltContent
;
7820 data
.mContent
.mString
= nullptr;
7825 case eCSSUnit_ListDep
: {
7826 const nsCSSValueList
* contentValueList
= contentValue
->GetListValue();
7828 while (contentValueList
) {
7830 contentValueList
= contentValueList
->mNext
;
7832 if (NS_SUCCEEDED(content
->AllocateContents(count
))) {
7833 const nsAutoString nullStr
;
7835 contentValueList
= contentValue
->GetListValue();
7836 while (contentValueList
) {
7837 const nsCSSValue
& value
= contentValueList
->mValue
;
7838 nsCSSUnit unit
= value
.GetUnit();
7839 nsStyleContentType type
;
7840 nsStyleContentData
&data
= content
->ContentAt(count
++);
7842 case eCSSUnit_String
: type
= eStyleContentType_String
; break;
7843 case eCSSUnit_Image
: type
= eStyleContentType_Image
; break;
7844 case eCSSUnit_Attr
: type
= eStyleContentType_Attr
; break;
7845 case eCSSUnit_Counter
: type
= eStyleContentType_Counter
; break;
7846 case eCSSUnit_Counters
: type
= eStyleContentType_Counters
; break;
7847 case eCSSUnit_Enumerated
:
7848 switch (value
.GetIntValue()) {
7849 case NS_STYLE_CONTENT_OPEN_QUOTE
:
7850 type
= eStyleContentType_OpenQuote
; break;
7851 case NS_STYLE_CONTENT_CLOSE_QUOTE
:
7852 type
= eStyleContentType_CloseQuote
; break;
7853 case NS_STYLE_CONTENT_NO_OPEN_QUOTE
:
7854 type
= eStyleContentType_NoOpenQuote
; break;
7855 case NS_STYLE_CONTENT_NO_CLOSE_QUOTE
:
7856 type
= eStyleContentType_NoCloseQuote
; break;
7858 NS_ERROR("bad content value");
7859 type
= eStyleContentType_Uninitialized
;
7863 NS_ERROR("bad content type");
7864 type
= eStyleContentType_Uninitialized
;
7867 if (type
== eStyleContentType_Image
) {
7868 NS_SET_IMAGE_REQUEST_WITH_DOC(data
.SetImage
,
7870 value
.GetImageValue
);
7872 else if (type
<= eStyleContentType_Attr
) {
7873 value
.GetStringValue(buffer
);
7874 data
.mContent
.mString
= NS_strdup(buffer
.get());
7876 else if (type
<= eStyleContentType_Counters
) {
7877 data
.mContent
.mCounters
= value
.GetArrayValue();
7878 data
.mContent
.mCounters
->AddRef();
7881 data
.mContent
.mString
= nullptr;
7883 contentValueList
= contentValueList
->mNext
;
7890 NS_ABORT_IF_FALSE(false,
7891 nsPrintfCString("unrecognized content unit %d",
7892 contentValue
->GetUnit()).get());
7895 // counter-increment: [string [int]]+, none, inherit
7896 const nsCSSValue
* counterIncrementValue
=
7897 aRuleData
->ValueForCounterIncrement();
7898 switch (counterIncrementValue
->GetUnit()) {
7903 case eCSSUnit_Initial
:
7904 case eCSSUnit_Unset
:
7905 content
->AllocateCounterIncrements(0);
7908 case eCSSUnit_Inherit
:
7909 canStoreInRuleTree
= false;
7910 count
= parentContent
->CounterIncrementCount();
7911 if (NS_SUCCEEDED(content
->AllocateCounterIncrements(count
))) {
7912 while (0 < count
--) {
7913 const nsStyleCounterData
*data
=
7914 parentContent
->GetCounterIncrementAt(count
);
7915 content
->SetCounterIncrementAt(count
, data
->mCounter
, data
->mValue
);
7920 case eCSSUnit_PairList
:
7921 case eCSSUnit_PairListDep
: {
7922 const nsCSSValuePairList
* ourIncrement
=
7923 counterIncrementValue
->GetPairListValue();
7924 NS_ABORT_IF_FALSE(ourIncrement
->mXValue
.GetUnit() == eCSSUnit_Ident
,
7925 "unexpected value unit");
7926 count
= ListLength(ourIncrement
);
7927 if (NS_FAILED(content
->AllocateCounterIncrements(count
))) {
7932 for (const nsCSSValuePairList
* p
= ourIncrement
; p
; p
= p
->mNext
, count
++) {
7934 if (p
->mYValue
.GetUnit() == eCSSUnit_Integer
) {
7935 increment
= p
->mYValue
.GetIntValue();
7939 p
->mXValue
.GetStringValue(buffer
);
7940 content
->SetCounterIncrementAt(count
, buffer
, increment
);
7946 NS_ABORT_IF_FALSE(false, "unexpected value unit");
7949 // counter-reset: [string [int]]+, none, inherit
7950 const nsCSSValue
* counterResetValue
= aRuleData
->ValueForCounterReset();
7951 switch (counterResetValue
->GetUnit()) {
7956 case eCSSUnit_Initial
:
7957 case eCSSUnit_Unset
:
7958 content
->AllocateCounterResets(0);
7961 case eCSSUnit_Inherit
:
7962 canStoreInRuleTree
= false;
7963 count
= parentContent
->CounterResetCount();
7964 if (NS_SUCCEEDED(content
->AllocateCounterResets(count
))) {
7965 while (0 < count
--) {
7966 const nsStyleCounterData
*data
=
7967 parentContent
->GetCounterResetAt(count
);
7968 content
->SetCounterResetAt(count
, data
->mCounter
, data
->mValue
);
7973 case eCSSUnit_PairList
:
7974 case eCSSUnit_PairListDep
: {
7975 const nsCSSValuePairList
* ourReset
=
7976 counterResetValue
->GetPairListValue();
7977 NS_ABORT_IF_FALSE(ourReset
->mXValue
.GetUnit() == eCSSUnit_Ident
,
7978 "unexpected value unit");
7979 count
= ListLength(ourReset
);
7980 if (NS_FAILED(content
->AllocateCounterResets(count
))) {
7985 for (const nsCSSValuePairList
* p
= ourReset
; p
; p
= p
->mNext
, count
++) {
7987 if (p
->mYValue
.GetUnit() == eCSSUnit_Integer
) {
7988 reset
= p
->mYValue
.GetIntValue();
7992 p
->mXValue
.GetStringValue(buffer
);
7993 content
->SetCounterResetAt(count
, buffer
, reset
);
7999 NS_ABORT_IF_FALSE(false, "unexpected value unit");
8002 // marker-offset: length, auto, inherit
8003 SetCoord(*aRuleData
->ValueForMarkerOffset(), content
->mMarkerOffset
, parentContent
->mMarkerOffset
,
8004 SETCOORD_LH
| SETCOORD_AUTO
| SETCOORD_INITIAL_AUTO
|
8005 SETCOORD_CALC_LENGTH_ONLY
| SETCOORD_UNSET_INITIAL
,
8006 aContext
, mPresContext
, canStoreInRuleTree
);
8008 // If we ended up with an image, track it.
8009 for (uint32_t i
= 0; i
< content
->ContentCount(); ++i
) {
8010 if ((content
->ContentAt(i
).mType
== eStyleContentType_Image
) &&
8011 content
->ContentAt(i
).mContent
.mImage
) {
8012 content
->ContentAt(i
).TrackImage(aContext
->PresContext());
8016 COMPUTE_END_RESET(Content
, content
)
8020 nsRuleNode::ComputeQuotesData(void* aStartStruct
,
8021 const nsRuleData
* aRuleData
,
8022 nsStyleContext
* aContext
,
8023 nsRuleNode
* aHighestNode
,
8024 const RuleDetail aRuleDetail
,
8025 const bool aCanStoreInRuleTree
)
8027 COMPUTE_START_INHERITED(Quotes
, (), quotes
, parentQuotes
)
8029 // quotes: inherit, initial, none, [string string]+
8030 const nsCSSValue
* quotesValue
= aRuleData
->ValueForQuotes();
8031 switch (quotesValue
->GetUnit()) {
8034 case eCSSUnit_Inherit
:
8035 case eCSSUnit_Unset
:
8036 canStoreInRuleTree
= false;
8037 quotes
->CopyFrom(*parentQuotes
);
8039 case eCSSUnit_Initial
:
8040 quotes
->SetInitial();
8043 quotes
->AllocateQuotes(0);
8045 case eCSSUnit_PairList
:
8046 case eCSSUnit_PairListDep
: {
8047 const nsCSSValuePairList
* ourQuotes
8048 = quotesValue
->GetPairListValue();
8049 nsAutoString buffer
;
8050 nsAutoString closeBuffer
;
8051 uint32_t count
= ListLength(ourQuotes
);
8052 if (NS_FAILED(quotes
->AllocateQuotes(count
))) {
8057 NS_ABORT_IF_FALSE(ourQuotes
->mXValue
.GetUnit() == eCSSUnit_String
&&
8058 ourQuotes
->mYValue
.GetUnit() == eCSSUnit_String
,
8059 "improper list contents for quotes");
8060 ourQuotes
->mXValue
.GetStringValue(buffer
);
8061 ourQuotes
->mYValue
.GetStringValue(closeBuffer
);
8062 quotes
->SetQuotesAt(count
++, buffer
, closeBuffer
);
8063 ourQuotes
= ourQuotes
->mNext
;
8068 NS_ABORT_IF_FALSE(false, "unexpected value unit");
8071 COMPUTE_END_INHERITED(Quotes
, quotes
)
8075 nsRuleNode::ComputeXULData(void* aStartStruct
,
8076 const nsRuleData
* aRuleData
,
8077 nsStyleContext
* aContext
,
8078 nsRuleNode
* aHighestNode
,
8079 const RuleDetail aRuleDetail
,
8080 const bool aCanStoreInRuleTree
)
8082 COMPUTE_START_RESET(XUL
, (), xul
, parentXUL
)
8084 // box-align: enum, inherit, initial
8085 SetDiscrete(*aRuleData
->ValueForBoxAlign(),
8086 xul
->mBoxAlign
, canStoreInRuleTree
,
8087 SETDSC_ENUMERATED
| SETDSC_UNSET_INITIAL
,
8088 parentXUL
->mBoxAlign
,
8089 NS_STYLE_BOX_ALIGN_STRETCH
, 0, 0, 0, 0);
8091 // box-direction: enum, inherit, initial
8092 SetDiscrete(*aRuleData
->ValueForBoxDirection(),
8093 xul
->mBoxDirection
, canStoreInRuleTree
,
8094 SETDSC_ENUMERATED
| SETDSC_UNSET_INITIAL
,
8095 parentXUL
->mBoxDirection
,
8096 NS_STYLE_BOX_DIRECTION_NORMAL
, 0, 0, 0, 0);
8098 // box-flex: factor, inherit
8099 SetFactor(*aRuleData
->ValueForBoxFlex(),
8100 xul
->mBoxFlex
, canStoreInRuleTree
,
8101 parentXUL
->mBoxFlex
, 0.0f
,
8102 SETFCT_UNSET_INITIAL
);
8104 // box-orient: enum, inherit, initial
8105 SetDiscrete(*aRuleData
->ValueForBoxOrient(),
8106 xul
->mBoxOrient
, canStoreInRuleTree
,
8107 SETDSC_ENUMERATED
| SETDSC_UNSET_INITIAL
,
8108 parentXUL
->mBoxOrient
,
8109 NS_STYLE_BOX_ORIENT_HORIZONTAL
, 0, 0, 0, 0);
8111 // box-pack: enum, inherit, initial
8112 SetDiscrete(*aRuleData
->ValueForBoxPack(),
8113 xul
->mBoxPack
, canStoreInRuleTree
,
8114 SETDSC_ENUMERATED
| SETDSC_UNSET_INITIAL
,
8115 parentXUL
->mBoxPack
,
8116 NS_STYLE_BOX_PACK_START
, 0, 0, 0, 0);
8118 // box-ordinal-group: integer, inherit, initial
8119 SetDiscrete(*aRuleData
->ValueForBoxOrdinalGroup(),
8120 xul
->mBoxOrdinal
, canStoreInRuleTree
,
8121 SETDSC_INTEGER
| SETDSC_UNSET_INITIAL
,
8122 parentXUL
->mBoxOrdinal
, 1,
8125 const nsCSSValue
* stackSizingValue
= aRuleData
->ValueForStackSizing();
8126 if (eCSSUnit_Inherit
== stackSizingValue
->GetUnit()) {
8127 canStoreInRuleTree
= false;
8128 xul
->mStretchStack
= parentXUL
->mStretchStack
;
8129 } else if (eCSSUnit_Initial
== stackSizingValue
->GetUnit() ||
8130 eCSSUnit_Unset
== stackSizingValue
->GetUnit()) {
8131 xul
->mStretchStack
= true;
8132 } else if (eCSSUnit_Enumerated
== stackSizingValue
->GetUnit()) {
8133 xul
->mStretchStack
= stackSizingValue
->GetIntValue() ==
8134 NS_STYLE_STACK_SIZING_STRETCH_TO_FIT
;
8137 COMPUTE_END_RESET(XUL
, xul
)
8141 nsRuleNode::ComputeColumnData(void* aStartStruct
,
8142 const nsRuleData
* aRuleData
,
8143 nsStyleContext
* aContext
,
8144 nsRuleNode
* aHighestNode
,
8145 const RuleDetail aRuleDetail
,
8146 const bool aCanStoreInRuleTree
)
8148 COMPUTE_START_RESET(Column
, (mPresContext
), column
, parent
)
8150 // column-width: length, auto, inherit
8151 SetCoord(*aRuleData
->ValueForColumnWidth(),
8152 column
->mColumnWidth
, parent
->mColumnWidth
,
8153 SETCOORD_LAH
| SETCOORD_INITIAL_AUTO
|
8154 SETCOORD_CALC_LENGTH_ONLY
| SETCOORD_CALC_CLAMP_NONNEGATIVE
|
8155 SETCOORD_UNSET_INITIAL
,
8156 aContext
, mPresContext
, canStoreInRuleTree
);
8158 // column-gap: length, inherit, normal
8159 SetCoord(*aRuleData
->ValueForColumnGap(),
8160 column
->mColumnGap
, parent
->mColumnGap
,
8161 SETCOORD_LH
| SETCOORD_NORMAL
| SETCOORD_INITIAL_NORMAL
|
8162 SETCOORD_CALC_LENGTH_ONLY
| SETCOORD_UNSET_INITIAL
,
8163 aContext
, mPresContext
, canStoreInRuleTree
);
8164 // clamp negative calc() to 0
8165 if (column
->mColumnGap
.GetUnit() == eStyleUnit_Coord
) {
8166 column
->mColumnGap
.SetCoordValue(
8167 std::max(column
->mColumnGap
.GetCoordValue(), 0));
8170 // column-count: auto, integer, inherit
8171 const nsCSSValue
* columnCountValue
= aRuleData
->ValueForColumnCount();
8172 if (eCSSUnit_Auto
== columnCountValue
->GetUnit() ||
8173 eCSSUnit_Initial
== columnCountValue
->GetUnit() ||
8174 eCSSUnit_Unset
== columnCountValue
->GetUnit()) {
8175 column
->mColumnCount
= NS_STYLE_COLUMN_COUNT_AUTO
;
8176 } else if (eCSSUnit_Integer
== columnCountValue
->GetUnit()) {
8177 column
->mColumnCount
= columnCountValue
->GetIntValue();
8178 // Max kMaxColumnCount columns - wallpaper for bug 345583.
8179 column
->mColumnCount
= std::min(column
->mColumnCount
,
8180 nsStyleColumn::kMaxColumnCount
);
8181 } else if (eCSSUnit_Inherit
== columnCountValue
->GetUnit()) {
8182 canStoreInRuleTree
= false;
8183 column
->mColumnCount
= parent
->mColumnCount
;
8186 // column-rule-width: length, enum, inherit
8187 const nsCSSValue
& widthValue
= *aRuleData
->ValueForColumnRuleWidth();
8188 if (eCSSUnit_Initial
== widthValue
.GetUnit() ||
8189 eCSSUnit_Unset
== widthValue
.GetUnit()) {
8190 column
->SetColumnRuleWidth(
8191 (mPresContext
->GetBorderWidthTable())[NS_STYLE_BORDER_WIDTH_MEDIUM
]);
8193 else if (eCSSUnit_Enumerated
== widthValue
.GetUnit()) {
8194 NS_ASSERTION(widthValue
.GetIntValue() == NS_STYLE_BORDER_WIDTH_THIN
||
8195 widthValue
.GetIntValue() == NS_STYLE_BORDER_WIDTH_MEDIUM
||
8196 widthValue
.GetIntValue() == NS_STYLE_BORDER_WIDTH_THICK
,
8197 "Unexpected enum value");
8198 column
->SetColumnRuleWidth(
8199 (mPresContext
->GetBorderWidthTable())[widthValue
.GetIntValue()]);
8201 else if (eCSSUnit_Inherit
== widthValue
.GetUnit()) {
8202 column
->SetColumnRuleWidth(parent
->GetComputedColumnRuleWidth());
8203 canStoreInRuleTree
= false;
8205 else if (widthValue
.IsLengthUnit() || widthValue
.IsCalcUnit()) {
8207 CalcLength(widthValue
, aContext
, mPresContext
, canStoreInRuleTree
);
8209 // FIXME: This is untested (by test_value_storage.html) for
8210 // column-rule-width since it gets covered up by the border
8212 NS_ASSERTION(widthValue
.IsCalcUnit(),
8213 "parser should have rejected negative length");
8216 column
->SetColumnRuleWidth(len
);
8219 // column-rule-style: enum, inherit
8220 const nsCSSValue
& styleValue
= *aRuleData
->ValueForColumnRuleStyle();
8221 NS_ABORT_IF_FALSE(eCSSUnit_None
!= styleValue
.GetUnit(),
8222 "'none' should be handled as enumerated value");
8223 if (eCSSUnit_Enumerated
== styleValue
.GetUnit()) {
8224 column
->mColumnRuleStyle
= styleValue
.GetIntValue();
8226 else if (eCSSUnit_Initial
== styleValue
.GetUnit() ||
8227 eCSSUnit_Unset
== styleValue
.GetUnit()) {
8228 column
->mColumnRuleStyle
= NS_STYLE_BORDER_STYLE_NONE
;
8230 else if (eCSSUnit_Inherit
== styleValue
.GetUnit()) {
8231 canStoreInRuleTree
= false;
8232 column
->mColumnRuleStyle
= parent
->mColumnRuleStyle
;
8235 // column-rule-color: color, inherit
8236 const nsCSSValue
& colorValue
= *aRuleData
->ValueForColumnRuleColor();
8237 if (eCSSUnit_Inherit
== colorValue
.GetUnit()) {
8238 canStoreInRuleTree
= false;
8239 column
->mColumnRuleColorIsForeground
= false;
8240 if (parent
->mColumnRuleColorIsForeground
) {
8241 if (parentContext
) {
8242 column
->mColumnRuleColor
= parentContext
->StyleColor()->mColor
;
8244 nsStyleColor
defaultColumnRuleColor(mPresContext
);
8245 column
->mColumnRuleColor
= defaultColumnRuleColor
.mColor
;
8248 column
->mColumnRuleColor
= parent
->mColumnRuleColor
;
8251 else if (eCSSUnit_Initial
== colorValue
.GetUnit() ||
8252 eCSSUnit_Unset
== colorValue
.GetUnit() ||
8253 eCSSUnit_Enumerated
== colorValue
.GetUnit()) {
8254 column
->mColumnRuleColorIsForeground
= true;
8256 else if (SetColor(colorValue
, 0, mPresContext
, aContext
,
8257 column
->mColumnRuleColor
, canStoreInRuleTree
)) {
8258 column
->mColumnRuleColorIsForeground
= false;
8261 // column-fill: enum
8262 SetDiscrete(*aRuleData
->ValueForColumnFill(),
8263 column
->mColumnFill
, canStoreInRuleTree
,
8264 SETDSC_ENUMERATED
| SETDSC_UNSET_INITIAL
,
8265 parent
->mColumnFill
,
8266 NS_STYLE_COLUMN_FILL_BALANCE
,
8269 COMPUTE_END_RESET(Column
, column
)
8273 SetSVGPaint(const nsCSSValue
& aValue
, const nsStyleSVGPaint
& parentPaint
,
8274 nsPresContext
* aPresContext
, nsStyleContext
*aContext
,
8275 nsStyleSVGPaint
& aResult
, nsStyleSVGPaintType aInitialPaintType
,
8276 bool& aCanStoreInRuleTree
)
8280 if (aValue
.GetUnit() == eCSSUnit_Inherit
||
8281 aValue
.GetUnit() == eCSSUnit_Unset
) {
8282 aResult
= parentPaint
;
8283 aCanStoreInRuleTree
= false;
8284 } else if (aValue
.GetUnit() == eCSSUnit_None
) {
8285 aResult
.SetType(eStyleSVGPaintType_None
);
8286 } else if (aValue
.GetUnit() == eCSSUnit_Initial
) {
8287 aResult
.SetType(aInitialPaintType
);
8288 aResult
.mPaint
.mColor
= NS_RGB(0, 0, 0);
8289 aResult
.mFallbackColor
= NS_RGB(0, 0, 0);
8290 } else if (SetColor(aValue
, NS_RGB(0, 0, 0), aPresContext
, aContext
,
8291 color
, aCanStoreInRuleTree
)) {
8292 aResult
.SetType(eStyleSVGPaintType_Color
);
8293 aResult
.mPaint
.mColor
= color
;
8294 } else if (aValue
.GetUnit() == eCSSUnit_Pair
) {
8295 const nsCSSValuePair
& pair
= aValue
.GetPairValue();
8297 if (pair
.mXValue
.GetUnit() == eCSSUnit_URL
) {
8298 aResult
.SetType(eStyleSVGPaintType_Server
);
8299 aResult
.mPaint
.mPaintServer
= pair
.mXValue
.GetURLValue();
8300 NS_IF_ADDREF(aResult
.mPaint
.mPaintServer
);
8301 } else if (pair
.mXValue
.GetUnit() == eCSSUnit_Enumerated
) {
8303 switch (pair
.mXValue
.GetIntValue()) {
8304 case NS_COLOR_CONTEXT_FILL
:
8305 aResult
.SetType(eStyleSVGPaintType_ContextFill
);
8307 case NS_COLOR_CONTEXT_STROKE
:
8308 aResult
.SetType(eStyleSVGPaintType_ContextStroke
);
8311 NS_NOTREACHED("unknown keyword as paint server value");
8315 NS_NOTREACHED("malformed paint server value");
8318 if (pair
.mYValue
.GetUnit() == eCSSUnit_None
) {
8319 aResult
.mFallbackColor
= NS_RGBA(0, 0, 0, 0);
8321 NS_ABORT_IF_FALSE(pair
.mYValue
.GetUnit() != eCSSUnit_Inherit
,
8322 "cannot inherit fallback colour");
8323 SetColor(pair
.mYValue
, NS_RGB(0, 0, 0), aPresContext
, aContext
,
8324 aResult
.mFallbackColor
, aCanStoreInRuleTree
);
8327 NS_ABORT_IF_FALSE(aValue
.GetUnit() == eCSSUnit_Null
,
8328 "malformed paint server value");
8333 SetSVGOpacity(const nsCSSValue
& aValue
,
8334 float& aOpacityField
, nsStyleSVGOpacitySource
& aOpacityTypeField
,
8335 bool& aCanStoreInRuleTree
,
8336 float aParentOpacity
, nsStyleSVGOpacitySource aParentOpacityType
)
8338 if (eCSSUnit_Enumerated
== aValue
.GetUnit()) {
8339 switch (aValue
.GetIntValue()) {
8340 case NS_STYLE_CONTEXT_FILL_OPACITY
:
8341 aOpacityTypeField
= eStyleSVGOpacitySource_ContextFillOpacity
;
8343 case NS_STYLE_CONTEXT_STROKE_OPACITY
:
8344 aOpacityTypeField
= eStyleSVGOpacitySource_ContextStrokeOpacity
;
8347 NS_NOTREACHED("SetSVGOpacity: Unknown keyword");
8349 // Fall back on fully opaque
8350 aOpacityField
= 1.0f
;
8351 } else if (eCSSUnit_Inherit
== aValue
.GetUnit() ||
8352 eCSSUnit_Unset
== aValue
.GetUnit()) {
8353 aCanStoreInRuleTree
= false;
8354 aOpacityField
= aParentOpacity
;
8355 aOpacityTypeField
= aParentOpacityType
;
8356 } else if (eCSSUnit_Null
!= aValue
.GetUnit()) {
8357 SetFactor(aValue
, aOpacityField
, aCanStoreInRuleTree
,
8358 aParentOpacity
, 1.0f
, SETFCT_OPACITY
);
8359 aOpacityTypeField
= eStyleSVGOpacitySource_Normal
;
8364 nsRuleNode::ComputeSVGData(void* aStartStruct
,
8365 const nsRuleData
* aRuleData
,
8366 nsStyleContext
* aContext
,
8367 nsRuleNode
* aHighestNode
,
8368 const RuleDetail aRuleDetail
,
8369 const bool aCanStoreInRuleTree
)
8371 COMPUTE_START_INHERITED(SVG
, (), svg
, parentSVG
)
8373 // clip-rule: enum, inherit, initial
8374 SetDiscrete(*aRuleData
->ValueForClipRule(),
8375 svg
->mClipRule
, canStoreInRuleTree
,
8376 SETDSC_ENUMERATED
| SETDSC_UNSET_INHERIT
,
8377 parentSVG
->mClipRule
,
8378 NS_STYLE_FILL_RULE_NONZERO
, 0, 0, 0, 0);
8380 // color-interpolation: enum, inherit, initial
8381 SetDiscrete(*aRuleData
->ValueForColorInterpolation(),
8382 svg
->mColorInterpolation
, canStoreInRuleTree
,
8383 SETDSC_ENUMERATED
| SETDSC_UNSET_INHERIT
,
8384 parentSVG
->mColorInterpolation
,
8385 NS_STYLE_COLOR_INTERPOLATION_SRGB
, 0, 0, 0, 0);
8387 // color-interpolation-filters: enum, inherit, initial
8388 SetDiscrete(*aRuleData
->ValueForColorInterpolationFilters(),
8389 svg
->mColorInterpolationFilters
, canStoreInRuleTree
,
8390 SETDSC_ENUMERATED
| SETDSC_UNSET_INHERIT
,
8391 parentSVG
->mColorInterpolationFilters
,
8392 NS_STYLE_COLOR_INTERPOLATION_LINEARRGB
, 0, 0, 0, 0);
8395 SetSVGPaint(*aRuleData
->ValueForFill(),
8396 parentSVG
->mFill
, mPresContext
, aContext
,
8397 svg
->mFill
, eStyleSVGPaintType_Color
, canStoreInRuleTree
);
8399 // fill-opacity: factor, inherit, initial,
8400 // context-fill-opacity, context-stroke-opacity
8401 nsStyleSVGOpacitySource contextFillOpacity
= svg
->mFillOpacitySource
;
8402 SetSVGOpacity(*aRuleData
->ValueForFillOpacity(),
8403 svg
->mFillOpacity
, contextFillOpacity
, canStoreInRuleTree
,
8404 parentSVG
->mFillOpacity
, parentSVG
->mFillOpacitySource
);
8405 svg
->mFillOpacitySource
= contextFillOpacity
;
8407 // fill-rule: enum, inherit, initial
8408 SetDiscrete(*aRuleData
->ValueForFillRule(),
8409 svg
->mFillRule
, canStoreInRuleTree
,
8410 SETDSC_ENUMERATED
| SETDSC_UNSET_INHERIT
,
8411 parentSVG
->mFillRule
,
8412 NS_STYLE_FILL_RULE_NONZERO
, 0, 0, 0, 0);
8414 // image-rendering: enum, inherit
8415 SetDiscrete(*aRuleData
->ValueForImageRendering(),
8416 svg
->mImageRendering
, canStoreInRuleTree
,
8417 SETDSC_ENUMERATED
| SETDSC_UNSET_INHERIT
,
8418 parentSVG
->mImageRendering
,
8419 NS_STYLE_IMAGE_RENDERING_AUTO
, 0, 0, 0, 0);
8421 // marker-end: url, none, inherit
8422 const nsCSSValue
* markerEndValue
= aRuleData
->ValueForMarkerEnd();
8423 if (eCSSUnit_URL
== markerEndValue
->GetUnit()) {
8424 svg
->mMarkerEnd
= markerEndValue
->GetURLValue();
8425 } else if (eCSSUnit_None
== markerEndValue
->GetUnit() ||
8426 eCSSUnit_Initial
== markerEndValue
->GetUnit()) {
8427 svg
->mMarkerEnd
= nullptr;
8428 } else if (eCSSUnit_Inherit
== markerEndValue
->GetUnit() ||
8429 eCSSUnit_Unset
== markerEndValue
->GetUnit()) {
8430 canStoreInRuleTree
= false;
8431 svg
->mMarkerEnd
= parentSVG
->mMarkerEnd
;
8434 // marker-mid: url, none, inherit
8435 const nsCSSValue
* markerMidValue
= aRuleData
->ValueForMarkerMid();
8436 if (eCSSUnit_URL
== markerMidValue
->GetUnit()) {
8437 svg
->mMarkerMid
= markerMidValue
->GetURLValue();
8438 } else if (eCSSUnit_None
== markerMidValue
->GetUnit() ||
8439 eCSSUnit_Initial
== markerMidValue
->GetUnit()) {
8440 svg
->mMarkerMid
= nullptr;
8441 } else if (eCSSUnit_Inherit
== markerMidValue
->GetUnit() ||
8442 eCSSUnit_Unset
== markerMidValue
->GetUnit()) {
8443 canStoreInRuleTree
= false;
8444 svg
->mMarkerMid
= parentSVG
->mMarkerMid
;
8447 // marker-start: url, none, inherit
8448 const nsCSSValue
* markerStartValue
= aRuleData
->ValueForMarkerStart();
8449 if (eCSSUnit_URL
== markerStartValue
->GetUnit()) {
8450 svg
->mMarkerStart
= markerStartValue
->GetURLValue();
8451 } else if (eCSSUnit_None
== markerStartValue
->GetUnit() ||
8452 eCSSUnit_Initial
== markerStartValue
->GetUnit()) {
8453 svg
->mMarkerStart
= nullptr;
8454 } else if (eCSSUnit_Inherit
== markerStartValue
->GetUnit() ||
8455 eCSSUnit_Unset
== markerStartValue
->GetUnit()) {
8456 canStoreInRuleTree
= false;
8457 svg
->mMarkerStart
= parentSVG
->mMarkerStart
;
8460 // paint-order: enum (bit field), inherit, initial
8461 const nsCSSValue
* paintOrderValue
= aRuleData
->ValueForPaintOrder();
8462 switch (paintOrderValue
->GetUnit()) {
8466 case eCSSUnit_Enumerated
:
8468 (NS_STYLE_PAINT_ORDER_BITWIDTH
* NS_STYLE_PAINT_ORDER_LAST_VALUE
<= 8,
8469 "SVGStyleStruct::mPaintOrder not big enough");
8470 svg
->mPaintOrder
= static_cast<uint8_t>(paintOrderValue
->GetIntValue());
8473 case eCSSUnit_Inherit
:
8474 case eCSSUnit_Unset
:
8475 canStoreInRuleTree
= false;
8476 svg
->mPaintOrder
= parentSVG
->mPaintOrder
;
8479 case eCSSUnit_Initial
:
8480 svg
->mPaintOrder
= NS_STYLE_PAINT_ORDER_NORMAL
;
8484 NS_NOTREACHED("unexpected unit");
8487 // shape-rendering: enum, inherit
8488 SetDiscrete(*aRuleData
->ValueForShapeRendering(),
8489 svg
->mShapeRendering
, canStoreInRuleTree
,
8490 SETDSC_ENUMERATED
| SETDSC_UNSET_INHERIT
,
8491 parentSVG
->mShapeRendering
,
8492 NS_STYLE_SHAPE_RENDERING_AUTO
, 0, 0, 0, 0);
8495 SetSVGPaint(*aRuleData
->ValueForStroke(),
8496 parentSVG
->mStroke
, mPresContext
, aContext
,
8497 svg
->mStroke
, eStyleSVGPaintType_None
, canStoreInRuleTree
);
8499 // stroke-dasharray: <dasharray>, none, inherit, context-value
8500 const nsCSSValue
* strokeDasharrayValue
= aRuleData
->ValueForStrokeDasharray();
8501 switch (strokeDasharrayValue
->GetUnit()) {
8505 case eCSSUnit_Inherit
:
8506 case eCSSUnit_Unset
:
8507 canStoreInRuleTree
= false;
8508 svg
->mStrokeDasharrayFromObject
= parentSVG
->mStrokeDasharrayFromObject
;
8509 // only do the copy if weren't already set up by the copy constructor
8510 // FIXME Bug 389408: This is broken when aStartStruct is non-null!
8511 if (!svg
->mStrokeDasharray
) {
8512 svg
->mStrokeDasharrayLength
= parentSVG
->mStrokeDasharrayLength
;
8513 if (svg
->mStrokeDasharrayLength
) {
8514 svg
->mStrokeDasharray
= new nsStyleCoord
[svg
->mStrokeDasharrayLength
];
8515 if (svg
->mStrokeDasharray
)
8516 memcpy(svg
->mStrokeDasharray
,
8517 parentSVG
->mStrokeDasharray
,
8518 svg
->mStrokeDasharrayLength
* sizeof(nsStyleCoord
));
8520 svg
->mStrokeDasharrayLength
= 0;
8525 case eCSSUnit_Enumerated
:
8526 NS_ABORT_IF_FALSE(strokeDasharrayValue
->GetIntValue() ==
8527 NS_STYLE_STROKE_PROP_CONTEXT_VALUE
,
8528 "Unknown keyword for stroke-dasharray");
8529 svg
->mStrokeDasharrayFromObject
= true;
8530 delete [] svg
->mStrokeDasharray
;
8531 svg
->mStrokeDasharray
= nullptr;
8532 svg
->mStrokeDasharrayLength
= 0;
8535 case eCSSUnit_Initial
:
8537 svg
->mStrokeDasharrayFromObject
= false;
8538 delete [] svg
->mStrokeDasharray
;
8539 svg
->mStrokeDasharray
= nullptr;
8540 svg
->mStrokeDasharrayLength
= 0;
8544 case eCSSUnit_ListDep
: {
8545 svg
->mStrokeDasharrayFromObject
= false;
8546 delete [] svg
->mStrokeDasharray
;
8547 svg
->mStrokeDasharray
= nullptr;
8548 svg
->mStrokeDasharrayLength
= 0;
8550 // count number of values
8551 const nsCSSValueList
*value
= strokeDasharrayValue
->GetListValue();
8552 svg
->mStrokeDasharrayLength
= ListLength(value
);
8554 NS_ASSERTION(svg
->mStrokeDasharrayLength
!= 0, "no dasharray items");
8556 svg
->mStrokeDasharray
= new nsStyleCoord
[svg
->mStrokeDasharrayLength
];
8558 if (svg
->mStrokeDasharray
) {
8560 while (nullptr != value
) {
8561 SetCoord(value
->mValue
,
8562 svg
->mStrokeDasharray
[i
++], nsStyleCoord(),
8563 SETCOORD_LP
| SETCOORD_FACTOR
,
8564 aContext
, mPresContext
, canStoreInRuleTree
);
8565 value
= value
->mNext
;
8568 svg
->mStrokeDasharrayLength
= 0;
8574 NS_ABORT_IF_FALSE(false, "unrecognized dasharray unit");
8577 // stroke-dashoffset: <dashoffset>, inherit
8578 const nsCSSValue
*strokeDashoffsetValue
=
8579 aRuleData
->ValueForStrokeDashoffset();
8580 svg
->mStrokeDashoffsetFromObject
=
8581 strokeDashoffsetValue
->GetUnit() == eCSSUnit_Enumerated
&&
8582 strokeDashoffsetValue
->GetIntValue() == NS_STYLE_STROKE_PROP_CONTEXT_VALUE
;
8583 if (svg
->mStrokeDashoffsetFromObject
) {
8584 svg
->mStrokeDashoffset
.SetCoordValue(0);
8586 SetCoord(*aRuleData
->ValueForStrokeDashoffset(),
8587 svg
->mStrokeDashoffset
, parentSVG
->mStrokeDashoffset
,
8588 SETCOORD_LPH
| SETCOORD_FACTOR
| SETCOORD_INITIAL_ZERO
|
8589 SETCOORD_UNSET_INHERIT
,
8590 aContext
, mPresContext
, canStoreInRuleTree
);
8593 // stroke-linecap: enum, inherit, initial
8594 SetDiscrete(*aRuleData
->ValueForStrokeLinecap(),
8595 svg
->mStrokeLinecap
, canStoreInRuleTree
,
8596 SETDSC_ENUMERATED
| SETDSC_UNSET_INHERIT
,
8597 parentSVG
->mStrokeLinecap
,
8598 NS_STYLE_STROKE_LINECAP_BUTT
, 0, 0, 0, 0);
8600 // stroke-linejoin: enum, inherit, initial
8601 SetDiscrete(*aRuleData
->ValueForStrokeLinejoin(),
8602 svg
->mStrokeLinejoin
, canStoreInRuleTree
,
8603 SETDSC_ENUMERATED
| SETDSC_UNSET_INHERIT
,
8604 parentSVG
->mStrokeLinejoin
,
8605 NS_STYLE_STROKE_LINEJOIN_MITER
, 0, 0, 0, 0);
8607 // stroke-miterlimit: <miterlimit>, inherit
8608 SetFactor(*aRuleData
->ValueForStrokeMiterlimit(),
8609 svg
->mStrokeMiterlimit
,
8611 parentSVG
->mStrokeMiterlimit
, 4.0f
,
8612 SETFCT_UNSET_INHERIT
);
8615 nsStyleSVGOpacitySource contextStrokeOpacity
= svg
->mStrokeOpacitySource
;
8616 SetSVGOpacity(*aRuleData
->ValueForStrokeOpacity(),
8617 svg
->mStrokeOpacity
, contextStrokeOpacity
, canStoreInRuleTree
,
8618 parentSVG
->mStrokeOpacity
, parentSVG
->mStrokeOpacitySource
);
8619 svg
->mStrokeOpacitySource
= contextStrokeOpacity
;
8622 const nsCSSValue
* strokeWidthValue
= aRuleData
->ValueForStrokeWidth();
8623 switch (strokeWidthValue
->GetUnit()) {
8624 case eCSSUnit_Enumerated
:
8625 NS_ABORT_IF_FALSE(strokeWidthValue
->GetIntValue() ==
8626 NS_STYLE_STROKE_PROP_CONTEXT_VALUE
,
8627 "Unrecognized keyword for stroke-width");
8628 svg
->mStrokeWidthFromObject
= true;
8629 svg
->mStrokeWidth
.SetCoordValue(nsPresContext::CSSPixelsToAppUnits(1));
8632 case eCSSUnit_Initial
:
8633 svg
->mStrokeWidthFromObject
= false;
8634 svg
->mStrokeWidth
.SetCoordValue(nsPresContext::CSSPixelsToAppUnits(1));
8638 svg
->mStrokeWidthFromObject
= false;
8639 SetCoord(*strokeWidthValue
,
8640 svg
->mStrokeWidth
, parentSVG
->mStrokeWidth
,
8641 SETCOORD_LPH
| SETCOORD_FACTOR
| SETCOORD_UNSET_INHERIT
,
8642 aContext
, mPresContext
, canStoreInRuleTree
);
8645 // text-anchor: enum, inherit, initial
8646 SetDiscrete(*aRuleData
->ValueForTextAnchor(),
8647 svg
->mTextAnchor
, canStoreInRuleTree
,
8648 SETDSC_ENUMERATED
| SETDSC_UNSET_INHERIT
,
8649 parentSVG
->mTextAnchor
,
8650 NS_STYLE_TEXT_ANCHOR_START
, 0, 0, 0, 0);
8652 // text-rendering: enum, inherit, initial
8653 SetDiscrete(*aRuleData
->ValueForTextRendering(),
8654 svg
->mTextRendering
, canStoreInRuleTree
,
8655 SETDSC_ENUMERATED
| SETDSC_UNSET_INHERIT
,
8656 parentSVG
->mTextRendering
,
8657 NS_STYLE_TEXT_RENDERING_AUTO
, 0, 0, 0, 0);
8659 COMPUTE_END_INHERITED(SVG
, svg
)
8662 // Returns true if the nsStyleFilter was successfully set using the nsCSSValue.
8664 nsRuleNode::SetStyleFilterToCSSValue(nsStyleFilter
* aStyleFilter
,
8665 const nsCSSValue
& aValue
,
8666 nsStyleContext
* aStyleContext
,
8667 nsPresContext
* aPresContext
,
8668 bool& aCanStoreInRuleTree
)
8670 nsCSSUnit unit
= aValue
.GetUnit();
8671 if (unit
== eCSSUnit_URL
) {
8672 nsIURI
* url
= aValue
.GetURLValue();
8675 aStyleFilter
->SetURL(url
);
8679 NS_ABORT_IF_FALSE(unit
== eCSSUnit_Function
, "expected a filter function");
8681 nsCSSValue::Array
* filterFunction
= aValue
.GetArrayValue();
8682 nsCSSKeyword functionName
=
8683 (nsCSSKeyword
)filterFunction
->Item(0).GetIntValue();
8686 DebugOnly
<bool> foundKeyword
=
8687 nsCSSProps::FindKeyword(functionName
,
8688 nsCSSProps::kFilterFunctionKTable
,
8690 NS_ABORT_IF_FALSE(foundKeyword
, "unknown filter type");
8691 if (type
== NS_STYLE_FILTER_DROP_SHADOW
) {
8692 nsRefPtr
<nsCSSShadowArray
> shadowArray
= GetShadowData(
8693 filterFunction
->Item(1).GetListValue(),
8696 aCanStoreInRuleTree
);
8697 aStyleFilter
->SetDropShadow(shadowArray
);
8701 int32_t mask
= SETCOORD_PERCENT
| SETCOORD_FACTOR
;
8702 if (type
== NS_STYLE_FILTER_BLUR
) {
8703 mask
= SETCOORD_LENGTH
|
8704 SETCOORD_CALC_LENGTH_ONLY
|
8705 SETCOORD_CALC_CLAMP_NONNEGATIVE
;
8706 } else if (type
== NS_STYLE_FILTER_HUE_ROTATE
) {
8707 mask
= SETCOORD_ANGLE
;
8710 NS_ABORT_IF_FALSE(filterFunction
->Count() == 2,
8711 "all filter functions should have "
8712 "exactly one argument");
8714 nsCSSValue
& arg
= filterFunction
->Item(1);
8715 nsStyleCoord filterParameter
;
8716 DebugOnly
<bool> didSetCoord
= SetCoord(arg
, filterParameter
,
8717 nsStyleCoord(), mask
,
8718 aStyleContext
, aPresContext
,
8719 aCanStoreInRuleTree
);
8720 aStyleFilter
->SetFilterParameter(filterParameter
, type
);
8721 NS_ABORT_IF_FALSE(didSetCoord
, "unexpected unit");
8726 nsRuleNode::ComputeSVGResetData(void* aStartStruct
,
8727 const nsRuleData
* aRuleData
,
8728 nsStyleContext
* aContext
,
8729 nsRuleNode
* aHighestNode
,
8730 const RuleDetail aRuleDetail
,
8731 const bool aCanStoreInRuleTree
)
8733 COMPUTE_START_RESET(SVGReset
, (), svgReset
, parentSVGReset
)
8736 const nsCSSValue
* stopColorValue
= aRuleData
->ValueForStopColor();
8737 if (eCSSUnit_Initial
== stopColorValue
->GetUnit() ||
8738 eCSSUnit_Unset
== stopColorValue
->GetUnit()) {
8739 svgReset
->mStopColor
= NS_RGB(0, 0, 0);
8741 SetColor(*stopColorValue
, parentSVGReset
->mStopColor
,
8742 mPresContext
, aContext
, svgReset
->mStopColor
, canStoreInRuleTree
);
8746 const nsCSSValue
* floodColorValue
= aRuleData
->ValueForFloodColor();
8747 if (eCSSUnit_Initial
== floodColorValue
->GetUnit() ||
8748 eCSSUnit_Unset
== floodColorValue
->GetUnit()) {
8749 svgReset
->mFloodColor
= NS_RGB(0, 0, 0);
8751 SetColor(*floodColorValue
, parentSVGReset
->mFloodColor
,
8752 mPresContext
, aContext
, svgReset
->mFloodColor
, canStoreInRuleTree
);
8756 const nsCSSValue
* lightingColorValue
= aRuleData
->ValueForLightingColor();
8757 if (eCSSUnit_Initial
== lightingColorValue
->GetUnit() ||
8758 eCSSUnit_Unset
== lightingColorValue
->GetUnit()) {
8759 svgReset
->mLightingColor
= NS_RGB(255, 255, 255);
8761 SetColor(*lightingColorValue
, parentSVGReset
->mLightingColor
,
8762 mPresContext
, aContext
, svgReset
->mLightingColor
,
8763 canStoreInRuleTree
);
8766 // clip-path: url, none, inherit
8767 const nsCSSValue
* clipPathValue
= aRuleData
->ValueForClipPath();
8768 if (eCSSUnit_URL
== clipPathValue
->GetUnit()) {
8769 svgReset
->mClipPath
= clipPathValue
->GetURLValue();
8770 } else if (eCSSUnit_None
== clipPathValue
->GetUnit() ||
8771 eCSSUnit_Initial
== clipPathValue
->GetUnit() ||
8772 eCSSUnit_Unset
== clipPathValue
->GetUnit()) {
8773 svgReset
->mClipPath
= nullptr;
8774 } else if (eCSSUnit_Inherit
== clipPathValue
->GetUnit()) {
8775 canStoreInRuleTree
= false;
8776 svgReset
->mClipPath
= parentSVGReset
->mClipPath
;
8780 SetFactor(*aRuleData
->ValueForStopOpacity(),
8781 svgReset
->mStopOpacity
, canStoreInRuleTree
,
8782 parentSVGReset
->mStopOpacity
, 1.0f
,
8783 SETFCT_OPACITY
| SETFCT_UNSET_INITIAL
);
8786 SetFactor(*aRuleData
->ValueForFloodOpacity(),
8787 svgReset
->mFloodOpacity
, canStoreInRuleTree
,
8788 parentSVGReset
->mFloodOpacity
, 1.0f
,
8789 SETFCT_OPACITY
| SETFCT_UNSET_INITIAL
);
8791 // dominant-baseline: enum, inherit, initial
8792 SetDiscrete(*aRuleData
->ValueForDominantBaseline(),
8793 svgReset
->mDominantBaseline
,
8795 SETDSC_ENUMERATED
| SETDSC_UNSET_INITIAL
,
8796 parentSVGReset
->mDominantBaseline
,
8797 NS_STYLE_DOMINANT_BASELINE_AUTO
, 0, 0, 0, 0);
8799 // vector-effect: enum, inherit, initial
8800 SetDiscrete(*aRuleData
->ValueForVectorEffect(),
8801 svgReset
->mVectorEffect
,
8803 SETDSC_ENUMERATED
| SETDSC_UNSET_INITIAL
,
8804 parentSVGReset
->mVectorEffect
,
8805 NS_STYLE_VECTOR_EFFECT_NONE
, 0, 0, 0, 0);
8807 // filter: url, none, inherit
8808 const nsCSSValue
* filterValue
= aRuleData
->ValueForFilter();
8809 switch (filterValue
->GetUnit()) {
8813 case eCSSUnit_Initial
:
8814 case eCSSUnit_Unset
:
8815 svgReset
->mFilters
.Clear();
8817 case eCSSUnit_Inherit
:
8818 canStoreInRuleTree
= false;
8819 svgReset
->mFilters
= parentSVGReset
->mFilters
;
8822 case eCSSUnit_ListDep
: {
8823 svgReset
->mFilters
.Clear();
8824 const nsCSSValueList
* cur
= filterValue
->GetListValue();
8826 nsStyleFilter styleFilter
;
8827 if (!SetStyleFilterToCSSValue(&styleFilter
, cur
->mValue
, aContext
,
8828 mPresContext
, canStoreInRuleTree
)) {
8829 svgReset
->mFilters
.Clear();
8832 NS_ABORT_IF_FALSE(styleFilter
.GetType() != NS_STYLE_FILTER_NONE
,
8833 "filter should be set");
8834 svgReset
->mFilters
.AppendElement(styleFilter
);
8840 NS_NOTREACHED("unexpected unit");
8843 // mask: url, none, inherit
8844 const nsCSSValue
* maskValue
= aRuleData
->ValueForMask();
8845 if (eCSSUnit_URL
== maskValue
->GetUnit()) {
8846 svgReset
->mMask
= maskValue
->GetURLValue();
8847 } else if (eCSSUnit_None
== maskValue
->GetUnit() ||
8848 eCSSUnit_Initial
== maskValue
->GetUnit() ||
8849 eCSSUnit_Unset
== maskValue
->GetUnit()) {
8850 svgReset
->mMask
= nullptr;
8851 } else if (eCSSUnit_Inherit
== maskValue
->GetUnit()) {
8852 canStoreInRuleTree
= false;
8853 svgReset
->mMask
= parentSVGReset
->mMask
;
8856 // mask-type: enum, inherit, initial
8857 SetDiscrete(*aRuleData
->ValueForMaskType(),
8858 svgReset
->mMaskType
,
8860 SETDSC_ENUMERATED
| SETDSC_UNSET_INITIAL
,
8861 parentSVGReset
->mMaskType
,
8862 NS_STYLE_MASK_TYPE_LUMINANCE
, 0, 0, 0, 0);
8864 COMPUTE_END_RESET(SVGReset
, svgReset
)
8868 nsRuleNode::ComputeVariablesData(void* aStartStruct
,
8869 const nsRuleData
* aRuleData
,
8870 nsStyleContext
* aContext
,
8871 nsRuleNode
* aHighestNode
,
8872 const RuleDetail aRuleDetail
,
8873 const bool aCanStoreInRuleTree
)
8875 COMPUTE_START_INHERITED(Variables
, (), variables
, parentVariables
)
8877 MOZ_ASSERT(aRuleData
->mVariables
,
8878 "shouldn't be in ComputeVariablesData if there were no variable "
8879 "declarations specified");
8881 CSSVariableResolver
resolver(&variables
->mVariables
);
8882 resolver
.Resolve(&parentVariables
->mVariables
,
8883 aRuleData
->mVariables
);
8884 canStoreInRuleTree
= false;
8886 COMPUTE_END_INHERITED(Variables
, variables
)
8890 nsRuleNode::GetStyleData(nsStyleStructID aSID
,
8891 nsStyleContext
* aContext
,
8894 NS_ASSERTION(IsUsedDirectly(),
8895 "if we ever call this on rule nodes that aren't used "
8896 "directly, we should adjust handling of mDependentBits "
8900 data
= mStyleData
.GetStyleData(aSID
);
8901 if (MOZ_LIKELY(data
!= nullptr))
8902 return data
; // We have a fully specified struct. Just return it.
8904 if (MOZ_UNLIKELY(!aComputeData
))
8907 // Nothing is cached. We'll have to delve further and examine our rules.
8908 data
= WalkRuleTree(aSID
, aContext
);
8910 NS_ABORT_IF_FALSE(data
, "should have aborted on out-of-memory");
8914 // See comments above in GetStyleData for an explanation of what the
8916 #define STYLE_STRUCT(name_, checkdata_cb_) \
8917 const nsStyle##name_* \
8918 nsRuleNode::GetStyle##name_(nsStyleContext* aContext, bool aComputeData) \
8920 NS_ASSERTION(IsUsedDirectly(), \
8921 "if we ever call this on rule nodes that aren't used " \
8922 "directly, we should adjust handling of mDependentBits " \
8925 const nsStyle##name_ *data; \
8926 data = mStyleData.GetStyle##name_(); \
8927 if (MOZ_LIKELY(data != nullptr)) \
8930 if (MOZ_UNLIKELY(!aComputeData)) \
8933 data = static_cast<const nsStyle##name_ *> \
8934 (WalkRuleTree(eStyleStruct_##name_, aContext)); \
8936 NS_ABORT_IF_FALSE(data, "should have aborted on out-of-memory"); \
8939 #include "nsStyleStructList.h"
8945 for (nsRuleNode
*node
= this;
8946 node
&& !(node
->mDependentBits
& NS_RULE_NODE_GC_MARK
);
8947 node
= node
->mParent
)
8948 node
->mDependentBits
|= NS_RULE_NODE_GC_MARK
;
8952 nsRuleNode::DestroyIfNotMarked()
8954 // If we're not marked, then we have to delete ourself.
8955 // However, we never allow the root node to GC itself, because nsStyleSet
8956 // wants to hold onto the root node and not worry about re-creating a
8957 // rule walker if the root node is deleted.
8958 if (!(mDependentBits
& NS_RULE_NODE_GC_MARK
) &&
8959 // Skip this only if we're the *current* root and not an old one.
8960 !(IsRoot() && mPresContext
->StyleSet()->GetRuleTree() == this)) {
8965 // Clear our mark, for the next time around.
8966 mDependentBits
&= ~NS_RULE_NODE_GC_MARK
;
8971 nsRuleNode::SweepHashEntry(PLDHashTable
*table
, PLDHashEntryHdr
*hdr
,
8972 uint32_t number
, void *arg
)
8974 ChildrenHashEntry
*entry
= static_cast<ChildrenHashEntry
*>(hdr
);
8975 nsRuleNode
* node
= entry
->mRuleNode
;
8976 if (node
->DestroyIfNotMarked()) {
8977 return PL_DHASH_REMOVE
; // implies NEXT, unless |ed with STOP
8979 if (node
->HaveChildren()) {
8980 // When children are hashed mNextSibling is not normally used but we use it
8981 // here to build a list of children that needs to be swept.
8982 nsRuleNode
** headQ
= static_cast<nsRuleNode
**>(arg
);
8983 node
->mNextSibling
= *headQ
;
8986 return PL_DHASH_NEXT
;
8990 nsRuleNode::SweepChildren(nsTArray
<nsRuleNode
*>& aSweepQueue
)
8992 NS_ASSERTION(!(mDependentBits
& NS_RULE_NODE_GC_MARK
),
8993 "missing DestroyIfNotMarked() call");
8994 NS_ASSERTION(HaveChildren(),
8995 "why call SweepChildren with no children?");
8996 uint32_t childrenDestroyed
= 0;
8997 nsRuleNode
* survivorsWithChildren
= nullptr;
8998 if (ChildrenAreHashed()) {
8999 PLDHashTable
* children
= ChildrenHash();
9000 uint32_t oldChildCount
= children
->EntryCount();
9001 PL_DHashTableEnumerate(children
, SweepHashEntry
, &survivorsWithChildren
);
9002 childrenDestroyed
= oldChildCount
- children
->EntryCount();
9003 if (childrenDestroyed
== oldChildCount
) {
9004 PL_DHashTableDestroy(children
);
9005 mChildren
.asVoid
= nullptr;
9008 for (nsRuleNode
** children
= ChildrenListPtr(); *children
; ) {
9009 nsRuleNode
* next
= (*children
)->mNextSibling
;
9010 if ((*children
)->DestroyIfNotMarked()) {
9011 // This rule node was destroyed, unlink it from the list by
9012 // making *children point to the next entry.
9014 ++childrenDestroyed
;
9016 children
= &(*children
)->mNextSibling
;
9019 survivorsWithChildren
= ChildrenList();
9021 if (survivorsWithChildren
) {
9022 aSweepQueue
.AppendElement(survivorsWithChildren
);
9024 NS_ASSERTION(childrenDestroyed
<= mRefCnt
, "wrong ref count");
9025 mRefCnt
-= childrenDestroyed
;
9026 NS_POSTCONDITION(IsRoot() || mRefCnt
> 0,
9027 "We didn't get swept, so we'd better have style contexts "
9028 "pointing to us or to one of our descendants, which means "
9029 "we'd better have a nonzero mRefCnt here!");
9035 NS_ASSERTION(IsRoot(), "must start sweeping at a root");
9036 NS_ASSERTION(!mNextSibling
, "root must not have mNextSibling");
9038 if (DestroyIfNotMarked()) {
9042 nsAutoTArray
<nsRuleNode
*, 70> sweepQueue
;
9043 sweepQueue
.AppendElement(this);
9044 while (!sweepQueue
.IsEmpty()) {
9045 nsTArray
<nsRuleNode
*>::index_type last
= sweepQueue
.Length() - 1;
9046 nsRuleNode
* ruleNode
= sweepQueue
[last
];
9047 sweepQueue
.RemoveElementAt(last
);
9048 for (; ruleNode
; ruleNode
= ruleNode
->mNextSibling
) {
9049 if (ruleNode
->HaveChildren()) {
9050 ruleNode
->SweepChildren(sweepQueue
);
9058 nsRuleNode::HasAuthorSpecifiedRules(nsStyleContext
* aStyleContext
,
9059 uint32_t ruleTypeMask
,
9060 bool aAuthorColorsAllowed
)
9062 uint32_t inheritBits
= 0;
9063 if (ruleTypeMask
& NS_AUTHOR_SPECIFIED_BACKGROUND
)
9064 inheritBits
|= NS_STYLE_INHERIT_BIT(Background
);
9066 if (ruleTypeMask
& NS_AUTHOR_SPECIFIED_BORDER
)
9067 inheritBits
|= NS_STYLE_INHERIT_BIT(Border
);
9069 if (ruleTypeMask
& NS_AUTHOR_SPECIFIED_PADDING
)
9070 inheritBits
|= NS_STYLE_INHERIT_BIT(Padding
);
9072 if (ruleTypeMask
& NS_AUTHOR_SPECIFIED_TEXT_SHADOW
)
9073 inheritBits
|= NS_STYLE_INHERIT_BIT(Text
);
9075 // properties in the SIDS, whether or not we care about them
9077 backgroundOffset
, borderOffset
, paddingOffset
, textShadowOffset
;
9079 // We put the reset properties the start of the nsCSSValue array....
9081 if (ruleTypeMask
& NS_AUTHOR_SPECIFIED_BACKGROUND
) {
9082 backgroundOffset
= nprops
;
9083 nprops
+= nsCSSProps::PropertyCountInStruct(eStyleStruct_Background
);
9086 if (ruleTypeMask
& NS_AUTHOR_SPECIFIED_BORDER
) {
9087 borderOffset
= nprops
;
9088 nprops
+= nsCSSProps::PropertyCountInStruct(eStyleStruct_Border
);
9091 if (ruleTypeMask
& NS_AUTHOR_SPECIFIED_PADDING
) {
9092 paddingOffset
= nprops
;
9093 nprops
+= nsCSSProps::PropertyCountInStruct(eStyleStruct_Padding
);
9096 // ...and the inherited properties at the end of the array.
9097 size_t inheritedOffset
= nprops
;
9099 if (ruleTypeMask
& NS_AUTHOR_SPECIFIED_TEXT_SHADOW
) {
9100 textShadowOffset
= nprops
;
9101 nprops
+= nsCSSProps::PropertyCountInStruct(eStyleStruct_Text
);
9104 void* dataStorage
= alloca(nprops
* sizeof(nsCSSValue
));
9105 AutoCSSValueArray
dataArray(dataStorage
, nprops
);
9107 /* We're relying on the use of |aStyleContext| not mutating it! */
9108 nsRuleData
ruleData(inheritBits
, dataArray
.get(),
9109 aStyleContext
->PresContext(), aStyleContext
);
9111 if (ruleTypeMask
& NS_AUTHOR_SPECIFIED_BACKGROUND
) {
9112 ruleData
.mValueOffsets
[eStyleStruct_Background
] = backgroundOffset
;
9115 if (ruleTypeMask
& NS_AUTHOR_SPECIFIED_BORDER
) {
9116 ruleData
.mValueOffsets
[eStyleStruct_Border
] = borderOffset
;
9119 if (ruleTypeMask
& NS_AUTHOR_SPECIFIED_PADDING
) {
9120 ruleData
.mValueOffsets
[eStyleStruct_Padding
] = paddingOffset
;
9123 if (ruleTypeMask
& NS_AUTHOR_SPECIFIED_TEXT_SHADOW
) {
9124 ruleData
.mValueOffsets
[eStyleStruct_Text
] = textShadowOffset
;
9127 static const nsCSSProperty backgroundValues
[] = {
9128 eCSSProperty_background_color
,
9129 eCSSProperty_background_image
,
9132 static const nsCSSProperty borderValues
[] = {
9133 eCSSProperty_border_top_color
,
9134 eCSSProperty_border_top_style
,
9135 eCSSProperty_border_top_width
,
9136 eCSSProperty_border_right_color_value
,
9137 eCSSProperty_border_right_style_value
,
9138 eCSSProperty_border_right_width_value
,
9139 eCSSProperty_border_bottom_color
,
9140 eCSSProperty_border_bottom_style
,
9141 eCSSProperty_border_bottom_width
,
9142 eCSSProperty_border_left_color_value
,
9143 eCSSProperty_border_left_style_value
,
9144 eCSSProperty_border_left_width_value
,
9145 eCSSProperty_border_start_color_value
,
9146 eCSSProperty_border_start_style_value
,
9147 eCSSProperty_border_start_width_value
,
9148 eCSSProperty_border_end_color_value
,
9149 eCSSProperty_border_end_style_value
,
9150 eCSSProperty_border_end_width_value
,
9151 eCSSProperty_border_top_left_radius
,
9152 eCSSProperty_border_top_right_radius
,
9153 eCSSProperty_border_bottom_right_radius
,
9154 eCSSProperty_border_bottom_left_radius
,
9157 static const nsCSSProperty paddingValues
[] = {
9158 eCSSProperty_padding_top
,
9159 eCSSProperty_padding_right_value
,
9160 eCSSProperty_padding_bottom
,
9161 eCSSProperty_padding_left_value
,
9162 eCSSProperty_padding_start_value
,
9163 eCSSProperty_padding_end_value
,
9166 static const nsCSSProperty textShadowValues
[] = {
9167 eCSSProperty_text_shadow
9170 // Number of properties we care about
9173 nsCSSValue
* values
[MOZ_ARRAY_LENGTH(backgroundValues
) +
9174 MOZ_ARRAY_LENGTH(borderValues
) +
9175 MOZ_ARRAY_LENGTH(paddingValues
) +
9176 MOZ_ARRAY_LENGTH(textShadowValues
)];
9178 nsCSSProperty properties
[MOZ_ARRAY_LENGTH(backgroundValues
) +
9179 MOZ_ARRAY_LENGTH(borderValues
) +
9180 MOZ_ARRAY_LENGTH(paddingValues
) +
9181 MOZ_ARRAY_LENGTH(textShadowValues
)];
9183 if (ruleTypeMask
& NS_AUTHOR_SPECIFIED_BACKGROUND
) {
9184 for (uint32_t i
= 0, i_end
= ArrayLength(backgroundValues
);
9186 properties
[nValues
] = backgroundValues
[i
];
9187 values
[nValues
++] = ruleData
.ValueFor(backgroundValues
[i
]);
9191 if (ruleTypeMask
& NS_AUTHOR_SPECIFIED_BORDER
) {
9192 for (uint32_t i
= 0, i_end
= ArrayLength(borderValues
);
9194 properties
[nValues
] = borderValues
[i
];
9195 values
[nValues
++] = ruleData
.ValueFor(borderValues
[i
]);
9199 if (ruleTypeMask
& NS_AUTHOR_SPECIFIED_PADDING
) {
9200 for (uint32_t i
= 0, i_end
= ArrayLength(paddingValues
);
9202 properties
[nValues
] = paddingValues
[i
];
9203 values
[nValues
++] = ruleData
.ValueFor(paddingValues
[i
]);
9207 if (ruleTypeMask
& NS_AUTHOR_SPECIFIED_TEXT_SHADOW
) {
9208 for (uint32_t i
= 0, i_end
= ArrayLength(textShadowValues
);
9210 properties
[nValues
] = textShadowValues
[i
];
9211 values
[nValues
++] = ruleData
.ValueFor(textShadowValues
[i
]);
9215 nsStyleContext
* styleContext
= aStyleContext
;
9217 // We need to be careful not to count styles covered up by user-important or
9218 // UA-important declarations. But we do want to catch explicit inherit
9219 // styling in those and check our parent style context to see whether we have
9220 // user styling for those properties. Note that we don't care here about
9221 // inheritance due to lack of a specified value, since all the properties we
9222 // care about are reset properties.
9223 bool haveExplicitUAInherit
;
9225 haveExplicitUAInherit
= false;
9226 for (nsRuleNode
* ruleNode
= styleContext
->RuleNode(); ruleNode
;
9227 ruleNode
= ruleNode
->GetParent()) {
9228 nsIStyleRule
*rule
= ruleNode
->GetRule();
9230 ruleData
.mLevel
= ruleNode
->GetLevel();
9231 ruleData
.mIsImportantRule
= ruleNode
->IsImportantRule();
9233 rule
->MapRuleInfoInto(&ruleData
);
9235 if (ruleData
.mLevel
== nsStyleSet::eAgentSheet
||
9236 ruleData
.mLevel
== nsStyleSet::eUserSheet
) {
9237 // This is a rule whose effect we want to ignore, so if any of
9238 // the properties we care about were set, set them to the dummy
9239 // value that they'll never otherwise get.
9240 for (uint32_t i
= 0; i
< nValues
; ++i
) {
9241 nsCSSUnit unit
= values
[i
]->GetUnit();
9242 if (unit
!= eCSSUnit_Null
&&
9243 unit
!= eCSSUnit_Dummy
&&
9244 unit
!= eCSSUnit_DummyInherit
) {
9245 if (unit
== eCSSUnit_Inherit
||
9246 (i
>= inheritedOffset
&& unit
== eCSSUnit_Unset
)) {
9247 haveExplicitUAInherit
= true;
9248 values
[i
]->SetDummyInheritValue();
9250 values
[i
]->SetDummyValue();
9255 // If any of the values we care about was set by the above rule,
9256 // we have author style.
9257 for (uint32_t i
= 0; i
< nValues
; ++i
) {
9258 if (values
[i
]->GetUnit() != eCSSUnit_Null
&&
9259 values
[i
]->GetUnit() != eCSSUnit_Dummy
&& // see above
9260 values
[i
]->GetUnit() != eCSSUnit_DummyInherit
) {
9261 // If author colors are not allowed, only claim to have
9262 // author-specified rules if we're looking at a non-color
9263 // property or if we're looking at the background color and it's
9264 // set to transparent. Anything else should get set to a dummy
9266 if (aAuthorColorsAllowed
||
9267 !nsCSSProps::PropHasFlags(properties
[i
],
9268 CSS_PROPERTY_IGNORED_WHEN_COLORS_DISABLED
) ||
9269 (properties
[i
] == eCSSProperty_background_color
&&
9270 !values
[i
]->IsNonTransparentColor())) {
9274 values
[i
]->SetDummyValue();
9281 if (haveExplicitUAInherit
) {
9282 // reset all the eCSSUnit_Null values to eCSSUnit_Dummy (since they're
9283 // not styled by the author, or by anyone else), and then reset all the
9284 // eCSSUnit_DummyInherit values to eCSSUnit_Null (so we will be able to
9285 // detect them being styled by the author) and move up to our parent
9287 for (uint32_t i
= 0; i
< nValues
; ++i
)
9288 if (values
[i
]->GetUnit() == eCSSUnit_Null
)
9289 values
[i
]->SetDummyValue();
9290 for (uint32_t i
= 0; i
< nValues
; ++i
)
9291 if (values
[i
]->GetUnit() == eCSSUnit_DummyInherit
)
9293 styleContext
= styleContext
->GetParent();
9295 } while (haveExplicitUAInherit
&& styleContext
);
9302 nsRuleNode::ComputeColor(const nsCSSValue
& aValue
, nsPresContext
* aPresContext
,
9303 nsStyleContext
* aStyleContext
, nscolor
& aResult
)
9305 MOZ_ASSERT(aValue
.GetUnit() != eCSSUnit_Inherit
,
9306 "aValue shouldn't have eCSSUnit_Inherit");
9307 MOZ_ASSERT(aValue
.GetUnit() != eCSSUnit_Initial
,
9308 "aValue shouldn't have eCSSUnit_Initial");
9309 MOZ_ASSERT(aValue
.GetUnit() != eCSSUnit_Unset
,
9310 "aValue shouldn't have eCSSUnit_Unset");
9312 bool canStoreInRuleTree
;
9313 bool ok
= SetColor(aValue
, NS_RGB(0, 0, 0), aPresContext
, aStyleContext
,
9314 aResult
, canStoreInRuleTree
);
9315 MOZ_ASSERT(ok
|| !(aPresContext
&& aStyleContext
));