1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 * structs that contain the data provided by nsStyleContext, the
8 * internal API for computed style data for an element
11 #include "nsStyleStruct.h"
12 #include "nsStyleStructInlines.h"
13 #include "nsStyleConsts.h"
14 #include "nsThemeConstants.h"
16 #include "nsPresContext.h"
17 #include "nsIWidget.h"
18 #include "nsCRTGlue.h"
19 #include "nsCSSProps.h"
23 #include "nsBidiUtils.h"
24 #include "nsLayoutUtils.h"
26 #include "imgIRequest.h"
27 #include "imgIContainer.h"
28 #include "CounterStyleManager.h"
30 #include "mozilla/Likely.h"
32 #include "nsIDocument.h"
35 static_assert((((1 << nsStyleStructID_Length
) - 1) &
36 ~(NS_STYLE_INHERIT_MASK
)) == 0,
37 "Not enough bits in NS_STYLE_INHERIT_MASK");
39 inline bool IsFixedUnit(const nsStyleCoord
& aCoord
, bool aEnumOK
)
41 return aCoord
.ConvertsToLength() ||
42 (aEnumOK
&& aCoord
.GetUnit() == eStyleUnit_Enumerated
);
45 static bool EqualURIs(nsIURI
*aURI1
, nsIURI
*aURI2
)
48 return aURI1
== aURI2
|| // handle null==null, and optimize
50 NS_SUCCEEDED(aURI1
->Equals(aURI2
, &eq
)) && // not equal on fail
54 static bool EqualURIs(mozilla::css::URLValue
*aURI1
, mozilla::css::URLValue
*aURI2
)
56 return aURI1
== aURI2
|| // handle null==null, and optimize
57 (aURI1
&& aURI2
&& aURI1
->URIEquals(*aURI2
));
60 static bool EqualImages(imgIRequest
*aImage1
, imgIRequest
* aImage2
)
62 if (aImage1
== aImage2
) {
66 if (!aImage1
|| !aImage2
) {
70 nsCOMPtr
<nsIURI
> uri1
, uri2
;
71 aImage1
->GetURI(getter_AddRefs(uri1
));
72 aImage2
->GetURI(getter_AddRefs(uri2
));
73 return EqualURIs(uri1
, uri2
);
76 // A nullsafe wrapper for strcmp. We depend on null-safety.
77 static int safe_strcmp(const char16_t
* a
, const char16_t
* b
)
82 return NS_strcmp(a
, b
);
85 static nsChangeHint
CalcShadowDifference(nsCSSShadowArray
* lhs
,
86 nsCSSShadowArray
* rhs
);
88 // --------------------
91 nsStyleFont::nsStyleFont(const nsFont
& aFont
, nsPresContext
*aPresContext
)
93 , mGenericID(kGenericFont_NONE
)
94 , mExplicitLanguage(false)
96 MOZ_COUNT_CTOR(nsStyleFont
);
100 nsStyleFont::nsStyleFont(const nsStyleFont
& aSrc
)
103 , mGenericID(aSrc
.mGenericID
)
104 , mScriptLevel(aSrc
.mScriptLevel
)
105 , mMathVariant(aSrc
.mMathVariant
)
106 , mMathDisplay(aSrc
.mMathDisplay
)
107 , mExplicitLanguage(aSrc
.mExplicitLanguage
)
108 , mAllowZoom(aSrc
.mAllowZoom
)
109 , mScriptUnconstrainedSize(aSrc
.mScriptUnconstrainedSize
)
110 , mScriptMinSize(aSrc
.mScriptMinSize
)
111 , mScriptSizeMultiplier(aSrc
.mScriptSizeMultiplier
)
112 , mLanguage(aSrc
.mLanguage
)
114 MOZ_COUNT_CTOR(nsStyleFont
);
117 nsStyleFont::nsStyleFont(nsPresContext
* aPresContext
)
118 // passing nullptr to GetDefaultFont make it use the doc language
119 : mFont(*(aPresContext
->GetDefaultFont(kPresContext_DefaultVariableFont_ID
,
121 , mGenericID(kGenericFont_NONE
)
122 , mExplicitLanguage(false)
124 MOZ_COUNT_CTOR(nsStyleFont
);
129 nsStyleFont::Init(nsPresContext
* aPresContext
)
131 mSize
= mFont
.size
= nsStyleFont::ZoomText(aPresContext
, mFont
.size
);
132 mScriptUnconstrainedSize
= mSize
;
133 mScriptMinSize
= aPresContext
->CSSTwipsToAppUnits(
134 NS_POINTS_TO_TWIPS(NS_MATHML_DEFAULT_SCRIPT_MIN_SIZE_PT
));
136 mScriptSizeMultiplier
= NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER
;
137 mMathVariant
= NS_MATHML_MATHVARIANT_NONE
;
138 mMathDisplay
= NS_MATHML_DISPLAYSTYLE_INLINE
;
141 nsAutoString language
;
142 aPresContext
->Document()->GetContentLanguage(language
);
143 language
.StripWhitespace();
145 // Content-Language may be a comma-separated list of language codes,
146 // in which case the HTML5 spec says to treat it as unknown
147 if (!language
.IsEmpty() &&
148 language
.FindChar(char16_t(',')) == kNotFound
) {
149 mLanguage
= do_GetAtom(language
);
150 // NOTE: This does *not* count as an explicit language; in other
151 // words, it doesn't trigger language-specific hyphenation.
153 // we didn't find a (usable) Content-Language, so we fall back
154 // to whatever the presContext guessed from the charset
155 mLanguage
= aPresContext
->GetLanguageFromCharset();
160 nsStyleFont::Destroy(nsPresContext
* aContext
) {
161 this->~nsStyleFont();
162 aContext
->PresShell()->
163 FreeByObjectID(nsPresArena::nsStyleFont_id
, this);
167 nsStyleFont::EnableZoom(nsPresContext
* aContext
, bool aEnable
)
169 if (mAllowZoom
== aEnable
) {
172 mAllowZoom
= aEnable
;
174 mSize
= nsStyleFont::ZoomText(aContext
, mSize
);
175 mFont
.size
= nsStyleFont::ZoomText(aContext
, mFont
.size
);
176 mScriptUnconstrainedSize
=
177 nsStyleFont::ZoomText(aContext
, mScriptUnconstrainedSize
);
179 mSize
= nsStyleFont::UnZoomText(aContext
, mSize
);
180 mFont
.size
= nsStyleFont::UnZoomText(aContext
, mFont
.size
);
181 mScriptUnconstrainedSize
=
182 nsStyleFont::UnZoomText(aContext
, mScriptUnconstrainedSize
);
186 nsChangeHint
nsStyleFont::CalcDifference(const nsStyleFont
& aOther
) const
188 MOZ_ASSERT(mAllowZoom
== aOther
.mAllowZoom
,
189 "expected mAllowZoom to be the same on both nsStyleFonts");
190 if (mSize
!= aOther
.mSize
||
191 mLanguage
!= aOther
.mLanguage
||
192 mExplicitLanguage
!= aOther
.mExplicitLanguage
||
193 mMathVariant
!= aOther
.mMathVariant
||
194 mMathDisplay
!= aOther
.mMathDisplay
) {
195 return NS_STYLE_HINT_REFLOW
;
197 return CalcFontDifference(mFont
, aOther
.mFont
);
201 nsStyleFont::ZoomText(nsPresContext
*aPresContext
, nscoord aSize
)
203 return nscoord(float(aSize
) * aPresContext
->TextZoom());
207 nsStyleFont::UnZoomText(nsPresContext
*aPresContext
, nscoord aSize
)
209 return nscoord(float(aSize
) / aPresContext
->TextZoom());
212 nsChangeHint
nsStyleFont::CalcFontDifference(const nsFont
& aFont1
, const nsFont
& aFont2
)
214 if ((aFont1
.size
== aFont2
.size
) &&
215 (aFont1
.sizeAdjust
== aFont2
.sizeAdjust
) &&
216 (aFont1
.style
== aFont2
.style
) &&
217 (aFont1
.weight
== aFont2
.weight
) &&
218 (aFont1
.stretch
== aFont2
.stretch
) &&
219 (aFont1
.smoothing
== aFont2
.smoothing
) &&
220 (aFont1
.fontlist
== aFont2
.fontlist
) &&
221 (aFont1
.kerning
== aFont2
.kerning
) &&
222 (aFont1
.synthesis
== aFont2
.synthesis
) &&
223 (aFont1
.variantAlternates
== aFont2
.variantAlternates
) &&
224 (aFont1
.alternateValues
== aFont2
.alternateValues
) &&
225 (aFont1
.featureValueLookup
== aFont2
.featureValueLookup
) &&
226 (aFont1
.variantCaps
== aFont2
.variantCaps
) &&
227 (aFont1
.variantEastAsian
== aFont2
.variantEastAsian
) &&
228 (aFont1
.variantLigatures
== aFont2
.variantLigatures
) &&
229 (aFont1
.variantNumeric
== aFont2
.variantNumeric
) &&
230 (aFont1
.variantPosition
== aFont2
.variantPosition
) &&
231 (aFont1
.fontFeatureSettings
== aFont2
.fontFeatureSettings
) &&
232 (aFont1
.languageOverride
== aFont2
.languageOverride
) &&
233 (aFont1
.systemFont
== aFont2
.systemFont
)) {
234 if ((aFont1
.decorations
== aFont2
.decorations
)) {
235 return NS_STYLE_HINT_NONE
;
237 return NS_STYLE_HINT_VISUAL
;
239 return NS_STYLE_HINT_REFLOW
;
242 static bool IsFixedData(const nsStyleSides
& aSides
, bool aEnumOK
)
244 NS_FOR_CSS_SIDES(side
) {
245 if (!IsFixedUnit(aSides
.Get(side
), aEnumOK
))
251 static nscoord
CalcCoord(const nsStyleCoord
& aCoord
,
252 const nscoord
* aEnumTable
,
255 if (aCoord
.GetUnit() == eStyleUnit_Enumerated
) {
256 NS_ABORT_IF_FALSE(aEnumTable
, "must have enum table");
257 int32_t value
= aCoord
.GetIntValue();
258 if (0 <= value
&& value
< aNumEnums
) {
259 return aEnumTable
[aCoord
.GetIntValue()];
261 NS_NOTREACHED("unexpected enum value");
264 NS_ABORT_IF_FALSE(aCoord
.ConvertsToLength(), "unexpected unit");
265 return nsRuleNode::ComputeCoordPercentCalc(aCoord
, 0);
268 nsStyleMargin::nsStyleMargin()
269 : mHasCachedMargin(false)
270 , mCachedMargin(0, 0, 0, 0)
272 MOZ_COUNT_CTOR(nsStyleMargin
);
273 nsStyleCoord
zero(0, nsStyleCoord::CoordConstructor
);
274 NS_FOR_CSS_SIDES(side
) {
275 mMargin
.Set(side
, zero
);
279 nsStyleMargin::nsStyleMargin(const nsStyleMargin
& aSrc
)
280 : mMargin(aSrc
.mMargin
)
281 , mHasCachedMargin(false)
282 , mCachedMargin(0, 0, 0, 0)
284 MOZ_COUNT_CTOR(nsStyleMargin
);
288 nsStyleMargin::Destroy(nsPresContext
* aContext
) {
289 this->~nsStyleMargin();
290 aContext
->PresShell()->
291 FreeByObjectID(nsPresArena::nsStyleMargin_id
, this);
295 void nsStyleMargin::RecalcData()
297 if (IsFixedData(mMargin
, false)) {
298 NS_FOR_CSS_SIDES(side
) {
299 mCachedMargin
.Side(side
) = CalcCoord(mMargin
.Get(side
), nullptr, 0);
301 mHasCachedMargin
= true;
304 mHasCachedMargin
= false;
307 nsChangeHint
nsStyleMargin::CalcDifference(const nsStyleMargin
& aOther
) const
309 if (mMargin
== aOther
.mMargin
) {
310 return NS_STYLE_HINT_NONE
;
312 // Margin differences can't affect descendant intrinsic sizes and
313 // don't need to force children to reflow.
314 return NS_CombineHint(nsChangeHint_NeedReflow
,
315 nsChangeHint_ClearAncestorIntrinsics
);
318 nsStylePadding::nsStylePadding()
319 : mHasCachedPadding(false)
320 , mCachedPadding(0, 0, 0, 0)
322 MOZ_COUNT_CTOR(nsStylePadding
);
323 nsStyleCoord
zero(0, nsStyleCoord::CoordConstructor
);
324 NS_FOR_CSS_SIDES(side
) {
325 mPadding
.Set(side
, zero
);
329 nsStylePadding::nsStylePadding(const nsStylePadding
& aSrc
)
330 : mPadding(aSrc
.mPadding
)
331 , mHasCachedPadding(false)
332 , mCachedPadding(0, 0, 0, 0)
334 MOZ_COUNT_CTOR(nsStylePadding
);
338 nsStylePadding::Destroy(nsPresContext
* aContext
) {
339 this->~nsStylePadding();
340 aContext
->PresShell()->
341 FreeByObjectID(nsPresArena::nsStylePadding_id
, this);
344 void nsStylePadding::RecalcData()
346 if (IsFixedData(mPadding
, false)) {
347 NS_FOR_CSS_SIDES(side
) {
348 // Clamp negative calc() to 0.
349 mCachedPadding
.Side(side
) =
350 std::max(CalcCoord(mPadding
.Get(side
), nullptr, 0), 0);
352 mHasCachedPadding
= true;
355 mHasCachedPadding
= false;
358 nsChangeHint
nsStylePadding::CalcDifference(const nsStylePadding
& aOther
) const
360 if (mPadding
== aOther
.mPadding
) {
361 return NS_STYLE_HINT_NONE
;
363 // Padding differences can't affect descendant intrinsic sizes, but do need
364 // to force children to reflow so that we can reposition them, since their
365 // offsets are from our frame bounds but our content rect's position within
366 // those bounds is moving.
367 return NS_SubtractHint(NS_STYLE_HINT_REFLOW
,
368 nsChangeHint_ClearDescendantIntrinsics
);
371 nsStyleBorder::nsStyleBorder(nsPresContext
* aPresContext
)
372 : mBorderColors(nullptr),
374 mBorderImageFill(NS_STYLE_BORDER_IMAGE_SLICE_NOFILL
),
375 mBorderImageRepeatH(NS_STYLE_BORDER_IMAGE_REPEAT_STRETCH
),
376 mBorderImageRepeatV(NS_STYLE_BORDER_IMAGE_REPEAT_STRETCH
),
377 mFloatEdge(NS_STYLE_FLOAT_EDGE_CONTENT
),
378 mBoxDecorationBreak(NS_STYLE_BOX_DECORATION_BREAK_SLICE
),
379 mComputedBorder(0, 0, 0, 0)
381 MOZ_COUNT_CTOR(nsStyleBorder
);
383 NS_FOR_CSS_HALF_CORNERS (corner
) {
384 mBorderRadius
.Set(corner
, nsStyleCoord(0, nsStyleCoord::CoordConstructor
));
388 (aPresContext
->GetBorderWidthTable())[NS_STYLE_BORDER_WIDTH_MEDIUM
];
389 NS_FOR_CSS_SIDES(side
) {
390 mBorderImageSlice
.Set(side
, nsStyleCoord(1.0f
, eStyleUnit_Percent
));
391 mBorderImageWidth
.Set(side
, nsStyleCoord(1.0f
, eStyleUnit_Factor
));
392 mBorderImageOutset
.Set(side
, nsStyleCoord(0.0f
, eStyleUnit_Factor
));
394 mBorder
.Side(side
) = medium
;
395 mBorderStyle
[side
] = NS_STYLE_BORDER_STYLE_NONE
| BORDER_COLOR_FOREGROUND
;
396 mBorderColor
[side
] = NS_RGB(0, 0, 0);
399 mTwipsPerPixel
= aPresContext
->DevPixelsToAppUnits(1);
402 nsBorderColors::~nsBorderColors()
404 NS_CSS_DELETE_LIST_MEMBER(nsBorderColors
, this, mNext
);
408 nsBorderColors::Clone(bool aDeep
) const
410 nsBorderColors
* result
= new nsBorderColors(mColor
);
411 if (MOZ_UNLIKELY(!result
))
414 NS_CSS_CLONE_LIST_MEMBER(nsBorderColors
, this, mNext
, result
, (false));
418 nsStyleBorder::nsStyleBorder(const nsStyleBorder
& aSrc
)
419 : mBorderColors(nullptr),
420 mBoxShadow(aSrc
.mBoxShadow
),
421 mBorderRadius(aSrc
.mBorderRadius
),
422 mBorderImageSource(aSrc
.mBorderImageSource
),
423 mBorderImageSlice(aSrc
.mBorderImageSlice
),
424 mBorderImageWidth(aSrc
.mBorderImageWidth
),
425 mBorderImageOutset(aSrc
.mBorderImageOutset
),
426 mBorderImageFill(aSrc
.mBorderImageFill
),
427 mBorderImageRepeatH(aSrc
.mBorderImageRepeatH
),
428 mBorderImageRepeatV(aSrc
.mBorderImageRepeatV
),
429 mFloatEdge(aSrc
.mFloatEdge
),
430 mBoxDecorationBreak(aSrc
.mBoxDecorationBreak
),
431 mComputedBorder(aSrc
.mComputedBorder
),
432 mBorder(aSrc
.mBorder
),
433 mTwipsPerPixel(aSrc
.mTwipsPerPixel
)
435 MOZ_COUNT_CTOR(nsStyleBorder
);
436 if (aSrc
.mBorderColors
) {
437 EnsureBorderColors();
438 for (int32_t i
= 0; i
< 4; i
++)
439 if (aSrc
.mBorderColors
[i
])
440 mBorderColors
[i
] = aSrc
.mBorderColors
[i
]->Clone();
442 mBorderColors
[i
] = nullptr;
445 NS_FOR_CSS_SIDES(side
) {
446 mBorderStyle
[side
] = aSrc
.mBorderStyle
[side
];
447 mBorderColor
[side
] = aSrc
.mBorderColor
[side
];
451 nsStyleBorder::~nsStyleBorder()
453 MOZ_COUNT_DTOR(nsStyleBorder
);
455 for (int32_t i
= 0; i
< 4; i
++)
456 delete mBorderColors
[i
];
457 delete [] mBorderColors
;
462 nsStyleBorder::GetImageOutset() const
464 // We don't check whether there is a border-image (which is OK since
465 // the initial values yields 0 outset) so that we don't have to
466 // reflow to update overflow areas when an image loads.
468 NS_FOR_CSS_SIDES(s
) {
469 nsStyleCoord coord
= mBorderImageOutset
.Get(s
);
471 switch (coord
.GetUnit()) {
472 case eStyleUnit_Coord
:
473 value
= coord
.GetCoordValue();
475 case eStyleUnit_Factor
:
476 value
= coord
.GetFactorValue() * mComputedBorder
.Side(s
);
479 NS_NOTREACHED("unexpected CSS unit for image outset");
483 outset
.Side(s
) = value
;
489 nsStyleBorder::Destroy(nsPresContext
* aContext
) {
490 UntrackImage(aContext
);
491 this->~nsStyleBorder();
492 aContext
->PresShell()->
493 FreeByObjectID(nsPresArena::nsStyleBorder_id
, this);
496 nsChangeHint
nsStyleBorder::CalcDifference(const nsStyleBorder
& aOther
) const
498 nsChangeHint shadowDifference
=
499 CalcShadowDifference(mBoxShadow
, aOther
.mBoxShadow
);
500 NS_ABORT_IF_FALSE(shadowDifference
== unsigned(NS_STYLE_HINT_REFLOW
) ||
501 shadowDifference
== unsigned(NS_STYLE_HINT_VISUAL
) ||
502 shadowDifference
== unsigned(NS_STYLE_HINT_NONE
),
503 "should do more with shadowDifference");
505 // Note that differences in mBorder don't affect rendering (which should only
506 // use mComputedBorder), so don't need to be tested for here.
507 // XXXbz we should be able to return a more specific change hint for
508 // at least GetComputedBorder() differences...
509 if (mTwipsPerPixel
!= aOther
.mTwipsPerPixel
||
510 GetComputedBorder() != aOther
.GetComputedBorder() ||
511 mFloatEdge
!= aOther
.mFloatEdge
||
512 mBorderImageOutset
!= aOther
.mBorderImageOutset
||
513 (shadowDifference
& nsChangeHint_NeedReflow
) ||
514 mBoxDecorationBreak
!= aOther
.mBoxDecorationBreak
)
515 return NS_STYLE_HINT_REFLOW
;
517 NS_FOR_CSS_SIDES(ix
) {
518 // See the explanation in nsChangeHint.h of
519 // nsChangeHint_BorderStyleNoneChange .
520 // Furthermore, even though we know *this* side is 0 width, just
521 // assume a visual hint for some other change rather than bother
522 // tracking this result through the rest of the function.
523 if (HasVisibleStyle(ix
) != aOther
.HasVisibleStyle(ix
)) {
524 return NS_CombineHint(NS_STYLE_HINT_VISUAL
,
525 nsChangeHint_BorderStyleNoneChange
);
529 // Note that mBorderStyle stores not only the border style but also
530 // color-related flags. Given that we've already done an mComputedBorder
531 // comparison, border-style differences can only lead to a VISUAL hint. So
532 // it's OK to just compare the values directly -- if either the actual
533 // style or the color flags differ we want to repaint.
534 NS_FOR_CSS_SIDES(ix
) {
535 if (mBorderStyle
[ix
] != aOther
.mBorderStyle
[ix
] ||
536 mBorderColor
[ix
] != aOther
.mBorderColor
[ix
])
537 return NS_STYLE_HINT_VISUAL
;
540 if (mBorderRadius
!= aOther
.mBorderRadius
||
541 !mBorderColors
!= !aOther
.mBorderColors
)
542 return NS_STYLE_HINT_VISUAL
;
544 if (IsBorderImageLoaded() || aOther
.IsBorderImageLoaded()) {
545 if (mBorderImageSource
!= aOther
.mBorderImageSource
||
546 mBorderImageRepeatH
!= aOther
.mBorderImageRepeatH
||
547 mBorderImageRepeatV
!= aOther
.mBorderImageRepeatV
||
548 mBorderImageSlice
!= aOther
.mBorderImageSlice
||
549 mBorderImageFill
!= aOther
.mBorderImageFill
||
550 mBorderImageWidth
!= aOther
.mBorderImageWidth
||
551 mBorderImageOutset
!= aOther
.mBorderImageOutset
)
552 return NS_STYLE_HINT_VISUAL
;
555 // Note that at this point if mBorderColors is non-null so is
556 // aOther.mBorderColors
558 NS_FOR_CSS_SIDES(ix
) {
559 if (!nsBorderColors::Equal(mBorderColors
[ix
],
560 aOther
.mBorderColors
[ix
]))
561 return NS_STYLE_HINT_VISUAL
;
565 return shadowDifference
;
568 nsStyleOutline::nsStyleOutline(nsPresContext
* aPresContext
)
570 MOZ_COUNT_CTOR(nsStyleOutline
);
571 // spacing values not inherited
572 nsStyleCoord
zero(0, nsStyleCoord::CoordConstructor
);
573 NS_FOR_CSS_HALF_CORNERS(corner
) {
574 mOutlineRadius
.Set(corner
, zero
);
579 mOutlineWidth
= nsStyleCoord(NS_STYLE_BORDER_WIDTH_MEDIUM
, eStyleUnit_Enumerated
);
580 mOutlineStyle
= NS_STYLE_BORDER_STYLE_NONE
;
581 mOutlineColor
= NS_RGB(0, 0, 0);
583 mHasCachedOutline
= false;
584 mTwipsPerPixel
= aPresContext
->DevPixelsToAppUnits(1);
587 nsStyleOutline::nsStyleOutline(const nsStyleOutline
& aSrc
)
588 : mOutlineRadius(aSrc
.mOutlineRadius
)
589 , mOutlineWidth(aSrc
.mOutlineWidth
)
590 , mOutlineOffset(aSrc
.mOutlineOffset
)
591 , mCachedOutlineWidth(aSrc
.mCachedOutlineWidth
)
592 , mOutlineColor(aSrc
.mOutlineColor
)
593 , mHasCachedOutline(aSrc
.mHasCachedOutline
)
594 , mOutlineStyle(aSrc
.mOutlineStyle
)
595 , mTwipsPerPixel(aSrc
.mTwipsPerPixel
)
597 MOZ_COUNT_CTOR(nsStyleOutline
);
601 nsStyleOutline::RecalcData(nsPresContext
* aContext
)
603 if (NS_STYLE_BORDER_STYLE_NONE
== GetOutlineStyle()) {
604 mCachedOutlineWidth
= 0;
605 mHasCachedOutline
= true;
606 } else if (IsFixedUnit(mOutlineWidth
, true)) {
607 // Clamp negative calc() to 0.
608 mCachedOutlineWidth
=
609 std::max(CalcCoord(mOutlineWidth
, aContext
->GetBorderWidthTable(), 3), 0);
610 mCachedOutlineWidth
=
611 NS_ROUND_BORDER_TO_PIXELS(mCachedOutlineWidth
, mTwipsPerPixel
);
612 mHasCachedOutline
= true;
615 mHasCachedOutline
= false;
618 nsChangeHint
nsStyleOutline::CalcDifference(const nsStyleOutline
& aOther
) const
620 bool outlineWasVisible
=
621 mCachedOutlineWidth
> 0 && mOutlineStyle
!= NS_STYLE_BORDER_STYLE_NONE
;
622 bool outlineIsVisible
=
623 aOther
.mCachedOutlineWidth
> 0 && aOther
.mOutlineStyle
!= NS_STYLE_BORDER_STYLE_NONE
;
624 if (outlineWasVisible
!= outlineIsVisible
||
625 (outlineIsVisible
&& (mOutlineOffset
!= aOther
.mOutlineOffset
||
626 mOutlineWidth
!= aOther
.mOutlineWidth
||
627 mTwipsPerPixel
!= aOther
.mTwipsPerPixel
))) {
628 return NS_CombineHint(nsChangeHint_AllReflowHints
,
629 nsChangeHint_RepaintFrame
);
631 if ((mOutlineStyle
!= aOther
.mOutlineStyle
) ||
632 (mOutlineColor
!= aOther
.mOutlineColor
) ||
633 (mOutlineRadius
!= aOther
.mOutlineRadius
)) {
634 return nsChangeHint_RepaintFrame
;
636 return NS_STYLE_HINT_NONE
;
639 // --------------------
642 nsStyleList::nsStyleList(nsPresContext
* aPresContext
)
643 : mListStylePosition(NS_STYLE_LIST_STYLE_POSITION_OUTSIDE
),
644 mListStyleType(NS_LITERAL_STRING("disc")),
645 mCounterStyle(aPresContext
->CounterStyleManager()->
646 BuildCounterStyle(mListStyleType
))
648 MOZ_COUNT_CTOR(nsStyleList
);
651 nsStyleList::~nsStyleList()
653 MOZ_COUNT_DTOR(nsStyleList
);
656 nsStyleList::nsStyleList(const nsStyleList
& aSource
)
657 : mListStylePosition(aSource
.mListStylePosition
),
658 mListStyleType(aSource
.mListStyleType
),
659 mCounterStyle(aSource
.mCounterStyle
),
660 mImageRegion(aSource
.mImageRegion
)
662 SetListStyleImage(aSource
.GetListStyleImage());
663 MOZ_COUNT_CTOR(nsStyleList
);
666 nsChangeHint
nsStyleList::CalcDifference(const nsStyleList
& aOther
) const
668 if (mListStylePosition
!= aOther
.mListStylePosition
)
669 return NS_STYLE_HINT_FRAMECHANGE
;
670 if (EqualImages(mListStyleImage
, aOther
.mListStyleImage
) &&
671 mListStyleType
== aOther
.mListStyleType
) {
672 if (mImageRegion
.IsEqualInterior(aOther
.mImageRegion
))
673 return NS_STYLE_HINT_NONE
;
674 if (mImageRegion
.width
== aOther
.mImageRegion
.width
&&
675 mImageRegion
.height
== aOther
.mImageRegion
.height
)
676 return NS_STYLE_HINT_VISUAL
;
678 return NS_STYLE_HINT_REFLOW
;
681 // --------------------
684 nsStyleXUL::nsStyleXUL()
686 MOZ_COUNT_CTOR(nsStyleXUL
);
687 mBoxAlign
= NS_STYLE_BOX_ALIGN_STRETCH
;
688 mBoxDirection
= NS_STYLE_BOX_DIRECTION_NORMAL
;
690 mBoxOrient
= NS_STYLE_BOX_ORIENT_HORIZONTAL
;
691 mBoxPack
= NS_STYLE_BOX_PACK_START
;
693 mStretchStack
= true;
696 nsStyleXUL::~nsStyleXUL()
698 MOZ_COUNT_DTOR(nsStyleXUL
);
701 nsStyleXUL::nsStyleXUL(const nsStyleXUL
& aSource
)
702 : mBoxFlex(aSource
.mBoxFlex
)
703 , mBoxOrdinal(aSource
.mBoxOrdinal
)
704 , mBoxAlign(aSource
.mBoxAlign
)
705 , mBoxDirection(aSource
.mBoxDirection
)
706 , mBoxOrient(aSource
.mBoxOrient
)
707 , mBoxPack(aSource
.mBoxPack
)
708 , mStretchStack(aSource
.mStretchStack
)
710 MOZ_COUNT_CTOR(nsStyleXUL
);
713 nsChangeHint
nsStyleXUL::CalcDifference(const nsStyleXUL
& aOther
) const
715 if (mBoxAlign
== aOther
.mBoxAlign
&&
716 mBoxDirection
== aOther
.mBoxDirection
&&
717 mBoxFlex
== aOther
.mBoxFlex
&&
718 mBoxOrient
== aOther
.mBoxOrient
&&
719 mBoxPack
== aOther
.mBoxPack
&&
720 mBoxOrdinal
== aOther
.mBoxOrdinal
&&
721 mStretchStack
== aOther
.mStretchStack
)
722 return NS_STYLE_HINT_NONE
;
723 if (mBoxOrdinal
!= aOther
.mBoxOrdinal
)
724 return NS_STYLE_HINT_FRAMECHANGE
;
725 return NS_STYLE_HINT_REFLOW
;
728 // --------------------
731 /* static */ const uint32_t nsStyleColumn::kMaxColumnCount
= 1000;
733 nsStyleColumn::nsStyleColumn(nsPresContext
* aPresContext
)
735 MOZ_COUNT_CTOR(nsStyleColumn
);
736 mColumnCount
= NS_STYLE_COLUMN_COUNT_AUTO
;
737 mColumnWidth
.SetAutoValue();
738 mColumnGap
.SetNormalValue();
739 mColumnFill
= NS_STYLE_COLUMN_FILL_BALANCE
;
741 mColumnRuleWidth
= (aPresContext
->GetBorderWidthTable())[NS_STYLE_BORDER_WIDTH_MEDIUM
];
742 mColumnRuleStyle
= NS_STYLE_BORDER_STYLE_NONE
;
743 mColumnRuleColor
= NS_RGB(0, 0, 0);
744 mColumnRuleColorIsForeground
= true;
746 mTwipsPerPixel
= aPresContext
->AppUnitsPerDevPixel();
749 nsStyleColumn::~nsStyleColumn()
751 MOZ_COUNT_DTOR(nsStyleColumn
);
754 nsStyleColumn::nsStyleColumn(const nsStyleColumn
& aSource
)
755 : mColumnCount(aSource
.mColumnCount
)
756 , mColumnWidth(aSource
.mColumnWidth
)
757 , mColumnGap(aSource
.mColumnGap
)
758 , mColumnRuleColor(aSource
.mColumnRuleColor
)
759 , mColumnRuleStyle(aSource
.mColumnRuleStyle
)
760 , mColumnFill(aSource
.mColumnFill
)
761 , mColumnRuleColorIsForeground(aSource
.mColumnRuleColorIsForeground
)
762 , mColumnRuleWidth(aSource
.mColumnRuleWidth
)
763 , mTwipsPerPixel(aSource
.mTwipsPerPixel
)
765 MOZ_COUNT_CTOR(nsStyleColumn
);
768 nsChangeHint
nsStyleColumn::CalcDifference(const nsStyleColumn
& aOther
) const
770 if ((mColumnWidth
.GetUnit() == eStyleUnit_Auto
)
771 != (aOther
.mColumnWidth
.GetUnit() == eStyleUnit_Auto
) ||
772 mColumnCount
!= aOther
.mColumnCount
)
773 // We force column count changes to do a reframe, because it's tricky to handle
774 // some edge cases where the column count gets smaller and content overflows.
776 return NS_STYLE_HINT_FRAMECHANGE
;
778 if (mColumnWidth
!= aOther
.mColumnWidth
||
779 mColumnGap
!= aOther
.mColumnGap
||
780 mColumnFill
!= aOther
.mColumnFill
)
781 return NS_STYLE_HINT_REFLOW
;
783 if (GetComputedColumnRuleWidth() != aOther
.GetComputedColumnRuleWidth() ||
784 mColumnRuleStyle
!= aOther
.mColumnRuleStyle
||
785 mColumnRuleColor
!= aOther
.mColumnRuleColor
||
786 mColumnRuleColorIsForeground
!= aOther
.mColumnRuleColorIsForeground
)
787 return NS_STYLE_HINT_VISUAL
;
789 return NS_STYLE_HINT_NONE
;
792 // --------------------
795 nsStyleSVG::nsStyleSVG()
797 MOZ_COUNT_CTOR(nsStyleSVG
);
798 mFill
.mType
= eStyleSVGPaintType_Color
;
799 mFill
.mPaint
.mColor
= NS_RGB(0,0,0);
800 mFill
.mFallbackColor
= NS_RGB(0,0,0);
801 mStroke
.mType
= eStyleSVGPaintType_None
;
802 mStroke
.mPaint
.mColor
= NS_RGB(0,0,0);
803 mStroke
.mFallbackColor
= NS_RGB(0,0,0);
804 mStrokeDasharray
= nullptr;
806 mStrokeDashoffset
.SetCoordValue(0);
807 mStrokeWidth
.SetCoordValue(nsPresContext::CSSPixelsToAppUnits(1));
810 mStrokeMiterlimit
= 4.0f
;
811 mStrokeOpacity
= 1.0f
;
813 mStrokeDasharrayLength
= 0;
814 mClipRule
= NS_STYLE_FILL_RULE_NONZERO
;
815 mColorInterpolation
= NS_STYLE_COLOR_INTERPOLATION_SRGB
;
816 mColorInterpolationFilters
= NS_STYLE_COLOR_INTERPOLATION_LINEARRGB
;
817 mFillRule
= NS_STYLE_FILL_RULE_NONZERO
;
818 mImageRendering
= NS_STYLE_IMAGE_RENDERING_AUTO
;
819 mPaintOrder
= NS_STYLE_PAINT_ORDER_NORMAL
;
820 mShapeRendering
= NS_STYLE_SHAPE_RENDERING_AUTO
;
821 mStrokeLinecap
= NS_STYLE_STROKE_LINECAP_BUTT
;
822 mStrokeLinejoin
= NS_STYLE_STROKE_LINEJOIN_MITER
;
823 mTextAnchor
= NS_STYLE_TEXT_ANCHOR_START
;
824 mTextRendering
= NS_STYLE_TEXT_RENDERING_AUTO
;
825 mFillOpacitySource
= eStyleSVGOpacitySource_Normal
;
826 mStrokeOpacitySource
= eStyleSVGOpacitySource_Normal
;
827 mStrokeDasharrayFromObject
= false;
828 mStrokeDashoffsetFromObject
= false;
829 mStrokeWidthFromObject
= false;
832 nsStyleSVG::~nsStyleSVG()
834 MOZ_COUNT_DTOR(nsStyleSVG
);
835 delete [] mStrokeDasharray
;
838 nsStyleSVG::nsStyleSVG(const nsStyleSVG
& aSource
)
840 MOZ_COUNT_CTOR(nsStyleSVG
);
841 mFill
= aSource
.mFill
;
842 mStroke
= aSource
.mStroke
;
844 mMarkerEnd
= aSource
.mMarkerEnd
;
845 mMarkerMid
= aSource
.mMarkerMid
;
846 mMarkerStart
= aSource
.mMarkerStart
;
848 mStrokeDasharrayLength
= aSource
.mStrokeDasharrayLength
;
849 if (aSource
.mStrokeDasharray
) {
850 mStrokeDasharray
= new nsStyleCoord
[mStrokeDasharrayLength
];
851 if (mStrokeDasharray
) {
852 for (size_t i
= 0; i
< mStrokeDasharrayLength
; i
++) {
853 mStrokeDasharray
[i
] = aSource
.mStrokeDasharray
[i
];
856 mStrokeDasharrayLength
= 0;
859 mStrokeDasharray
= nullptr;
862 mStrokeDashoffset
= aSource
.mStrokeDashoffset
;
863 mStrokeWidth
= aSource
.mStrokeWidth
;
865 mFillOpacity
= aSource
.mFillOpacity
;
866 mStrokeMiterlimit
= aSource
.mStrokeMiterlimit
;
867 mStrokeOpacity
= aSource
.mStrokeOpacity
;
869 mClipRule
= aSource
.mClipRule
;
870 mColorInterpolation
= aSource
.mColorInterpolation
;
871 mColorInterpolationFilters
= aSource
.mColorInterpolationFilters
;
872 mFillRule
= aSource
.mFillRule
;
873 mImageRendering
= aSource
.mImageRendering
;
874 mPaintOrder
= aSource
.mPaintOrder
;
875 mShapeRendering
= aSource
.mShapeRendering
;
876 mStrokeLinecap
= aSource
.mStrokeLinecap
;
877 mStrokeLinejoin
= aSource
.mStrokeLinejoin
;
878 mTextAnchor
= aSource
.mTextAnchor
;
879 mTextRendering
= aSource
.mTextRendering
;
880 mFillOpacitySource
= aSource
.mFillOpacitySource
;
881 mStrokeOpacitySource
= aSource
.mStrokeOpacitySource
;
882 mStrokeDasharrayFromObject
= aSource
.mStrokeDasharrayFromObject
;
883 mStrokeDashoffsetFromObject
= aSource
.mStrokeDashoffsetFromObject
;
884 mStrokeWidthFromObject
= aSource
.mStrokeWidthFromObject
;
887 static bool PaintURIChanged(const nsStyleSVGPaint
& aPaint1
,
888 const nsStyleSVGPaint
& aPaint2
)
890 if (aPaint1
.mType
!= aPaint2
.mType
) {
891 return aPaint1
.mType
== eStyleSVGPaintType_Server
||
892 aPaint2
.mType
== eStyleSVGPaintType_Server
;
894 return aPaint1
.mType
== eStyleSVGPaintType_Server
&&
895 !EqualURIs(aPaint1
.mPaint
.mPaintServer
, aPaint2
.mPaint
.mPaintServer
);
898 nsChangeHint
nsStyleSVG::CalcDifference(const nsStyleSVG
& aOther
) const
900 nsChangeHint hint
= nsChangeHint(0);
902 if (!EqualURIs(mMarkerEnd
, aOther
.mMarkerEnd
) ||
903 !EqualURIs(mMarkerMid
, aOther
.mMarkerMid
) ||
904 !EqualURIs(mMarkerStart
, aOther
.mMarkerStart
)) {
905 // Markers currently contribute to nsSVGPathGeometryFrame::mRect,
906 // so we need a reflow as well as a repaint. No intrinsic sizes need
907 // to change, so nsChangeHint_NeedReflow is sufficient.
908 NS_UpdateHint(hint
, nsChangeHint_UpdateEffects
);
909 NS_UpdateHint(hint
, nsChangeHint_NeedReflow
);
910 NS_UpdateHint(hint
, nsChangeHint_NeedDirtyReflow
); // XXX remove me: bug 876085
911 NS_UpdateHint(hint
, nsChangeHint_RepaintFrame
);
915 if (mFill
!= aOther
.mFill
||
916 mStroke
!= aOther
.mStroke
||
917 mFillOpacity
!= aOther
.mFillOpacity
||
918 mStrokeOpacity
!= aOther
.mStrokeOpacity
) {
919 NS_UpdateHint(hint
, nsChangeHint_RepaintFrame
);
920 if (HasStroke() != aOther
.HasStroke() ||
921 (!HasStroke() && HasFill() != aOther
.HasFill())) {
922 // Frame bounds and overflow rects depend on whether we "have" fill or
923 // stroke. Whether we have stroke or not just changed, or else we have no
924 // stroke (in which case whether we have fill or not is significant to frame
925 // bounds) and whether we have fill or not just changed. In either case we
926 // need to reflow so the frame rect is updated.
927 // XXXperf this is a waste on non nsSVGPathGeometryFrames.
928 NS_UpdateHint(hint
, nsChangeHint_NeedReflow
);
929 NS_UpdateHint(hint
, nsChangeHint_NeedDirtyReflow
); // XXX remove me: bug 876085
931 if (PaintURIChanged(mFill
, aOther
.mFill
) ||
932 PaintURIChanged(mStroke
, aOther
.mStroke
)) {
933 NS_UpdateHint(hint
, nsChangeHint_UpdateEffects
);
937 // Stroke currently contributes to nsSVGPathGeometryFrame::mRect, so
938 // we need a reflow here. No intrinsic sizes need to change, so
939 // nsChangeHint_NeedReflow is sufficient.
940 // Note that stroke-dashoffset does not affect nsSVGPathGeometryFrame::mRect.
941 // text-anchor and text-rendering changes also require a reflow since they
942 // change frames' rects.
943 if (mStrokeWidth
!= aOther
.mStrokeWidth
||
944 mStrokeMiterlimit
!= aOther
.mStrokeMiterlimit
||
945 mStrokeLinecap
!= aOther
.mStrokeLinecap
||
946 mStrokeLinejoin
!= aOther
.mStrokeLinejoin
||
947 mTextAnchor
!= aOther
.mTextAnchor
||
948 mTextRendering
!= aOther
.mTextRendering
) {
949 NS_UpdateHint(hint
, nsChangeHint_NeedReflow
);
950 NS_UpdateHint(hint
, nsChangeHint_NeedDirtyReflow
); // XXX remove me: bug 876085
951 NS_UpdateHint(hint
, nsChangeHint_RepaintFrame
);
955 if (hint
& nsChangeHint_RepaintFrame
) {
956 return hint
; // we don't add anything else below
959 if ( mStrokeDashoffset
!= aOther
.mStrokeDashoffset
||
960 mClipRule
!= aOther
.mClipRule
||
961 mColorInterpolation
!= aOther
.mColorInterpolation
||
962 mColorInterpolationFilters
!= aOther
.mColorInterpolationFilters
||
963 mFillRule
!= aOther
.mFillRule
||
964 mImageRendering
!= aOther
.mImageRendering
||
965 mPaintOrder
!= aOther
.mPaintOrder
||
966 mShapeRendering
!= aOther
.mShapeRendering
||
967 mStrokeDasharrayLength
!= aOther
.mStrokeDasharrayLength
||
968 mFillOpacitySource
!= aOther
.mFillOpacitySource
||
969 mStrokeOpacitySource
!= aOther
.mStrokeOpacitySource
||
970 mStrokeDasharrayFromObject
!= aOther
.mStrokeDasharrayFromObject
||
971 mStrokeDashoffsetFromObject
!= aOther
.mStrokeDashoffsetFromObject
||
972 mStrokeWidthFromObject
!= aOther
.mStrokeWidthFromObject
) {
973 NS_UpdateHint(hint
, nsChangeHint_RepaintFrame
);
977 // length of stroke dasharrays are the same (tested above) - check entries
978 for (uint32_t i
=0; i
<mStrokeDasharrayLength
; i
++)
979 if (mStrokeDasharray
[i
] != aOther
.mStrokeDasharray
[i
]) {
980 NS_UpdateHint(hint
, nsChangeHint_RepaintFrame
);
987 // --------------------
990 nsStyleFilter::nsStyleFilter()
991 : mType(NS_STYLE_FILTER_NONE
)
992 , mDropShadow(nullptr)
994 MOZ_COUNT_CTOR(nsStyleFilter
);
997 nsStyleFilter::nsStyleFilter(const nsStyleFilter
& aSource
)
998 : mType(NS_STYLE_FILTER_NONE
)
999 , mDropShadow(nullptr)
1001 MOZ_COUNT_CTOR(nsStyleFilter
);
1002 if (aSource
.mType
== NS_STYLE_FILTER_URL
) {
1003 SetURL(aSource
.mURL
);
1004 } else if (aSource
.mType
== NS_STYLE_FILTER_DROP_SHADOW
) {
1005 SetDropShadow(aSource
.mDropShadow
);
1006 } else if (aSource
.mType
!= NS_STYLE_FILTER_NONE
) {
1007 SetFilterParameter(aSource
.mFilterParameter
, aSource
.mType
);
1011 nsStyleFilter::~nsStyleFilter()
1014 MOZ_COUNT_DTOR(nsStyleFilter
);
1018 nsStyleFilter::operator=(const nsStyleFilter
& aOther
)
1020 if (this == &aOther
)
1023 if (aOther
.mType
== NS_STYLE_FILTER_URL
) {
1024 SetURL(aOther
.mURL
);
1025 } else if (aOther
.mType
== NS_STYLE_FILTER_DROP_SHADOW
) {
1026 SetDropShadow(aOther
.mDropShadow
);
1027 } else if (aOther
.mType
!= NS_STYLE_FILTER_NONE
) {
1028 SetFilterParameter(aOther
.mFilterParameter
, aOther
.mType
);
1035 nsStyleFilter::operator==(const nsStyleFilter
& aOther
) const
1037 if (mType
!= aOther
.mType
) {
1041 if (mType
== NS_STYLE_FILTER_URL
) {
1042 return EqualURIs(mURL
, aOther
.mURL
);
1043 } else if (mType
== NS_STYLE_FILTER_DROP_SHADOW
) {
1044 return *mDropShadow
== *aOther
.mDropShadow
;
1045 } else if (mType
!= NS_STYLE_FILTER_NONE
) {
1046 return mFilterParameter
== aOther
.mFilterParameter
;
1053 nsStyleFilter::ReleaseRef()
1055 if (mType
== NS_STYLE_FILTER_DROP_SHADOW
) {
1056 NS_ASSERTION(mDropShadow
, "expected pointer");
1057 mDropShadow
->Release();
1058 } else if (mType
== NS_STYLE_FILTER_URL
) {
1059 NS_ASSERTION(mURL
, "expected pointer");
1065 nsStyleFilter::SetFilterParameter(const nsStyleCoord
& aFilterParameter
,
1069 mFilterParameter
= aFilterParameter
;
1074 nsStyleFilter::SetURL(nsIURI
* aURL
)
1076 NS_ASSERTION(aURL
, "expected pointer");
1080 mType
= NS_STYLE_FILTER_URL
;
1084 nsStyleFilter::SetDropShadow(nsCSSShadowArray
* aDropShadow
)
1086 NS_ASSERTION(aDropShadow
, "expected pointer");
1088 mDropShadow
= aDropShadow
;
1089 mDropShadow
->AddRef();
1090 mType
= NS_STYLE_FILTER_DROP_SHADOW
;
1093 // --------------------
1096 nsStyleSVGReset::nsStyleSVGReset()
1098 MOZ_COUNT_CTOR(nsStyleSVGReset
);
1099 mStopColor
= NS_RGB(0,0,0);
1100 mFloodColor
= NS_RGB(0,0,0);
1101 mLightingColor
= NS_RGB(255,255,255);
1102 mClipPath
= nullptr;
1104 mStopOpacity
= 1.0f
;
1105 mFloodOpacity
= 1.0f
;
1106 mDominantBaseline
= NS_STYLE_DOMINANT_BASELINE_AUTO
;
1107 mVectorEffect
= NS_STYLE_VECTOR_EFFECT_NONE
;
1108 mMaskType
= NS_STYLE_MASK_TYPE_LUMINANCE
;
1111 nsStyleSVGReset::~nsStyleSVGReset()
1113 MOZ_COUNT_DTOR(nsStyleSVGReset
);
1116 nsStyleSVGReset::nsStyleSVGReset(const nsStyleSVGReset
& aSource
)
1118 MOZ_COUNT_CTOR(nsStyleSVGReset
);
1119 mStopColor
= aSource
.mStopColor
;
1120 mFloodColor
= aSource
.mFloodColor
;
1121 mLightingColor
= aSource
.mLightingColor
;
1122 mClipPath
= aSource
.mClipPath
;
1123 mFilters
= aSource
.mFilters
;
1124 mMask
= aSource
.mMask
;
1125 mStopOpacity
= aSource
.mStopOpacity
;
1126 mFloodOpacity
= aSource
.mFloodOpacity
;
1127 mDominantBaseline
= aSource
.mDominantBaseline
;
1128 mVectorEffect
= aSource
.mVectorEffect
;
1129 mMaskType
= aSource
.mMaskType
;
1132 nsChangeHint
nsStyleSVGReset::CalcDifference(const nsStyleSVGReset
& aOther
) const
1134 nsChangeHint hint
= nsChangeHint(0);
1136 if (!EqualURIs(mClipPath
, aOther
.mClipPath
) ||
1137 !EqualURIs(mMask
, aOther
.mMask
) ||
1138 mFilters
!= aOther
.mFilters
) {
1139 NS_UpdateHint(hint
, nsChangeHint_UpdateEffects
);
1140 NS_UpdateHint(hint
, nsChangeHint_RepaintFrame
);
1141 // We only actually need to update the overflow area for filter
1142 // changes. However, mask and clip-path changes require that we
1143 // update the PreEffectsBBoxProperty, which is done during overflow
1145 NS_UpdateHint(hint
, nsChangeHint_UpdateOverflow
);
1148 if (mDominantBaseline
!= aOther
.mDominantBaseline
) {
1149 // XXXjwatt: why NS_STYLE_HINT_REFLOW? Isn't that excessive?
1150 NS_UpdateHint(hint
, NS_STYLE_HINT_REFLOW
);
1151 } else if (mVectorEffect
!= aOther
.mVectorEffect
) {
1152 // Stroke currently affects nsSVGPathGeometryFrame::mRect, and
1153 // vector-effect affect stroke. As a result we need to reflow if
1154 // vector-effect changes in order to have nsSVGPathGeometryFrame::
1155 // ReflowSVG called to update its mRect. No intrinsic sizes need
1156 // to change so nsChangeHint_NeedReflow is sufficient.
1157 NS_UpdateHint(hint
, nsChangeHint_NeedReflow
);
1158 NS_UpdateHint(hint
, nsChangeHint_NeedDirtyReflow
); // XXX remove me: bug 876085
1159 NS_UpdateHint(hint
, nsChangeHint_RepaintFrame
);
1160 } else if (mStopColor
!= aOther
.mStopColor
||
1161 mFloodColor
!= aOther
.mFloodColor
||
1162 mLightingColor
!= aOther
.mLightingColor
||
1163 mStopOpacity
!= aOther
.mStopOpacity
||
1164 mFloodOpacity
!= aOther
.mFloodOpacity
||
1165 mMaskType
!= aOther
.mMaskType
) {
1166 NS_UpdateHint(hint
, nsChangeHint_RepaintFrame
);
1172 // nsStyleSVGPaint implementation
1173 nsStyleSVGPaint::~nsStyleSVGPaint()
1175 if (mType
== eStyleSVGPaintType_Server
) {
1176 NS_IF_RELEASE(mPaint
.mPaintServer
);
1181 nsStyleSVGPaint::SetType(nsStyleSVGPaintType aType
)
1183 if (mType
== eStyleSVGPaintType_Server
) {
1184 this->~nsStyleSVGPaint();
1185 new (this) nsStyleSVGPaint();
1190 nsStyleSVGPaint
& nsStyleSVGPaint::operator=(const nsStyleSVGPaint
& aOther
)
1192 if (this == &aOther
)
1195 SetType(aOther
.mType
);
1197 mFallbackColor
= aOther
.mFallbackColor
;
1198 if (mType
== eStyleSVGPaintType_Server
) {
1199 mPaint
.mPaintServer
= aOther
.mPaint
.mPaintServer
;
1200 NS_IF_ADDREF(mPaint
.mPaintServer
);
1202 mPaint
.mColor
= aOther
.mPaint
.mColor
;
1207 bool nsStyleSVGPaint::operator==(const nsStyleSVGPaint
& aOther
) const
1209 if (mType
!= aOther
.mType
)
1211 if (mType
== eStyleSVGPaintType_Server
)
1212 return EqualURIs(mPaint
.mPaintServer
, aOther
.mPaint
.mPaintServer
) &&
1213 mFallbackColor
== aOther
.mFallbackColor
;
1214 if (mType
== eStyleSVGPaintType_Color
)
1215 return mPaint
.mColor
== aOther
.mPaint
.mColor
;
1220 // --------------------
1223 nsStylePosition::nsStylePosition(void)
1225 MOZ_COUNT_CTOR(nsStylePosition
);
1226 // positioning values not inherited
1227 nsStyleCoord
autoCoord(eStyleUnit_Auto
);
1228 mOffset
.SetLeft(autoCoord
);
1229 mOffset
.SetTop(autoCoord
);
1230 mOffset
.SetRight(autoCoord
);
1231 mOffset
.SetBottom(autoCoord
);
1232 mWidth
.SetAutoValue();
1233 mMinWidth
.SetAutoValue();
1234 mMaxWidth
.SetNoneValue();
1235 mHeight
.SetAutoValue();
1236 mMinHeight
.SetAutoValue();
1237 mMaxHeight
.SetNoneValue();
1238 mFlexBasis
.SetAutoValue();
1240 // The initial value of grid-auto-columns and grid-auto-rows is 'auto',
1241 // which computes to 'minmax(min-content, max-content)'.
1242 mGridAutoColumnsMin
.SetIntValue(NS_STYLE_GRID_TRACK_BREADTH_MIN_CONTENT
,
1243 eStyleUnit_Enumerated
);
1244 mGridAutoColumnsMax
.SetIntValue(NS_STYLE_GRID_TRACK_BREADTH_MAX_CONTENT
,
1245 eStyleUnit_Enumerated
);
1246 mGridAutoRowsMin
.SetIntValue(NS_STYLE_GRID_TRACK_BREADTH_MIN_CONTENT
,
1247 eStyleUnit_Enumerated
);
1248 mGridAutoRowsMax
.SetIntValue(NS_STYLE_GRID_TRACK_BREADTH_MAX_CONTENT
,
1249 eStyleUnit_Enumerated
);
1251 mGridAutoFlow
= NS_STYLE_GRID_AUTO_FLOW_ROW
;
1252 mBoxSizing
= NS_STYLE_BOX_SIZING_CONTENT
;
1253 mAlignContent
= NS_STYLE_ALIGN_CONTENT_STRETCH
;
1254 mAlignItems
= NS_STYLE_ALIGN_ITEMS_INITIAL_VALUE
;
1255 mAlignSelf
= NS_STYLE_ALIGN_SELF_AUTO
;
1256 mFlexDirection
= NS_STYLE_FLEX_DIRECTION_ROW
;
1257 mFlexWrap
= NS_STYLE_FLEX_WRAP_NOWRAP
;
1258 mJustifyContent
= NS_STYLE_JUSTIFY_CONTENT_FLEX_START
;
1259 mOrder
= NS_STYLE_ORDER_INITIAL
;
1262 mZIndex
.SetAutoValue();
1263 // Other members get their default constructors
1264 // which initialize them to representations of their respective initial value.
1265 // mGridTemplateAreas: nullptr for 'none'
1266 // mGridTemplate{Rows,Columns}: false and empty arrays for 'none'
1267 // mGrid{Column,Row}{Start,End}: false/0/empty values for 'auto'
1270 nsStylePosition::~nsStylePosition(void)
1272 MOZ_COUNT_DTOR(nsStylePosition
);
1275 nsStylePosition::nsStylePosition(const nsStylePosition
& aSource
)
1276 : mOffset(aSource
.mOffset
)
1277 , mWidth(aSource
.mWidth
)
1278 , mMinWidth(aSource
.mMinWidth
)
1279 , mMaxWidth(aSource
.mMaxWidth
)
1280 , mHeight(aSource
.mHeight
)
1281 , mMinHeight(aSource
.mMinHeight
)
1282 , mMaxHeight(aSource
.mMaxHeight
)
1283 , mFlexBasis(aSource
.mFlexBasis
)
1284 , mGridAutoColumnsMin(aSource
.mGridAutoColumnsMin
)
1285 , mGridAutoColumnsMax(aSource
.mGridAutoColumnsMax
)
1286 , mGridAutoRowsMin(aSource
.mGridAutoRowsMin
)
1287 , mGridAutoRowsMax(aSource
.mGridAutoRowsMax
)
1288 , mGridAutoFlow(aSource
.mGridAutoFlow
)
1289 , mBoxSizing(aSource
.mBoxSizing
)
1290 , mAlignContent(aSource
.mAlignContent
)
1291 , mAlignItems(aSource
.mAlignItems
)
1292 , mAlignSelf(aSource
.mAlignSelf
)
1293 , mFlexDirection(aSource
.mFlexDirection
)
1294 , mFlexWrap(aSource
.mFlexWrap
)
1295 , mJustifyContent(aSource
.mJustifyContent
)
1296 , mOrder(aSource
.mOrder
)
1297 , mFlexGrow(aSource
.mFlexGrow
)
1298 , mFlexShrink(aSource
.mFlexShrink
)
1299 , mZIndex(aSource
.mZIndex
)
1300 , mGridTemplateColumns(aSource
.mGridTemplateColumns
)
1301 , mGridTemplateRows(aSource
.mGridTemplateRows
)
1302 , mGridTemplateAreas(aSource
.mGridTemplateAreas
)
1303 , mGridColumnStart(aSource
.mGridColumnStart
)
1304 , mGridColumnEnd(aSource
.mGridColumnEnd
)
1305 , mGridRowStart(aSource
.mGridRowStart
)
1306 , mGridRowEnd(aSource
.mGridRowEnd
)
1308 MOZ_COUNT_CTOR(nsStylePosition
);
1312 IsAutonessEqual(const nsStyleSides
& aSides1
, const nsStyleSides
& aSides2
)
1314 NS_FOR_CSS_SIDES(side
) {
1315 if ((aSides1
.GetUnit(side
) == eStyleUnit_Auto
) !=
1316 (aSides2
.GetUnit(side
) == eStyleUnit_Auto
)) {
1323 nsChangeHint
nsStylePosition::CalcDifference(const nsStylePosition
& aOther
) const
1326 (mZIndex
== aOther
.mZIndex
) ? NS_STYLE_HINT_NONE
: nsChangeHint_RepaintFrame
;
1328 if (mOrder
!= aOther
.mOrder
) {
1329 // "order" impacts both layout order and stacking order, so we need both a
1330 // reflow and a repaint when it changes. (Technically, we only need a
1331 // reflow if we're in a multi-line flexbox (which we can't be sure about,
1332 // since that's determined by styling on our parent) -- there, "order" can
1333 // affect which flex line we end up on, & hence can affect our sizing by
1334 // changing the group of flex items we're competing with for space.)
1335 return NS_CombineHint(hint
, NS_CombineHint(nsChangeHint_RepaintFrame
,
1336 nsChangeHint_AllReflowHints
));
1339 if (mBoxSizing
!= aOther
.mBoxSizing
) {
1340 // Can affect both widths and heights; just a bad scene.
1341 return NS_CombineHint(hint
, nsChangeHint_AllReflowHints
);
1344 // Properties that apply to flex items:
1345 // XXXdholbert These should probably be more targeted (bug 819536)
1346 if (mAlignSelf
!= aOther
.mAlignSelf
||
1347 mFlexBasis
!= aOther
.mFlexBasis
||
1348 mFlexGrow
!= aOther
.mFlexGrow
||
1349 mFlexShrink
!= aOther
.mFlexShrink
) {
1350 return NS_CombineHint(hint
, nsChangeHint_AllReflowHints
);
1353 // Properties that apply to flex containers:
1354 // - flex-direction can swap a flex container between vertical & horizontal.
1355 // - align-items can change the sizing of a flex container & the positioning
1357 // - flex-wrap changes whether a flex container's children are wrapped, which
1358 // impacts their sizing/positioning and hence impacts the container's size.
1359 if (mAlignItems
!= aOther
.mAlignItems
||
1360 mFlexDirection
!= aOther
.mFlexDirection
||
1361 mFlexWrap
!= aOther
.mFlexWrap
) {
1362 return NS_CombineHint(hint
, nsChangeHint_AllReflowHints
);
1365 // Properties that apply to grid containers:
1366 // FIXME: only for grid containers
1367 // (ie. 'display: grid' or 'display: inline-grid')
1368 if (mGridTemplateColumns
!= aOther
.mGridTemplateColumns
||
1369 mGridTemplateRows
!= aOther
.mGridTemplateRows
||
1370 mGridTemplateAreas
!= aOther
.mGridTemplateAreas
||
1371 mGridAutoColumnsMin
!= aOther
.mGridAutoColumnsMin
||
1372 mGridAutoColumnsMax
!= aOther
.mGridAutoColumnsMax
||
1373 mGridAutoRowsMin
!= aOther
.mGridAutoRowsMin
||
1374 mGridAutoRowsMax
!= aOther
.mGridAutoRowsMax
||
1375 mGridAutoFlow
!= aOther
.mGridAutoFlow
) {
1376 return NS_CombineHint(hint
, nsChangeHint_AllReflowHints
);
1379 // Properties that apply to grid items:
1380 // FIXME: only for grid items
1381 // (ie. parent frame is 'display: grid' or 'display: inline-grid')
1382 if (mGridColumnStart
!= aOther
.mGridColumnStart
||
1383 mGridColumnEnd
!= aOther
.mGridColumnEnd
||
1384 mGridRowStart
!= aOther
.mGridRowStart
||
1385 mGridRowEnd
!= aOther
.mGridRowEnd
) {
1386 return NS_CombineHint(hint
, nsChangeHint_AllReflowHints
);
1389 // Changing justify-content on a flexbox might affect the positioning of its
1390 // children, but it won't affect any sizing.
1391 if (mJustifyContent
!= aOther
.mJustifyContent
) {
1392 NS_UpdateHint(hint
, nsChangeHint_NeedReflow
);
1395 // Properties that apply only to multi-line flex containers:
1396 // 'align-content' can change the positioning & sizing of a multi-line flex
1397 // container's children when there's extra space in the cross axis, but it
1398 // shouldn't affect the container's own sizing.
1400 // NOTE: If we get here, we know that mFlexWrap == aOther.mFlexWrap
1401 // (otherwise, we would've returned earlier). So it doesn't matter which one
1402 // of those we check to see if we're multi-line.
1403 if (mFlexWrap
!= NS_STYLE_FLEX_WRAP_NOWRAP
&&
1404 mAlignContent
!= aOther
.mAlignContent
) {
1405 NS_UpdateHint(hint
, nsChangeHint_NeedReflow
);
1408 if (mHeight
!= aOther
.mHeight
||
1409 mMinHeight
!= aOther
.mMinHeight
||
1410 mMaxHeight
!= aOther
.mMaxHeight
) {
1411 // Height changes can affect descendant intrinsic sizes due to replaced
1412 // elements with percentage heights in descendants which also have
1413 // percentage heights. And due to our not-so-great computation of mVResize
1414 // in nsHTMLReflowState, they do need to force reflow of the whole subtree.
1415 // XXXbz due to XUL caching heights as well, height changes also need to
1416 // clear ancestor intrinsics!
1417 return NS_CombineHint(hint
, nsChangeHint_AllReflowHints
);
1420 if (mWidth
!= aOther
.mWidth
||
1421 mMinWidth
!= aOther
.mMinWidth
||
1422 mMaxWidth
!= aOther
.mMaxWidth
) {
1423 // None of our width differences can affect descendant intrinsic
1424 // sizes and none of them need to force children to reflow.
1426 NS_CombineHint(hint
,
1427 NS_SubtractHint(nsChangeHint_AllReflowHints
,
1428 NS_CombineHint(nsChangeHint_ClearDescendantIntrinsics
,
1429 nsChangeHint_NeedDirtyReflow
)));
1432 // If width and height have not changed, but any of the offsets have changed,
1433 // then return the respective hints so that we would hopefully be able to
1435 // Note that it is possible that we'll need to reflow when processing
1436 // restyles, but we don't have enough information to make a good decision
1438 // Don't try to handle changes between "auto" and non-auto efficiently;
1439 // that's tricky to do and will hardly ever be able to avoid a reflow.
1440 if (mOffset
!= aOther
.mOffset
) {
1441 if (IsAutonessEqual(mOffset
, aOther
.mOffset
)) {
1442 NS_UpdateHint(hint
, nsChangeHint(nsChangeHint_RecomputePosition
|
1443 nsChangeHint_UpdateOverflow
));
1445 return NS_CombineHint(hint
, nsChangeHint_AllReflowHints
);
1452 nsStylePosition::WidthCoordDependsOnContainer(const nsStyleCoord
&aCoord
)
1454 return aCoord
.HasPercent() ||
1455 (aCoord
.GetUnit() == eStyleUnit_Enumerated
&&
1456 (aCoord
.GetIntValue() == NS_STYLE_WIDTH_FIT_CONTENT
||
1457 aCoord
.GetIntValue() == NS_STYLE_WIDTH_AVAILABLE
));
1460 // --------------------
1464 nsStyleTable::nsStyleTable()
1466 MOZ_COUNT_CTOR(nsStyleTable
);
1467 // values not inherited
1468 mLayoutStrategy
= NS_STYLE_TABLE_LAYOUT_AUTO
;
1472 nsStyleTable::~nsStyleTable(void)
1474 MOZ_COUNT_DTOR(nsStyleTable
);
1477 nsStyleTable::nsStyleTable(const nsStyleTable
& aSource
)
1478 : mLayoutStrategy(aSource
.mLayoutStrategy
)
1479 , mSpan(aSource
.mSpan
)
1481 MOZ_COUNT_CTOR(nsStyleTable
);
1484 nsChangeHint
nsStyleTable::CalcDifference(const nsStyleTable
& aOther
) const
1486 if (mSpan
!= aOther
.mSpan
||
1487 mLayoutStrategy
!= aOther
.mLayoutStrategy
)
1488 return NS_STYLE_HINT_FRAMECHANGE
;
1489 return NS_STYLE_HINT_NONE
;
1492 // -----------------------
1493 // nsStyleTableBorder
1495 nsStyleTableBorder::nsStyleTableBorder(nsPresContext
* aPresContext
)
1497 MOZ_COUNT_CTOR(nsStyleTableBorder
);
1498 mBorderCollapse
= NS_STYLE_BORDER_SEPARATE
;
1500 nsCompatibility compatMode
= eCompatibility_FullStandards
;
1502 compatMode
= aPresContext
->CompatibilityMode();
1503 mEmptyCells
= (compatMode
== eCompatibility_NavQuirks
)
1504 ? NS_STYLE_TABLE_EMPTY_CELLS_SHOW_BACKGROUND
1505 : NS_STYLE_TABLE_EMPTY_CELLS_SHOW
;
1506 mCaptionSide
= NS_STYLE_CAPTION_SIDE_TOP
;
1507 mBorderSpacingX
= 0;
1508 mBorderSpacingY
= 0;
1511 nsStyleTableBorder::~nsStyleTableBorder(void)
1513 MOZ_COUNT_DTOR(nsStyleTableBorder
);
1516 nsStyleTableBorder::nsStyleTableBorder(const nsStyleTableBorder
& aSource
)
1517 : mBorderSpacingX(aSource
.mBorderSpacingX
)
1518 , mBorderSpacingY(aSource
.mBorderSpacingY
)
1519 , mBorderCollapse(aSource
.mBorderCollapse
)
1520 , mCaptionSide(aSource
.mCaptionSide
)
1521 , mEmptyCells(aSource
.mEmptyCells
)
1523 MOZ_COUNT_CTOR(nsStyleTableBorder
);
1526 nsChangeHint
nsStyleTableBorder::CalcDifference(const nsStyleTableBorder
& aOther
) const
1528 // Border-collapse changes need a reframe, because we use a different frame
1529 // class for table cells in the collapsed border model. This is used to
1530 // conserve memory when using the separated border model (collapsed borders
1531 // require extra state to be stored).
1532 if (mBorderCollapse
!= aOther
.mBorderCollapse
) {
1533 return NS_STYLE_HINT_FRAMECHANGE
;
1536 if ((mCaptionSide
== aOther
.mCaptionSide
) &&
1537 (mBorderSpacingX
== aOther
.mBorderSpacingX
) &&
1538 (mBorderSpacingY
== aOther
.mBorderSpacingY
)) {
1539 if (mEmptyCells
== aOther
.mEmptyCells
)
1540 return NS_STYLE_HINT_NONE
;
1541 return NS_STYLE_HINT_VISUAL
;
1544 return NS_STYLE_HINT_REFLOW
;
1547 // --------------------
1551 nsStyleColor::nsStyleColor(nsPresContext
* aPresContext
)
1553 MOZ_COUNT_CTOR(nsStyleColor
);
1554 mColor
= aPresContext
->DefaultColor();
1557 nsStyleColor::nsStyleColor(const nsStyleColor
& aSource
)
1559 MOZ_COUNT_CTOR(nsStyleColor
);
1560 mColor
= aSource
.mColor
;
1563 nsChangeHint
nsStyleColor::CalcDifference(const nsStyleColor
& aOther
) const
1565 if (mColor
== aOther
.mColor
)
1566 return NS_STYLE_HINT_NONE
;
1567 return NS_STYLE_HINT_VISUAL
;
1570 // --------------------
1574 nsStyleGradient::operator==(const nsStyleGradient
& aOther
) const
1576 NS_ABORT_IF_FALSE(mSize
== NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER
||
1577 mShape
!= NS_STYLE_GRADIENT_SHAPE_LINEAR
,
1578 "incorrect combination of shape and size");
1579 NS_ABORT_IF_FALSE(aOther
.mSize
== NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER
||
1580 aOther
.mShape
!= NS_STYLE_GRADIENT_SHAPE_LINEAR
,
1581 "incorrect combination of shape and size");
1583 if (mShape
!= aOther
.mShape
||
1584 mSize
!= aOther
.mSize
||
1585 mRepeating
!= aOther
.mRepeating
||
1586 mLegacySyntax
!= aOther
.mLegacySyntax
||
1587 mBgPosX
!= aOther
.mBgPosX
||
1588 mBgPosY
!= aOther
.mBgPosY
||
1589 mAngle
!= aOther
.mAngle
||
1590 mRadiusX
!= aOther
.mRadiusX
||
1591 mRadiusY
!= aOther
.mRadiusY
)
1594 if (mStops
.Length() != aOther
.mStops
.Length())
1597 for (uint32_t i
= 0; i
< mStops
.Length(); i
++) {
1598 if (mStops
[i
].mLocation
!= aOther
.mStops
[i
].mLocation
||
1599 mStops
[i
].mColor
!= aOther
.mStops
[i
].mColor
)
1606 nsStyleGradient::nsStyleGradient(void)
1607 : mShape(NS_STYLE_GRADIENT_SHAPE_LINEAR
)
1608 , mSize(NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER
)
1610 , mLegacySyntax(false)
1615 nsStyleGradient::IsOpaque()
1617 for (uint32_t i
= 0; i
< mStops
.Length(); i
++) {
1618 if (NS_GET_A(mStops
[i
].mColor
) < 255)
1625 nsStyleGradient::HasCalc()
1627 for (uint32_t i
= 0; i
< mStops
.Length(); i
++) {
1628 if (mStops
[i
].mLocation
.IsCalcUnit())
1631 return mBgPosX
.IsCalcUnit() || mBgPosY
.IsCalcUnit() || mAngle
.IsCalcUnit() ||
1632 mRadiusX
.IsCalcUnit() || mRadiusY
.IsCalcUnit();
1635 // --------------------
1639 nsStyleImage::nsStyleImage()
1640 : mType(eStyleImageType_Null
)
1641 , mCropRect(nullptr)
1643 , mImageTracked(false)
1646 MOZ_COUNT_CTOR(nsStyleImage
);
1649 nsStyleImage::~nsStyleImage()
1651 MOZ_COUNT_DTOR(nsStyleImage
);
1652 if (mType
!= eStyleImageType_Null
)
1656 nsStyleImage::nsStyleImage(const nsStyleImage
& aOther
)
1657 : mType(eStyleImageType_Null
)
1658 , mCropRect(nullptr)
1660 , mImageTracked(false)
1663 // We need our own copy constructor because we don't want
1664 // to copy the reference count
1665 MOZ_COUNT_CTOR(nsStyleImage
);
1670 nsStyleImage::operator=(const nsStyleImage
& aOther
)
1672 if (this != &aOther
)
1679 nsStyleImage::DoCopy(const nsStyleImage
& aOther
)
1683 if (aOther
.mType
== eStyleImageType_Image
)
1684 SetImageData(aOther
.mImage
);
1685 else if (aOther
.mType
== eStyleImageType_Gradient
)
1686 SetGradientData(aOther
.mGradient
);
1687 else if (aOther
.mType
== eStyleImageType_Element
)
1688 SetElementId(aOther
.mElementId
);
1690 SetCropRect(aOther
.mCropRect
);
1694 nsStyleImage::SetNull()
1696 NS_ABORT_IF_FALSE(!mImageTracked
,
1697 "Calling SetNull() with image tracked!");
1699 if (mType
== eStyleImageType_Gradient
)
1700 mGradient
->Release();
1701 else if (mType
== eStyleImageType_Image
)
1703 else if (mType
== eStyleImageType_Element
)
1704 NS_Free(mElementId
);
1706 mType
= eStyleImageType_Null
;
1707 mCropRect
= nullptr;
1711 nsStyleImage::SetImageData(imgRequestProxy
* aImage
)
1713 NS_ABORT_IF_FALSE(!mImageTracked
,
1714 "Setting a new image without untracking the old one!");
1716 NS_IF_ADDREF(aImage
);
1718 if (mType
!= eStyleImageType_Null
)
1723 mType
= eStyleImageType_Image
;
1729 nsStyleImage::TrackImage(nsPresContext
* aContext
)
1732 NS_ABORT_IF_FALSE(!mImageTracked
, "Already tracking image!");
1733 NS_ABORT_IF_FALSE(mType
== eStyleImageType_Image
,
1734 "Can't track image when there isn't one!");
1736 // Register the image with the document
1737 nsIDocument
* doc
= aContext
->Document();
1739 doc
->AddImage(mImage
);
1743 mImageTracked
= true;
1748 nsStyleImage::UntrackImage(nsPresContext
* aContext
)
1751 NS_ABORT_IF_FALSE(mImageTracked
, "Image not tracked!");
1752 NS_ABORT_IF_FALSE(mType
== eStyleImageType_Image
,
1753 "Can't untrack image when there isn't one!");
1755 // Unregister the image with the document
1756 nsIDocument
* doc
= aContext
->Document();
1758 doc
->RemoveImage(mImage
, nsIDocument::REQUEST_DISCARD
);
1762 mImageTracked
= false;
1767 nsStyleImage::SetGradientData(nsStyleGradient
* aGradient
)
1770 aGradient
->AddRef();
1772 if (mType
!= eStyleImageType_Null
)
1776 mGradient
= aGradient
;
1777 mType
= eStyleImageType_Gradient
;
1782 nsStyleImage::SetElementId(const char16_t
* aElementId
)
1784 if (mType
!= eStyleImageType_Null
)
1788 mElementId
= NS_strdup(aElementId
);
1789 mType
= eStyleImageType_Element
;
1794 nsStyleImage::SetCropRect(nsStyleSides
* aCropRect
)
1797 mCropRect
= new nsStyleSides(*aCropRect
);
1798 // There is really not much we can do if 'new' fails
1800 mCropRect
= nullptr;
1805 ConvertToPixelCoord(const nsStyleCoord
& aCoord
, int32_t aPercentScale
)
1808 switch (aCoord
.GetUnit()) {
1809 case eStyleUnit_Percent
:
1810 pixelValue
= aCoord
.GetPercentValue() * aPercentScale
;
1812 case eStyleUnit_Factor
:
1813 pixelValue
= aCoord
.GetFactorValue();
1816 NS_NOTREACHED("unexpected unit for image crop rect");
1819 NS_ABORT_IF_FALSE(pixelValue
>= 0, "we ensured non-negative while parsing");
1820 pixelValue
= std::min(pixelValue
, double(INT32_MAX
)); // avoid overflow
1821 return NS_lround(pixelValue
);
1825 nsStyleImage::ComputeActualCropRect(nsIntRect
& aActualCropRect
,
1826 bool* aIsEntireImage
) const
1828 if (mType
!= eStyleImageType_Image
)
1831 nsCOMPtr
<imgIContainer
> imageContainer
;
1832 mImage
->GetImage(getter_AddRefs(imageContainer
));
1833 if (!imageContainer
)
1836 nsIntSize imageSize
;
1837 imageContainer
->GetWidth(&imageSize
.width
);
1838 imageContainer
->GetHeight(&imageSize
.height
);
1839 if (imageSize
.width
<= 0 || imageSize
.height
<= 0)
1842 int32_t left
= ConvertToPixelCoord(mCropRect
->GetLeft(), imageSize
.width
);
1843 int32_t top
= ConvertToPixelCoord(mCropRect
->GetTop(), imageSize
.height
);
1844 int32_t right
= ConvertToPixelCoord(mCropRect
->GetRight(), imageSize
.width
);
1845 int32_t bottom
= ConvertToPixelCoord(mCropRect
->GetBottom(), imageSize
.height
);
1847 // IntersectRect() returns an empty rect if we get negative width or height
1848 nsIntRect
cropRect(left
, top
, right
- left
, bottom
- top
);
1849 nsIntRect
imageRect(nsIntPoint(0, 0), imageSize
);
1850 aActualCropRect
.IntersectRect(imageRect
, cropRect
);
1853 *aIsEntireImage
= aActualCropRect
.IsEqualInterior(imageRect
);
1858 nsStyleImage::StartDecoding() const
1860 if ((mType
== eStyleImageType_Image
) && mImage
)
1861 return mImage
->StartDecoding();
1866 nsStyleImage::IsOpaque() const
1871 if (mType
== eStyleImageType_Gradient
)
1872 return mGradient
->IsOpaque();
1874 if (mType
== eStyleImageType_Element
)
1877 NS_ABORT_IF_FALSE(mType
== eStyleImageType_Image
, "unexpected image type");
1879 nsCOMPtr
<imgIContainer
> imageContainer
;
1880 mImage
->GetImage(getter_AddRefs(imageContainer
));
1881 NS_ABORT_IF_FALSE(imageContainer
, "IsComplete() said image container is ready");
1883 // Check if the crop region of the current image frame is opaque.
1884 if (imageContainer
->FrameIsOpaque(imgIContainer::FRAME_CURRENT
)) {
1888 // Must make sure if mCropRect contains at least a pixel.
1889 // XXX Is this optimization worth it? Maybe I should just return false.
1890 nsIntRect actualCropRect
;
1891 bool rv
= ComputeActualCropRect(actualCropRect
);
1892 NS_ASSERTION(rv
, "ComputeActualCropRect() can not fail here");
1893 return rv
&& !actualCropRect
.IsEmpty();
1900 nsStyleImage::IsComplete() const
1903 case eStyleImageType_Null
:
1905 case eStyleImageType_Gradient
:
1906 case eStyleImageType_Element
:
1908 case eStyleImageType_Image
:
1910 uint32_t status
= imgIRequest::STATUS_ERROR
;
1911 return NS_SUCCEEDED(mImage
->GetImageStatus(&status
)) &&
1912 (status
& imgIRequest::STATUS_SIZE_AVAILABLE
) &&
1913 (status
& imgIRequest::STATUS_FRAME_COMPLETE
);
1916 NS_NOTREACHED("unexpected image type");
1922 nsStyleImage::IsLoaded() const
1925 case eStyleImageType_Null
:
1927 case eStyleImageType_Gradient
:
1928 case eStyleImageType_Element
:
1930 case eStyleImageType_Image
:
1932 uint32_t status
= imgIRequest::STATUS_ERROR
;
1933 return NS_SUCCEEDED(mImage
->GetImageStatus(&status
)) &&
1934 !(status
& imgIRequest::STATUS_ERROR
) &&
1935 (status
& imgIRequest::STATUS_LOAD_COMPLETE
);
1938 NS_NOTREACHED("unexpected image type");
1944 EqualRects(const nsStyleSides
* aRect1
, const nsStyleSides
* aRect2
)
1946 return aRect1
== aRect2
|| /* handles null== null, and optimize */
1947 (aRect1
&& aRect2
&& *aRect1
== *aRect2
);
1951 nsStyleImage::operator==(const nsStyleImage
& aOther
) const
1953 if (mType
!= aOther
.mType
)
1956 if (!EqualRects(mCropRect
, aOther
.mCropRect
))
1959 if (mType
== eStyleImageType_Image
)
1960 return EqualImages(mImage
, aOther
.mImage
);
1962 if (mType
== eStyleImageType_Gradient
)
1963 return *mGradient
== *aOther
.mGradient
;
1965 if (mType
== eStyleImageType_Element
)
1966 return NS_strcmp(mElementId
, aOther
.mElementId
) == 0;
1971 // --------------------
1972 // nsStyleBackground
1975 nsStyleBackground::nsStyleBackground()
1976 : mAttachmentCount(1)
1983 , mBlendModeCount(1)
1984 , mBackgroundColor(NS_RGBA(0, 0, 0, 0))
1986 MOZ_COUNT_CTOR(nsStyleBackground
);
1987 Layer
*onlyLayer
= mLayers
.AppendElement();
1988 NS_ASSERTION(onlyLayer
, "auto array must have room for 1 element");
1989 onlyLayer
->SetInitialValues();
1992 nsStyleBackground::nsStyleBackground(const nsStyleBackground
& aSource
)
1993 : mAttachmentCount(aSource
.mAttachmentCount
)
1994 , mClipCount(aSource
.mClipCount
)
1995 , mOriginCount(aSource
.mOriginCount
)
1996 , mRepeatCount(aSource
.mRepeatCount
)
1997 , mPositionCount(aSource
.mPositionCount
)
1998 , mImageCount(aSource
.mImageCount
)
1999 , mSizeCount(aSource
.mSizeCount
)
2000 , mBlendModeCount(aSource
.mBlendModeCount
)
2001 , mLayers(aSource
.mLayers
) // deep copy
2002 , mBackgroundColor(aSource
.mBackgroundColor
)
2004 MOZ_COUNT_CTOR(nsStyleBackground
);
2005 // If the deep copy of mLayers failed, truncate the counts.
2006 uint32_t count
= mLayers
.Length();
2007 if (count
!= aSource
.mLayers
.Length()) {
2008 NS_WARNING("truncating counts due to out-of-memory");
2009 mAttachmentCount
= std::max(mAttachmentCount
, count
);
2010 mClipCount
= std::max(mClipCount
, count
);
2011 mOriginCount
= std::max(mOriginCount
, count
);
2012 mRepeatCount
= std::max(mRepeatCount
, count
);
2013 mPositionCount
= std::max(mPositionCount
, count
);
2014 mImageCount
= std::max(mImageCount
, count
);
2015 mSizeCount
= std::max(mSizeCount
, count
);
2016 mBlendModeCount
= std::max(mSizeCount
, count
);
2020 nsStyleBackground::~nsStyleBackground()
2022 MOZ_COUNT_DTOR(nsStyleBackground
);
2026 nsStyleBackground::Destroy(nsPresContext
* aContext
)
2028 // Untrack all the images stored in our layers
2029 for (uint32_t i
= 0; i
< mImageCount
; ++i
)
2030 mLayers
[i
].UntrackImages(aContext
);
2032 this->~nsStyleBackground();
2033 aContext
->PresShell()->
2034 FreeByObjectID(nsPresArena::nsStyleBackground_id
, this);
2037 nsChangeHint
nsStyleBackground::CalcDifference(const nsStyleBackground
& aOther
) const
2039 const nsStyleBackground
* moreLayers
=
2040 mImageCount
> aOther
.mImageCount
? this : &aOther
;
2041 const nsStyleBackground
* lessLayers
=
2042 mImageCount
> aOther
.mImageCount
? &aOther
: this;
2044 bool hasVisualDifference
= false;
2046 NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i
, moreLayers
) {
2047 if (i
< lessLayers
->mImageCount
) {
2048 if (moreLayers
->mLayers
[i
] != lessLayers
->mLayers
[i
]) {
2049 if ((moreLayers
->mLayers
[i
].mImage
.GetType() == eStyleImageType_Element
) ||
2050 (lessLayers
->mLayers
[i
].mImage
.GetType() == eStyleImageType_Element
))
2051 return NS_CombineHint(nsChangeHint_UpdateEffects
, NS_STYLE_HINT_VISUAL
);
2052 hasVisualDifference
= true;
2055 if (moreLayers
->mLayers
[i
].mImage
.GetType() == eStyleImageType_Element
)
2056 return NS_CombineHint(nsChangeHint_UpdateEffects
, NS_STYLE_HINT_VISUAL
);
2057 hasVisualDifference
= true;
2061 if (hasVisualDifference
|| mBackgroundColor
!= aOther
.mBackgroundColor
)
2062 return NS_STYLE_HINT_VISUAL
;
2064 return NS_STYLE_HINT_NONE
;
2067 bool nsStyleBackground::HasFixedBackground() const
2069 NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i
, this) {
2070 const Layer
&layer
= mLayers
[i
];
2071 if (layer
.mAttachment
== NS_STYLE_BG_ATTACHMENT_FIXED
&&
2072 !layer
.mImage
.IsEmpty()) {
2079 bool nsStyleBackground::IsTransparent() const
2081 return BottomLayer().mImage
.IsEmpty() &&
2083 NS_GET_A(mBackgroundColor
) == 0;
2087 nsStyleBackground::Position::SetInitialValues()
2089 // Initial value is "0% 0%"
2090 mXPosition
.mPercent
= 0.0f
;
2091 mXPosition
.mLength
= 0;
2092 mXPosition
.mHasPercent
= true;
2093 mYPosition
.mPercent
= 0.0f
;
2094 mYPosition
.mLength
= 0;
2095 mYPosition
.mHasPercent
= true;
2099 nsStyleBackground::Size::DependsOnPositioningAreaSize(const nsStyleImage
& aImage
) const
2101 NS_ABORT_IF_FALSE(aImage
.GetType() != eStyleImageType_Null
,
2102 "caller should have handled this");
2104 // If either dimension contains a non-zero percentage, rendering for that
2105 // dimension straightforwardly depends on frame size.
2106 if ((mWidthType
== eLengthPercentage
&& mWidth
.mPercent
!= 0.0f
) ||
2107 (mHeightType
== eLengthPercentage
&& mHeight
.mPercent
!= 0.0f
)) {
2111 // So too for contain and cover.
2112 if (mWidthType
== eContain
|| mWidthType
== eCover
) {
2116 // If both dimensions are fixed lengths, there's no dependency.
2117 if (mWidthType
== eLengthPercentage
&& mHeightType
== eLengthPercentage
) {
2121 NS_ABORT_IF_FALSE((mWidthType
== eLengthPercentage
&& mHeightType
== eAuto
) ||
2122 (mWidthType
== eAuto
&& mHeightType
== eLengthPercentage
) ||
2123 (mWidthType
== eAuto
&& mHeightType
== eAuto
),
2126 nsStyleImageType type
= aImage
.GetType();
2128 // Gradient rendering depends on frame size when auto is involved because
2129 // gradients have no intrinsic ratio or dimensions, and therefore the relevant
2130 // dimension is "treat[ed] as 100%".
2131 if (type
== eStyleImageType_Gradient
) {
2135 // XXX Element rendering for auto or fixed length doesn't depend on frame size
2136 // according to the spec. However, we don't implement the spec yet, so
2137 // for now we bail and say element() plus auto affects ultimate size.
2138 if (type
== eStyleImageType_Element
) {
2142 if (type
== eStyleImageType_Image
) {
2143 nsCOMPtr
<imgIContainer
> imgContainer
;
2144 aImage
.GetImageData()->GetImage(getter_AddRefs(imgContainer
));
2146 nsIntSize imageSize
;
2148 bool hasWidth
, hasHeight
;
2149 nsLayoutUtils::ComputeSizeForDrawing(imgContainer
, imageSize
, imageRatio
,
2150 hasWidth
, hasHeight
);
2152 // If the image has a fixed width and height, rendering never depends on
2154 if (hasWidth
&& hasHeight
) {
2158 // If the image has an intrinsic ratio, rendering will depend on frame
2159 // size when background-size is all auto.
2160 if (imageRatio
!= nsSize(0, 0)) {
2161 return mWidthType
== mHeightType
;
2164 // Otherwise, rendering depends on frame size when the image dimensions
2165 // and background-size don't complement each other.
2166 return !(hasWidth
&& mHeightType
== eLengthPercentage
) &&
2167 !(hasHeight
&& mWidthType
== eLengthPercentage
);
2170 NS_NOTREACHED("missed an enum value");
2173 // Passed the gauntlet: no dependency.
2178 nsStyleBackground::Size::SetInitialValues()
2180 mWidthType
= mHeightType
= eAuto
;
2184 nsStyleBackground::Size::operator==(const Size
& aOther
) const
2186 NS_ABORT_IF_FALSE(mWidthType
< eDimensionType_COUNT
,
2187 "bad mWidthType for this");
2188 NS_ABORT_IF_FALSE(mHeightType
< eDimensionType_COUNT
,
2189 "bad mHeightType for this");
2190 NS_ABORT_IF_FALSE(aOther
.mWidthType
< eDimensionType_COUNT
,
2191 "bad mWidthType for aOther");
2192 NS_ABORT_IF_FALSE(aOther
.mHeightType
< eDimensionType_COUNT
,
2193 "bad mHeightType for aOther");
2195 return mWidthType
== aOther
.mWidthType
&&
2196 mHeightType
== aOther
.mHeightType
&&
2197 (mWidthType
!= eLengthPercentage
|| mWidth
== aOther
.mWidth
) &&
2198 (mHeightType
!= eLengthPercentage
|| mHeight
== aOther
.mHeight
);
2202 nsStyleBackground::Repeat::SetInitialValues()
2204 mXRepeat
= NS_STYLE_BG_REPEAT_REPEAT
;
2205 mYRepeat
= NS_STYLE_BG_REPEAT_REPEAT
;
2208 nsStyleBackground::Layer::Layer()
2212 nsStyleBackground::Layer::~Layer()
2217 nsStyleBackground::Layer::SetInitialValues()
2219 mAttachment
= NS_STYLE_BG_ATTACHMENT_SCROLL
;
2220 mClip
= NS_STYLE_BG_CLIP_BORDER
;
2221 mOrigin
= NS_STYLE_BG_ORIGIN_PADDING
;
2222 mRepeat
.SetInitialValues();
2223 mBlendMode
= NS_STYLE_BLEND_NORMAL
;
2224 mPosition
.SetInitialValues();
2225 mSize
.SetInitialValues();
2230 nsStyleBackground::Layer::RenderingMightDependOnPositioningAreaSizeChange() const
2232 // Do we even have an image?
2233 if (mImage
.IsEmpty()) {
2237 return mPosition
.DependsOnPositioningAreaSize() ||
2238 mSize
.DependsOnPositioningAreaSize(mImage
);
2242 nsStyleBackground::Layer::operator==(const Layer
& aOther
) const
2244 return mAttachment
== aOther
.mAttachment
&&
2245 mClip
== aOther
.mClip
&&
2246 mOrigin
== aOther
.mOrigin
&&
2247 mRepeat
== aOther
.mRepeat
&&
2248 mBlendMode
== aOther
.mBlendMode
&&
2249 mPosition
== aOther
.mPosition
&&
2250 mSize
== aOther
.mSize
&&
2251 mImage
== aOther
.mImage
;
2254 // --------------------
2257 void nsTimingFunction::AssignFromKeyword(int32_t aTimingFunctionType
)
2259 switch (aTimingFunctionType
) {
2260 case NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_START
:
2264 case NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END
:
2273 static_assert(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE
== 0 &&
2274 NS_STYLE_TRANSITION_TIMING_FUNCTION_LINEAR
== 1 &&
2275 NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE_IN
== 2 &&
2276 NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE_OUT
== 3 &&
2277 NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE_IN_OUT
== 4,
2278 "transition timing function constants not as expected");
2280 static const float timingFunctionValues
[5][4] = {
2281 { 0.25f
, 0.10f
, 0.25f
, 1.00f
}, // ease
2282 { 0.00f
, 0.00f
, 1.00f
, 1.00f
}, // linear
2283 { 0.42f
, 0.00f
, 1.00f
, 1.00f
}, // ease-in
2284 { 0.00f
, 0.00f
, 0.58f
, 1.00f
}, // ease-out
2285 { 0.42f
, 0.00f
, 0.58f
, 1.00f
} // ease-in-out
2288 NS_ABORT_IF_FALSE(0 <= aTimingFunctionType
&& aTimingFunctionType
< 5,
2289 "keyword out of range");
2290 mFunc
.mX1
= timingFunctionValues
[aTimingFunctionType
][0];
2291 mFunc
.mY1
= timingFunctionValues
[aTimingFunctionType
][1];
2292 mFunc
.mX2
= timingFunctionValues
[aTimingFunctionType
][2];
2293 mFunc
.mY2
= timingFunctionValues
[aTimingFunctionType
][3];
2296 mozilla::StyleTransition::StyleTransition(const StyleTransition
& aCopy
)
2297 : mTimingFunction(aCopy
.mTimingFunction
)
2298 , mDuration(aCopy
.mDuration
)
2299 , mDelay(aCopy
.mDelay
)
2300 , mProperty(aCopy
.mProperty
)
2301 , mUnknownProperty(aCopy
.mUnknownProperty
)
2306 mozilla::StyleTransition::SetInitialValues()
2308 mTimingFunction
= nsTimingFunction(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE
);
2311 mProperty
= eCSSPropertyExtra_all_properties
;
2315 mozilla::StyleTransition::SetUnknownProperty(const nsAString
& aUnknownProperty
)
2317 NS_ASSERTION(nsCSSProps::LookupProperty(aUnknownProperty
,
2318 nsCSSProps::eEnabledForAllContent
) ==
2319 eCSSProperty_UNKNOWN
,
2320 "should be unknown property");
2321 mProperty
= eCSSProperty_UNKNOWN
;
2322 mUnknownProperty
= do_GetAtom(aUnknownProperty
);
2325 mozilla::StyleAnimation::StyleAnimation(const mozilla::StyleAnimation
& aCopy
)
2326 : mTimingFunction(aCopy
.mTimingFunction
)
2327 , mDuration(aCopy
.mDuration
)
2328 , mDelay(aCopy
.mDelay
)
2329 , mName(aCopy
.mName
)
2330 , mDirection(aCopy
.mDirection
)
2331 , mFillMode(aCopy
.mFillMode
)
2332 , mPlayState(aCopy
.mPlayState
)
2333 , mIterationCount(aCopy
.mIterationCount
)
2338 mozilla::StyleAnimation::SetInitialValues()
2340 mTimingFunction
= nsTimingFunction(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE
);
2343 mName
= EmptyString();
2344 mDirection
= NS_STYLE_ANIMATION_DIRECTION_NORMAL
;
2345 mFillMode
= NS_STYLE_ANIMATION_FILL_MODE_NONE
;
2346 mPlayState
= NS_STYLE_ANIMATION_PLAY_STATE_RUNNING
;
2347 mIterationCount
= 1.0f
;
2350 nsStyleDisplay::nsStyleDisplay()
2351 : mWillChangeBitField(0)
2353 MOZ_COUNT_CTOR(nsStyleDisplay
);
2354 mAppearance
= NS_THEME_NONE
;
2355 mDisplay
= NS_STYLE_DISPLAY_INLINE
;
2356 mOriginalDisplay
= mDisplay
;
2357 mPosition
= NS_STYLE_POSITION_STATIC
;
2358 mFloats
= NS_STYLE_FLOAT_NONE
;
2359 mOriginalFloats
= mFloats
;
2360 mBreakType
= NS_STYLE_CLEAR_NONE
;
2361 mBreakInside
= NS_STYLE_PAGE_BREAK_AUTO
;
2362 mBreakBefore
= false;
2363 mBreakAfter
= false;
2364 mOverflowX
= NS_STYLE_OVERFLOW_VISIBLE
;
2365 mOverflowY
= NS_STYLE_OVERFLOW_VISIBLE
;
2366 mOverflowClipBox
= NS_STYLE_OVERFLOW_CLIP_BOX_PADDING_BOX
;
2367 mResize
= NS_STYLE_RESIZE_NONE
;
2368 mClipFlags
= NS_STYLE_CLIP_AUTO
;
2369 mClip
.SetRect(0,0,0,0);
2371 mSpecifiedTransform
= nullptr;
2372 mTransformOrigin
[0].SetPercentValue(0.5f
); // Transform is centered on origin
2373 mTransformOrigin
[1].SetPercentValue(0.5f
);
2374 mTransformOrigin
[2].SetCoordValue(0);
2375 mPerspectiveOrigin
[0].SetPercentValue(0.5f
);
2376 mPerspectiveOrigin
[1].SetPercentValue(0.5f
);
2377 mChildPerspective
.SetNoneValue();
2378 mBackfaceVisibility
= NS_STYLE_BACKFACE_VISIBILITY_VISIBLE
;
2379 mTransformStyle
= NS_STYLE_TRANSFORM_STYLE_FLAT
;
2380 mOrient
= NS_STYLE_ORIENT_AUTO
;
2381 mMixBlendMode
= NS_STYLE_BLEND_NORMAL
;
2382 mTouchAction
= NS_STYLE_TOUCH_ACTION_AUTO
;
2384 mTransitions
.AppendElement();
2385 NS_ABORT_IF_FALSE(mTransitions
.Length() == 1,
2386 "appending within auto buffer should never fail");
2387 mTransitions
[0].SetInitialValues();
2388 mTransitionTimingFunctionCount
= 1;
2389 mTransitionDurationCount
= 1;
2390 mTransitionDelayCount
= 1;
2391 mTransitionPropertyCount
= 1;
2393 mAnimations
.AppendElement();
2394 NS_ABORT_IF_FALSE(mAnimations
.Length() == 1,
2395 "appending within auto buffer should never fail");
2396 mAnimations
[0].SetInitialValues();
2397 mAnimationTimingFunctionCount
= 1;
2398 mAnimationDurationCount
= 1;
2399 mAnimationDelayCount
= 1;
2400 mAnimationNameCount
= 1;
2401 mAnimationDirectionCount
= 1;
2402 mAnimationFillModeCount
= 1;
2403 mAnimationPlayStateCount
= 1;
2404 mAnimationIterationCountCount
= 1;
2407 nsStyleDisplay::nsStyleDisplay(const nsStyleDisplay
& aSource
)
2408 : mBinding(aSource
.mBinding
)
2409 , mClip(aSource
.mClip
)
2410 , mOpacity(aSource
.mOpacity
)
2411 , mDisplay(aSource
.mDisplay
)
2412 , mOriginalDisplay(aSource
.mOriginalDisplay
)
2413 , mAppearance(aSource
.mAppearance
)
2414 , mPosition(aSource
.mPosition
)
2415 , mFloats(aSource
.mFloats
)
2416 , mOriginalFloats(aSource
.mOriginalFloats
)
2417 , mBreakType(aSource
.mBreakType
)
2418 , mBreakInside(aSource
.mBreakInside
)
2419 , mBreakBefore(aSource
.mBreakBefore
)
2420 , mBreakAfter(aSource
.mBreakAfter
)
2421 , mOverflowX(aSource
.mOverflowX
)
2422 , mOverflowY(aSource
.mOverflowY
)
2423 , mOverflowClipBox(aSource
.mOverflowClipBox
)
2424 , mResize(aSource
.mResize
)
2425 , mClipFlags(aSource
.mClipFlags
)
2426 , mOrient(aSource
.mOrient
)
2427 , mMixBlendMode(aSource
.mMixBlendMode
)
2428 , mWillChangeBitField(aSource
.mWillChangeBitField
)
2429 , mWillChange(aSource
.mWillChange
)
2430 , mTouchAction(aSource
.mTouchAction
)
2431 , mBackfaceVisibility(aSource
.mBackfaceVisibility
)
2432 , mTransformStyle(aSource
.mTransformStyle
)
2433 , mSpecifiedTransform(aSource
.mSpecifiedTransform
)
2434 , mChildPerspective(aSource
.mChildPerspective
)
2435 , mTransitions(aSource
.mTransitions
)
2436 , mTransitionTimingFunctionCount(aSource
.mTransitionTimingFunctionCount
)
2437 , mTransitionDurationCount(aSource
.mTransitionDurationCount
)
2438 , mTransitionDelayCount(aSource
.mTransitionDelayCount
)
2439 , mTransitionPropertyCount(aSource
.mTransitionPropertyCount
)
2440 , mAnimations(aSource
.mAnimations
)
2441 , mAnimationTimingFunctionCount(aSource
.mAnimationTimingFunctionCount
)
2442 , mAnimationDurationCount(aSource
.mAnimationDurationCount
)
2443 , mAnimationDelayCount(aSource
.mAnimationDelayCount
)
2444 , mAnimationNameCount(aSource
.mAnimationNameCount
)
2445 , mAnimationDirectionCount(aSource
.mAnimationDirectionCount
)
2446 , mAnimationFillModeCount(aSource
.mAnimationFillModeCount
)
2447 , mAnimationPlayStateCount(aSource
.mAnimationPlayStateCount
)
2448 , mAnimationIterationCountCount(aSource
.mAnimationIterationCountCount
)
2450 MOZ_COUNT_CTOR(nsStyleDisplay
);
2452 /* Copy over transform origin. */
2453 mTransformOrigin
[0] = aSource
.mTransformOrigin
[0];
2454 mTransformOrigin
[1] = aSource
.mTransformOrigin
[1];
2455 mTransformOrigin
[2] = aSource
.mTransformOrigin
[2];
2456 mPerspectiveOrigin
[0] = aSource
.mPerspectiveOrigin
[0];
2457 mPerspectiveOrigin
[1] = aSource
.mPerspectiveOrigin
[1];
2460 nsChangeHint
nsStyleDisplay::CalcDifference(const nsStyleDisplay
& aOther
) const
2462 nsChangeHint hint
= nsChangeHint(0);
2464 if (!EqualURIs(mBinding
, aOther
.mBinding
)
2465 || mPosition
!= aOther
.mPosition
2466 || mDisplay
!= aOther
.mDisplay
2467 || (mFloats
== NS_STYLE_FLOAT_NONE
) != (aOther
.mFloats
== NS_STYLE_FLOAT_NONE
)
2468 || mOverflowX
!= aOther
.mOverflowX
2469 || mOverflowY
!= aOther
.mOverflowY
2470 || mResize
!= aOther
.mResize
)
2471 NS_UpdateHint(hint
, nsChangeHint_ReconstructFrame
);
2473 if ((mAppearance
== NS_THEME_TEXTFIELD
&&
2474 aOther
.mAppearance
!= NS_THEME_TEXTFIELD
) ||
2475 (mAppearance
!= NS_THEME_TEXTFIELD
&&
2476 aOther
.mAppearance
== NS_THEME_TEXTFIELD
)) {
2477 // This is for <input type=number> where we allow authors to specify a
2478 // |-moz-appearance:textfield| to get a control without a spinner. (The
2479 // spinner is present for |-moz-appearance:number-input| but also other
2480 // values such as 'none'.) We need to reframe since we want to use
2481 // nsTextControlFrame instead of nsNumberControlFrame if the author
2482 // specifies 'textfield'.
2483 return nsChangeHint_ReconstructFrame
;
2486 if (mFloats
!= aOther
.mFloats
) {
2487 // Changing which side we float on doesn't affect descendants directly
2489 NS_SubtractHint(nsChangeHint_AllReflowHints
,
2490 NS_CombineHint(nsChangeHint_ClearDescendantIntrinsics
,
2491 nsChangeHint_NeedDirtyReflow
)));
2494 // XXX the following is conservative, for now: changing float breaking shouldn't
2495 // necessarily require a repaint, reflow should suffice.
2496 if (mBreakType
!= aOther
.mBreakType
2497 || mBreakInside
!= aOther
.mBreakInside
2498 || mBreakBefore
!= aOther
.mBreakBefore
2499 || mBreakAfter
!= aOther
.mBreakAfter
2500 || mAppearance
!= aOther
.mAppearance
2501 || mOrient
!= aOther
.mOrient
2502 || mOverflowClipBox
!= aOther
.mOverflowClipBox
2503 || mClipFlags
!= aOther
.mClipFlags
)
2504 NS_UpdateHint(hint
, NS_CombineHint(nsChangeHint_AllReflowHints
,
2505 nsChangeHint_RepaintFrame
));
2507 if (!mClip
.IsEqualInterior(aOther
.mClip
)) {
2508 // If the clip has changed, we just need to update overflow areas. DLBI
2509 // will handle the invalidation.
2510 NS_UpdateHint(hint
, NS_CombineHint(nsChangeHint_UpdateOverflow
,
2511 nsChangeHint_SchedulePaint
));
2514 if (mOpacity
!= aOther
.mOpacity
) {
2515 // If we're going from the optimized >=0.99 opacity value to 1.0 or back, then
2516 // repaint the frame because DLBI will not catch the invalidation. Otherwise,
2517 // just update the opacity layer.
2518 if ((mOpacity
>= 0.99f
&& mOpacity
< 1.0f
&& aOther
.mOpacity
== 1.0f
) ||
2519 (aOther
.mOpacity
>= 0.99f
&& aOther
.mOpacity
< 1.0f
&& mOpacity
== 1.0f
)) {
2520 NS_UpdateHint(hint
, nsChangeHint_RepaintFrame
);
2522 NS_UpdateHint(hint
, nsChangeHint_UpdateOpacityLayer
);
2526 if (mMixBlendMode
!= aOther
.mMixBlendMode
) {
2527 NS_UpdateHint(hint
, nsChangeHint_RepaintFrame
);
2530 /* If we've added or removed the transform property, we need to reconstruct the frame to add
2531 * or remove the view object, and also to handle abs-pos and fixed-pos containers.
2533 if (HasTransformStyle() != aOther
.HasTransformStyle()) {
2534 // We do not need to apply nsChangeHint_UpdateTransformLayer since
2535 // nsChangeHint_RepaintFrame will forcibly invalidate the frame area and
2536 // ensure layers are rebuilt (or removed).
2537 NS_UpdateHint(hint
, NS_CombineHint(nsChangeHint_AddOrRemoveTransform
,
2538 NS_CombineHint(nsChangeHint_UpdateOverflow
,
2539 nsChangeHint_RepaintFrame
)));
2541 else if (HasTransformStyle()) {
2542 /* Otherwise, if we've kept the property lying around and we already had a
2543 * transform, we need to see whether or not we've changed the transform.
2544 * If so, we need to recompute its overflow rect (which probably changed
2545 * if the transform changed) and to redraw within the bounds of that new
2548 if (!mSpecifiedTransform
!= !aOther
.mSpecifiedTransform
||
2549 (mSpecifiedTransform
&&
2550 *mSpecifiedTransform
!= *aOther
.mSpecifiedTransform
)) {
2551 NS_UpdateHint(hint
, nsChangeHint_UpdateTransformLayer
);
2553 if (mSpecifiedTransform
&&
2554 aOther
.mSpecifiedTransform
) {
2555 NS_UpdateHint(hint
, nsChangeHint_UpdatePostTransformOverflow
);
2557 NS_UpdateHint(hint
, nsChangeHint_UpdateOverflow
);
2561 const nsChangeHint kUpdateOverflowAndRepaintHint
=
2562 NS_CombineHint(nsChangeHint_UpdateOverflow
, nsChangeHint_RepaintFrame
);
2563 for (uint8_t index
= 0; index
< 3; ++index
)
2564 if (mTransformOrigin
[index
] != aOther
.mTransformOrigin
[index
]) {
2565 NS_UpdateHint(hint
, kUpdateOverflowAndRepaintHint
);
2569 for (uint8_t index
= 0; index
< 2; ++index
)
2570 if (mPerspectiveOrigin
[index
] != aOther
.mPerspectiveOrigin
[index
]) {
2571 NS_UpdateHint(hint
, kUpdateOverflowAndRepaintHint
);
2575 if (mChildPerspective
!= aOther
.mChildPerspective
||
2576 mTransformStyle
!= aOther
.mTransformStyle
)
2577 NS_UpdateHint(hint
, kUpdateOverflowAndRepaintHint
);
2579 if (mBackfaceVisibility
!= aOther
.mBackfaceVisibility
)
2580 NS_UpdateHint(hint
, nsChangeHint_RepaintFrame
);
2583 // Note that the HasTransformStyle() != aOther.HasTransformStyle()
2584 // test above handles relevant changes in the
2585 // NS_STYLE_WILL_CHANGE_TRANSFORM bit, which in turn handles frame
2586 // reconstruction for changes in the containing block of
2587 // fixed-positioned elements. Other than that, all changes to
2588 // 'will-change' can be handled by a repaint.
2589 uint8_t willChangeBitsChanged
=
2590 mWillChangeBitField
^ aOther
.mWillChangeBitField
;
2591 if (willChangeBitsChanged
) {
2592 NS_UpdateHint(hint
, nsChangeHint_RepaintFrame
);
2595 // Note: Our current behavior for handling changes to the
2596 // transition-duration, transition-delay, and transition-timing-function
2597 // properties is to do nothing. In other words, the transition
2598 // property that matters is what it is when the transition begins, and
2599 // we don't stop a transition later because the transition property
2601 // We do handle changes to transition-property, but we don't need to
2602 // bother with anything here, since the transition manager is notified
2603 // of any style context change anyway.
2605 // Note: Likewise, for animation-*, the animation manager gets
2606 // notified about every new style context constructed, and it uses
2607 // that opportunity to handle dynamic changes appropriately.
2612 // --------------------
2613 // nsStyleVisibility
2616 nsStyleVisibility::nsStyleVisibility(nsPresContext
* aPresContext
)
2618 MOZ_COUNT_CTOR(nsStyleVisibility
);
2619 uint32_t bidiOptions
= aPresContext
->GetBidi();
2620 if (GET_BIDI_OPTION_DIRECTION(bidiOptions
) == IBMBIDI_TEXTDIRECTION_RTL
)
2621 mDirection
= NS_STYLE_DIRECTION_RTL
;
2623 mDirection
= NS_STYLE_DIRECTION_LTR
;
2625 mVisible
= NS_STYLE_VISIBILITY_VISIBLE
;
2626 mPointerEvents
= NS_STYLE_POINTER_EVENTS_AUTO
;
2627 mWritingMode
= NS_STYLE_WRITING_MODE_HORIZONTAL_TB
;
2630 nsStyleVisibility::nsStyleVisibility(const nsStyleVisibility
& aSource
)
2632 MOZ_COUNT_CTOR(nsStyleVisibility
);
2633 mImageOrientation
= aSource
.mImageOrientation
;
2634 mDirection
= aSource
.mDirection
;
2635 mVisible
= aSource
.mVisible
;
2636 mPointerEvents
= aSource
.mPointerEvents
;
2637 mWritingMode
= aSource
.mWritingMode
;
2640 nsChangeHint
nsStyleVisibility::CalcDifference(const nsStyleVisibility
& aOther
) const
2642 nsChangeHint hint
= nsChangeHint(0);
2644 if (mDirection
!= aOther
.mDirection
|| mWritingMode
!= aOther
.mWritingMode
) {
2645 NS_UpdateHint(hint
, nsChangeHint_ReconstructFrame
);
2647 if ((mImageOrientation
!= aOther
.mImageOrientation
)) {
2648 NS_UpdateHint(hint
, nsChangeHint_AllReflowHints
);
2649 NS_UpdateHint(hint
, nsChangeHint_RepaintFrame
);
2651 if (mVisible
!= aOther
.mVisible
) {
2652 if ((NS_STYLE_VISIBILITY_COLLAPSE
== mVisible
) ||
2653 (NS_STYLE_VISIBILITY_COLLAPSE
== aOther
.mVisible
)) {
2654 NS_UpdateHint(hint
, NS_STYLE_HINT_REFLOW
);
2656 NS_UpdateHint(hint
, NS_STYLE_HINT_VISUAL
);
2659 if (mPointerEvents
!= aOther
.mPointerEvents
) {
2660 // nsSVGPathGeometryFrame's mRect depends on stroke _and_ on the value
2661 // of pointer-events. See nsSVGPathGeometryFrame::ReflowSVG's use of
2662 // GetHitTestFlags. (Only a reflow, no visual change.)
2663 NS_UpdateHint(hint
, nsChangeHint_NeedReflow
);
2664 NS_UpdateHint(hint
, nsChangeHint_NeedDirtyReflow
); // XXX remove me: bug 876085
2670 nsStyleContentData::~nsStyleContentData()
2672 NS_ABORT_IF_FALSE(!mImageTracked
,
2673 "nsStyleContentData being destroyed while still tracking image!");
2674 if (mType
== eStyleContentType_Image
) {
2675 NS_IF_RELEASE(mContent
.mImage
);
2676 } else if (mType
== eStyleContentType_Counter
||
2677 mType
== eStyleContentType_Counters
) {
2678 mContent
.mCounters
->Release();
2679 } else if (mContent
.mString
) {
2680 NS_Free(mContent
.mString
);
2684 nsStyleContentData
& nsStyleContentData::operator=(const nsStyleContentData
& aOther
)
2686 if (this == &aOther
)
2688 this->~nsStyleContentData();
2689 new (this) nsStyleContentData();
2691 mType
= aOther
.mType
;
2692 if (mType
== eStyleContentType_Image
) {
2693 mContent
.mImage
= aOther
.mContent
.mImage
;
2694 NS_IF_ADDREF(mContent
.mImage
);
2695 } else if (mType
== eStyleContentType_Counter
||
2696 mType
== eStyleContentType_Counters
) {
2697 mContent
.mCounters
= aOther
.mContent
.mCounters
;
2698 mContent
.mCounters
->AddRef();
2699 } else if (aOther
.mContent
.mString
) {
2700 mContent
.mString
= NS_strdup(aOther
.mContent
.mString
);
2702 mContent
.mString
= nullptr;
2707 bool nsStyleContentData::operator==(const nsStyleContentData
& aOther
) const
2709 if (mType
!= aOther
.mType
)
2711 if (mType
== eStyleContentType_Image
) {
2712 if (!mContent
.mImage
|| !aOther
.mContent
.mImage
)
2713 return mContent
.mImage
== aOther
.mContent
.mImage
;
2715 nsCOMPtr
<nsIURI
> thisURI
, otherURI
;
2716 mContent
.mImage
->GetURI(getter_AddRefs(thisURI
));
2717 aOther
.mContent
.mImage
->GetURI(getter_AddRefs(otherURI
));
2718 return thisURI
== otherURI
|| // handles null==null
2719 (thisURI
&& otherURI
&&
2720 NS_SUCCEEDED(thisURI
->Equals(otherURI
, &eq
)) &&
2723 if (mType
== eStyleContentType_Counter
||
2724 mType
== eStyleContentType_Counters
)
2725 return *mContent
.mCounters
== *aOther
.mContent
.mCounters
;
2726 return safe_strcmp(mContent
.mString
, aOther
.mContent
.mString
) == 0;
2730 nsStyleContentData::TrackImage(nsPresContext
* aContext
)
2733 NS_ABORT_IF_FALSE(!mImageTracked
, "Already tracking image!");
2734 NS_ABORT_IF_FALSE(mType
== eStyleContentType_Image
,
2735 "Trying to do image tracking on non-image!");
2736 NS_ABORT_IF_FALSE(mContent
.mImage
,
2737 "Can't track image when there isn't one!");
2739 // Register the image with the document
2740 nsIDocument
* doc
= aContext
->Document();
2742 doc
->AddImage(mContent
.mImage
);
2746 mImageTracked
= true;
2751 nsStyleContentData::UntrackImage(nsPresContext
* aContext
)
2754 NS_ABORT_IF_FALSE(mImageTracked
, "Image not tracked!");
2755 NS_ABORT_IF_FALSE(mType
== eStyleContentType_Image
,
2756 "Trying to do image tracking on non-image!");
2757 NS_ABORT_IF_FALSE(mContent
.mImage
,
2758 "Can't untrack image when there isn't one!");
2760 // Unregister the image with the document
2761 nsIDocument
* doc
= aContext
->Document();
2763 doc
->RemoveImage(mContent
.mImage
, nsIDocument::REQUEST_DISCARD
);
2767 mImageTracked
= false;
2772 //-----------------------
2776 nsStyleContent::nsStyleContent(void)
2779 mIncrements(nullptr),
2785 MOZ_COUNT_CTOR(nsStyleContent
);
2786 mMarkerOffset
.SetAutoValue();
2789 nsStyleContent::~nsStyleContent(void)
2791 MOZ_COUNT_DTOR(nsStyleContent
);
2792 DELETE_ARRAY_IF(mContents
);
2793 DELETE_ARRAY_IF(mIncrements
);
2794 DELETE_ARRAY_IF(mResets
);
2798 nsStyleContent::Destroy(nsPresContext
* aContext
)
2800 // Unregister any images we might have with the document.
2801 for (uint32_t i
= 0; i
< mContentCount
; ++i
) {
2802 if ((mContents
[i
].mType
== eStyleContentType_Image
) &&
2803 mContents
[i
].mContent
.mImage
) {
2804 mContents
[i
].UntrackImage(aContext
);
2808 this->~nsStyleContent();
2809 aContext
->PresShell()->
2810 FreeByObjectID(nsPresArena::nsStyleContent_id
, this);
2813 nsStyleContent::nsStyleContent(const nsStyleContent
& aSource
)
2816 mIncrements(nullptr),
2823 MOZ_COUNT_CTOR(nsStyleContent
);
2824 mMarkerOffset
= aSource
.mMarkerOffset
;
2827 if (NS_SUCCEEDED(AllocateContents(aSource
.ContentCount()))) {
2828 for (index
= 0; index
< mContentCount
; index
++) {
2829 ContentAt(index
) = aSource
.ContentAt(index
);
2833 if (NS_SUCCEEDED(AllocateCounterIncrements(aSource
.CounterIncrementCount()))) {
2834 for (index
= 0; index
< mIncrementCount
; index
++) {
2835 const nsStyleCounterData
*data
= aSource
.GetCounterIncrementAt(index
);
2836 mIncrements
[index
].mCounter
= data
->mCounter
;
2837 mIncrements
[index
].mValue
= data
->mValue
;
2841 if (NS_SUCCEEDED(AllocateCounterResets(aSource
.CounterResetCount()))) {
2842 for (index
= 0; index
< mResetCount
; index
++) {
2843 const nsStyleCounterData
*data
= aSource
.GetCounterResetAt(index
);
2844 mResets
[index
].mCounter
= data
->mCounter
;
2845 mResets
[index
].mValue
= data
->mValue
;
2850 nsChangeHint
nsStyleContent::CalcDifference(const nsStyleContent
& aOther
) const
2852 // In ReResolveStyleContext we assume that if there's no existing
2853 // ::before or ::after and we don't have to restyle children of the
2854 // node then we can't end up with a ::before or ::after due to the
2855 // restyle of the node itself. That's not quite true, but the only
2856 // exception to the above is when the 'content' property of the node
2857 // changes and the pseudo-element inherits the changed value. Since
2858 // the code here triggers a frame change on the node in that case,
2859 // the optimization in ReResolveStyleContext is ok. But if we ever
2860 // change this code to not reconstruct frames on changes to the
2861 // 'content' property, then we will need to revisit the optimization
2862 // in ReResolveStyleContext.
2864 if (mContentCount
!= aOther
.mContentCount
||
2865 mIncrementCount
!= aOther
.mIncrementCount
||
2866 mResetCount
!= aOther
.mResetCount
) {
2867 return NS_STYLE_HINT_FRAMECHANGE
;
2870 uint32_t ix
= mContentCount
;
2872 if (mContents
[ix
] != aOther
.mContents
[ix
]) {
2873 // Unfortunately we need to reframe here; a simple reflow
2874 // will not pick up different text or different image URLs,
2875 // since we set all that up in the CSSFrameConstructor
2876 return NS_STYLE_HINT_FRAMECHANGE
;
2879 ix
= mIncrementCount
;
2881 if ((mIncrements
[ix
].mValue
!= aOther
.mIncrements
[ix
].mValue
) ||
2882 (mIncrements
[ix
].mCounter
!= aOther
.mIncrements
[ix
].mCounter
)) {
2883 return NS_STYLE_HINT_FRAMECHANGE
;
2888 if ((mResets
[ix
].mValue
!= aOther
.mResets
[ix
].mValue
) ||
2889 (mResets
[ix
].mCounter
!= aOther
.mResets
[ix
].mCounter
)) {
2890 return NS_STYLE_HINT_FRAMECHANGE
;
2893 if (mMarkerOffset
!= aOther
.mMarkerOffset
) {
2894 return NS_STYLE_HINT_REFLOW
;
2896 return NS_STYLE_HINT_NONE
;
2899 nsresult
nsStyleContent::AllocateContents(uint32_t aCount
)
2901 // We need to run the destructors of the elements of mContents, so we
2902 // delete and reallocate even if aCount == mContentCount. (If
2903 // nsStyleContentData had its members private and managed their
2904 // ownership on setting, we wouldn't need this, but that seems
2905 // unnecessary at this point.)
2906 DELETE_ARRAY_IF(mContents
);
2908 mContents
= new nsStyleContentData
[aCount
];
2911 return NS_ERROR_OUT_OF_MEMORY
;
2914 mContentCount
= aCount
;
2918 // ---------------------
2922 nsStyleQuotes::nsStyleQuotes(void)
2926 MOZ_COUNT_CTOR(nsStyleQuotes
);
2930 nsStyleQuotes::~nsStyleQuotes(void)
2932 MOZ_COUNT_DTOR(nsStyleQuotes
);
2933 DELETE_ARRAY_IF(mQuotes
);
2936 nsStyleQuotes::nsStyleQuotes(const nsStyleQuotes
& aSource
)
2940 MOZ_COUNT_CTOR(nsStyleQuotes
);
2945 nsStyleQuotes::SetInitial()
2947 // The initial value for quotes is the en-US typographic convention:
2948 // outermost are LEFT and RIGHT DOUBLE QUOTATION MARK, alternating
2949 // with LEFT and RIGHT SINGLE QUOTATION MARK.
2950 static const char16_t initialQuotes
[8] = {
2951 0x201C, 0, 0x201D, 0, 0x2018, 0, 0x2019, 0
2954 if (NS_SUCCEEDED(AllocateQuotes(2))) {
2956 nsDependentString(&initialQuotes
[0], 1),
2957 nsDependentString(&initialQuotes
[2], 1));
2959 nsDependentString(&initialQuotes
[4], 1),
2960 nsDependentString(&initialQuotes
[6], 1));
2965 nsStyleQuotes::CopyFrom(const nsStyleQuotes
& aSource
)
2967 if (NS_SUCCEEDED(AllocateQuotes(aSource
.QuotesCount()))) {
2968 uint32_t count
= (mQuotesCount
* 2);
2969 for (uint32_t index
= 0; index
< count
; index
+= 2) {
2970 aSource
.GetQuotesAt(index
, mQuotes
[index
], mQuotes
[index
+ 1]);
2975 nsChangeHint
nsStyleQuotes::CalcDifference(const nsStyleQuotes
& aOther
) const
2977 // If the quotes implementation is ever going to change we might not need
2978 // a framechange here and a reflow should be sufficient. See bug 35768.
2979 if (mQuotesCount
== aOther
.mQuotesCount
) {
2980 uint32_t ix
= (mQuotesCount
* 2);
2982 if (mQuotes
[ix
] != aOther
.mQuotes
[ix
]) {
2983 return NS_STYLE_HINT_FRAMECHANGE
;
2987 return NS_STYLE_HINT_NONE
;
2989 return NS_STYLE_HINT_FRAMECHANGE
;
2992 // --------------------
2996 nsStyleTextReset::nsStyleTextReset(void)
2998 MOZ_COUNT_CTOR(nsStyleTextReset
);
2999 mVerticalAlign
.SetIntValue(NS_STYLE_VERTICAL_ALIGN_BASELINE
, eStyleUnit_Enumerated
);
3000 mTextDecorationLine
= NS_STYLE_TEXT_DECORATION_LINE_NONE
;
3001 mTextDecorationColor
= NS_RGB(0,0,0);
3002 mTextDecorationStyle
=
3003 NS_STYLE_TEXT_DECORATION_STYLE_SOLID
| BORDER_COLOR_FOREGROUND
;
3004 mUnicodeBidi
= NS_STYLE_UNICODE_BIDI_NORMAL
;
3007 nsStyleTextReset::nsStyleTextReset(const nsStyleTextReset
& aSource
)
3009 MOZ_COUNT_CTOR(nsStyleTextReset
);
3013 nsStyleTextReset::~nsStyleTextReset(void)
3015 MOZ_COUNT_DTOR(nsStyleTextReset
);
3018 nsChangeHint
nsStyleTextReset::CalcDifference(const nsStyleTextReset
& aOther
) const
3020 if (mVerticalAlign
== aOther
.mVerticalAlign
3021 && mUnicodeBidi
== aOther
.mUnicodeBidi
) {
3022 uint8_t lineStyle
= GetDecorationStyle();
3023 uint8_t otherLineStyle
= aOther
.GetDecorationStyle();
3024 if (mTextDecorationLine
!= aOther
.mTextDecorationLine
||
3025 lineStyle
!= otherLineStyle
) {
3026 // Repaint for other style decoration lines because they must be in
3027 // default overflow rect
3028 nsChangeHint hint
= NS_STYLE_HINT_VISUAL
;
3029 NS_UpdateHint(hint
, nsChangeHint_UpdateSubtreeOverflow
);
3033 // Repaint for decoration color changes
3034 nscolor decColor
, otherDecColor
;
3035 bool isFG
, otherIsFG
;
3036 GetDecorationColor(decColor
, isFG
);
3037 aOther
.GetDecorationColor(otherDecColor
, otherIsFG
);
3038 if (isFG
!= otherIsFG
|| (!isFG
&& decColor
!= otherDecColor
)) {
3039 return NS_STYLE_HINT_VISUAL
;
3042 if (mTextOverflow
!= aOther
.mTextOverflow
) {
3043 return NS_STYLE_HINT_VISUAL
;
3045 return NS_STYLE_HINT_NONE
;
3047 return NS_STYLE_HINT_REFLOW
;
3050 // Allowed to return one of NS_STYLE_HINT_NONE, NS_STYLE_HINT_REFLOW
3051 // or NS_STYLE_HINT_VISUAL. Currently we just return NONE or REFLOW, though.
3052 // XXXbz can this not return a more specific hint? If that's ever
3053 // changed, nsStyleBorder::CalcDifference will need changing too.
3055 CalcShadowDifference(nsCSSShadowArray
* lhs
,
3056 nsCSSShadowArray
* rhs
)
3059 return NS_STYLE_HINT_NONE
;
3061 if (!lhs
|| !rhs
|| lhs
->Length() != rhs
->Length())
3062 return NS_STYLE_HINT_REFLOW
;
3064 for (uint32_t i
= 0; i
< lhs
->Length(); ++i
) {
3065 if (*lhs
->ShadowAt(i
) != *rhs
->ShadowAt(i
))
3066 return NS_STYLE_HINT_REFLOW
;
3068 return NS_STYLE_HINT_NONE
;
3071 // --------------------
3075 nsStyleText::nsStyleText(void)
3077 MOZ_COUNT_CTOR(nsStyleText
);
3078 mTextAlign
= NS_STYLE_TEXT_ALIGN_DEFAULT
;
3079 mTextAlignLast
= NS_STYLE_TEXT_ALIGN_AUTO
;
3080 mTextAlignTrue
= false;
3081 mTextAlignLastTrue
= false;
3082 mTextTransform
= NS_STYLE_TEXT_TRANSFORM_NONE
;
3083 mWhiteSpace
= NS_STYLE_WHITESPACE_NORMAL
;
3084 mWordBreak
= NS_STYLE_WORDBREAK_NORMAL
;
3085 mWordWrap
= NS_STYLE_WORDWRAP_NORMAL
;
3086 mHyphens
= NS_STYLE_HYPHENS_MANUAL
;
3087 mTextSizeAdjust
= NS_STYLE_TEXT_SIZE_ADJUST_AUTO
;
3088 mTextOrientation
= NS_STYLE_TEXT_ORIENTATION_AUTO
;
3089 mTextCombineUpright
= NS_STYLE_TEXT_COMBINE_UPRIGHT_NONE
;
3090 mControlCharacterVisibility
= NS_STYLE_CONTROL_CHARACTER_VISIBILITY_HIDDEN
;
3092 mLetterSpacing
.SetNormalValue();
3093 mLineHeight
.SetNormalValue();
3094 mTextIndent
.SetCoordValue(0);
3097 mTextShadow
= nullptr;
3098 mTabSize
= NS_STYLE_TABSIZE_INITIAL
;
3101 nsStyleText::nsStyleText(const nsStyleText
& aSource
)
3102 : mTextAlign(aSource
.mTextAlign
),
3103 mTextAlignLast(aSource
.mTextAlignLast
),
3104 mTextAlignTrue(false),
3105 mTextAlignLastTrue(false),
3106 mTextTransform(aSource
.mTextTransform
),
3107 mWhiteSpace(aSource
.mWhiteSpace
),
3108 mWordBreak(aSource
.mWordBreak
),
3109 mWordWrap(aSource
.mWordWrap
),
3110 mHyphens(aSource
.mHyphens
),
3111 mTextSizeAdjust(aSource
.mTextSizeAdjust
),
3112 mTextOrientation(aSource
.mTextOrientation
),
3113 mTextCombineUpright(aSource
.mTextCombineUpright
),
3114 mControlCharacterVisibility(aSource
.mControlCharacterVisibility
),
3115 mTabSize(aSource
.mTabSize
),
3116 mWordSpacing(aSource
.mWordSpacing
),
3117 mLetterSpacing(aSource
.mLetterSpacing
),
3118 mLineHeight(aSource
.mLineHeight
),
3119 mTextIndent(aSource
.mTextIndent
),
3120 mTextShadow(aSource
.mTextShadow
)
3122 MOZ_COUNT_CTOR(nsStyleText
);
3125 nsStyleText::~nsStyleText(void)
3127 MOZ_COUNT_DTOR(nsStyleText
);
3130 nsChangeHint
nsStyleText::CalcDifference(const nsStyleText
& aOther
) const
3132 if (WhiteSpaceOrNewlineIsSignificant() !=
3133 aOther
.WhiteSpaceOrNewlineIsSignificant()) {
3134 // This may require construction of suppressed text frames
3135 return NS_STYLE_HINT_FRAMECHANGE
;
3138 if (mTextCombineUpright
!= aOther
.mTextCombineUpright
||
3139 mControlCharacterVisibility
!= aOther
.mControlCharacterVisibility
) {
3140 return nsChangeHint_ReconstructFrame
;
3143 if ((mTextAlign
!= aOther
.mTextAlign
) ||
3144 (mTextAlignLast
!= aOther
.mTextAlignLast
) ||
3145 (mTextAlignTrue
!= aOther
.mTextAlignTrue
) ||
3146 (mTextAlignLastTrue
!= aOther
.mTextAlignLastTrue
) ||
3147 (mTextTransform
!= aOther
.mTextTransform
) ||
3148 (mWhiteSpace
!= aOther
.mWhiteSpace
) ||
3149 (mWordBreak
!= aOther
.mWordBreak
) ||
3150 (mWordWrap
!= aOther
.mWordWrap
) ||
3151 (mHyphens
!= aOther
.mHyphens
) ||
3152 (mTextSizeAdjust
!= aOther
.mTextSizeAdjust
) ||
3153 (mTextOrientation
!= aOther
.mTextOrientation
) ||
3154 (mLetterSpacing
!= aOther
.mLetterSpacing
) ||
3155 (mLineHeight
!= aOther
.mLineHeight
) ||
3156 (mTextIndent
!= aOther
.mTextIndent
) ||
3157 (mWordSpacing
!= aOther
.mWordSpacing
) ||
3158 (mTabSize
!= aOther
.mTabSize
))
3159 return NS_STYLE_HINT_REFLOW
;
3161 return CalcShadowDifference(mTextShadow
, aOther
.mTextShadow
);
3164 //-----------------------
3165 // nsStyleUserInterface
3168 nsCursorImage::nsCursorImage()
3169 : mHaveHotspot(false)
3175 nsCursorImage::nsCursorImage(const nsCursorImage
& aOther
)
3176 : mHaveHotspot(aOther
.mHaveHotspot
)
3177 , mHotspotX(aOther
.mHotspotX
)
3178 , mHotspotY(aOther
.mHotspotY
)
3180 SetImage(aOther
.GetImage());
3183 nsCursorImage::~nsCursorImage()
3189 nsCursorImage::operator=(const nsCursorImage
& aOther
)
3191 if (this != &aOther
) {
3192 mHaveHotspot
= aOther
.mHaveHotspot
;
3193 mHotspotX
= aOther
.mHotspotX
;
3194 mHotspotY
= aOther
.mHotspotY
;
3195 SetImage(aOther
.GetImage());
3201 nsStyleUserInterface::nsStyleUserInterface(void)
3203 MOZ_COUNT_CTOR(nsStyleUserInterface
);
3204 mUserInput
= NS_STYLE_USER_INPUT_AUTO
;
3205 mUserModify
= NS_STYLE_USER_MODIFY_READ_ONLY
;
3206 mUserFocus
= NS_STYLE_USER_FOCUS_NONE
;
3208 mCursor
= NS_STYLE_CURSOR_AUTO
; // fix for bugzilla bug 51113
3210 mCursorArrayLength
= 0;
3211 mCursorArray
= nullptr;
3214 nsStyleUserInterface::nsStyleUserInterface(const nsStyleUserInterface
& aSource
) :
3215 mUserInput(aSource
.mUserInput
),
3216 mUserModify(aSource
.mUserModify
),
3217 mUserFocus(aSource
.mUserFocus
),
3218 mCursor(aSource
.mCursor
)
3220 MOZ_COUNT_CTOR(nsStyleUserInterface
);
3221 CopyCursorArrayFrom(aSource
);
3224 nsStyleUserInterface::~nsStyleUserInterface(void)
3226 MOZ_COUNT_DTOR(nsStyleUserInterface
);
3227 delete [] mCursorArray
;
3230 nsChangeHint
nsStyleUserInterface::CalcDifference(const nsStyleUserInterface
& aOther
) const
3232 nsChangeHint hint
= nsChangeHint(0);
3233 if (mCursor
!= aOther
.mCursor
)
3234 NS_UpdateHint(hint
, nsChangeHint_UpdateCursor
);
3236 // We could do better. But it wouldn't be worth it, URL-specified cursors are
3238 if (mCursorArrayLength
> 0 || aOther
.mCursorArrayLength
> 0)
3239 NS_UpdateHint(hint
, nsChangeHint_UpdateCursor
);
3241 if (mUserModify
!= aOther
.mUserModify
)
3242 NS_UpdateHint(hint
, NS_STYLE_HINT_VISUAL
);
3244 if ((mUserInput
!= aOther
.mUserInput
) &&
3245 ((NS_STYLE_USER_INPUT_NONE
== mUserInput
) ||
3246 (NS_STYLE_USER_INPUT_NONE
== aOther
.mUserInput
))) {
3247 NS_UpdateHint(hint
, NS_STYLE_HINT_FRAMECHANGE
);
3250 // ignore mUserFocus
3256 nsStyleUserInterface::CopyCursorArrayFrom(const nsStyleUserInterface
& aSource
)
3258 mCursorArray
= nullptr;
3259 mCursorArrayLength
= 0;
3260 if (aSource
.mCursorArrayLength
) {
3261 mCursorArray
= new nsCursorImage
[aSource
.mCursorArrayLength
];
3263 mCursorArrayLength
= aSource
.mCursorArrayLength
;
3264 for (uint32_t i
= 0; i
< mCursorArrayLength
; ++i
)
3265 mCursorArray
[i
] = aSource
.mCursorArray
[i
];
3270 //-----------------------
3274 nsStyleUIReset::nsStyleUIReset(void)
3276 MOZ_COUNT_CTOR(nsStyleUIReset
);
3277 mUserSelect
= NS_STYLE_USER_SELECT_AUTO
;
3278 mForceBrokenImageIcon
= 0;
3279 mIMEMode
= NS_STYLE_IME_MODE_AUTO
;
3280 mWindowShadow
= NS_STYLE_WINDOW_SHADOW_DEFAULT
;
3283 nsStyleUIReset::nsStyleUIReset(const nsStyleUIReset
& aSource
)
3285 MOZ_COUNT_CTOR(nsStyleUIReset
);
3286 mUserSelect
= aSource
.mUserSelect
;
3287 mForceBrokenImageIcon
= aSource
.mForceBrokenImageIcon
;
3288 mIMEMode
= aSource
.mIMEMode
;
3289 mWindowShadow
= aSource
.mWindowShadow
;
3292 nsStyleUIReset::~nsStyleUIReset(void)
3294 MOZ_COUNT_DTOR(nsStyleUIReset
);
3297 nsChangeHint
nsStyleUIReset::CalcDifference(const nsStyleUIReset
& aOther
) const
3300 if (mForceBrokenImageIcon
!= aOther
.mForceBrokenImageIcon
)
3301 return NS_STYLE_HINT_FRAMECHANGE
;
3302 if (mWindowShadow
!= aOther
.mWindowShadow
) {
3303 // We really need just an nsChangeHint_SyncFrameView, except
3304 // on an ancestor of the frame, so we get that by doing a
3306 return NS_STYLE_HINT_REFLOW
;
3308 if (mUserSelect
!= aOther
.mUserSelect
)
3309 return NS_STYLE_HINT_VISUAL
;
3310 return NS_STYLE_HINT_NONE
;
3313 //-----------------------
3317 nsStyleVariables::nsStyleVariables()
3319 MOZ_COUNT_CTOR(nsStyleVariables
);
3322 nsStyleVariables::nsStyleVariables(const nsStyleVariables
& aSource
)
3324 MOZ_COUNT_CTOR(nsStyleVariables
);
3327 nsStyleVariables::~nsStyleVariables(void)
3329 MOZ_COUNT_DTOR(nsStyleVariables
);
3333 nsStyleVariables::CalcDifference(const nsStyleVariables
& aOther
) const
3335 return nsChangeHint(0);