Bumping gaia.json for 2 gaia revision(s) a=gaia-bump
[gecko.git] / layout / style / nsStyleStruct.cpp
blobb6b407af3e26003b63062c51398e8597bfcbf695
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/. */
6 /*
7 * structs that contain the data provided by nsStyleContext, the
8 * internal API for computed style data for an element
9 */
11 #include "nsStyleStruct.h"
12 #include "nsStyleStructInlines.h"
13 #include "nsStyleConsts.h"
14 #include "nsThemeConstants.h"
15 #include "nsString.h"
16 #include "nsPresContext.h"
17 #include "nsIWidget.h"
18 #include "nsCRTGlue.h"
19 #include "nsCSSProps.h"
21 #include "nsCOMPtr.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"
31 #include "nsIURI.h"
32 #include "nsIDocument.h"
33 #include <algorithm>
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)
47 bool eq;
48 return aURI1 == aURI2 || // handle null==null, and optimize
49 (aURI1 && aURI2 &&
50 NS_SUCCEEDED(aURI1->Equals(aURI2, &eq)) && // not equal on fail
51 eq);
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) {
63 return true;
66 if (!aImage1 || !aImage2) {
67 return false;
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)
79 if (!a || !b) {
80 return (int)(a - b);
82 return NS_strcmp(a, b);
85 static nsChangeHint CalcShadowDifference(nsCSSShadowArray* lhs,
86 nsCSSShadowArray* rhs);
88 // --------------------
89 // nsStyleFont
91 nsStyleFont::nsStyleFont(const nsFont& aFont, nsPresContext *aPresContext)
92 : mFont(aFont)
93 , mGenericID(kGenericFont_NONE)
94 , mExplicitLanguage(false)
96 MOZ_COUNT_CTOR(nsStyleFont);
97 Init(aPresContext);
100 nsStyleFont::nsStyleFont(const nsStyleFont& aSrc)
101 : mFont(aSrc.mFont)
102 , mSize(aSrc.mSize)
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,
120 nullptr)))
121 , mGenericID(kGenericFont_NONE)
122 , mExplicitLanguage(false)
124 MOZ_COUNT_CTOR(nsStyleFont);
125 Init(aPresContext);
128 void
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));
135 mScriptLevel = 0;
136 mScriptSizeMultiplier = NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER;
137 mMathVariant = NS_MATHML_MATHVARIANT_NONE;
138 mMathDisplay = NS_MATHML_DISPLAYSTYLE_INLINE;
139 mAllowZoom = true;
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.
152 } else {
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();
159 void
160 nsStyleFont::Destroy(nsPresContext* aContext) {
161 this->~nsStyleFont();
162 aContext->PresShell()->
163 FreeByObjectID(nsPresArena::nsStyleFont_id, this);
166 void
167 nsStyleFont::EnableZoom(nsPresContext* aContext, bool aEnable)
169 if (mAllowZoom == aEnable) {
170 return;
172 mAllowZoom = aEnable;
173 if (mAllowZoom) {
174 mSize = nsStyleFont::ZoomText(aContext, mSize);
175 mFont.size = nsStyleFont::ZoomText(aContext, mFont.size);
176 mScriptUnconstrainedSize =
177 nsStyleFont::ZoomText(aContext, mScriptUnconstrainedSize);
178 } else {
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;
198 nsChangeHint hint = CalcFontDifference(mFont, aOther.mFont);
199 if (hint) {
200 return hint;
203 // XXX Should any of these cause a non-nsChangeHint_NeutralChange change?
204 if (mGenericID != aOther.mGenericID ||
205 mScriptLevel != aOther.mScriptLevel ||
206 mScriptUnconstrainedSize != aOther.mScriptUnconstrainedSize ||
207 mScriptMinSize != aOther.mScriptMinSize ||
208 mScriptSizeMultiplier != aOther.mScriptSizeMultiplier) {
209 return nsChangeHint_NeutralChange;
212 return NS_STYLE_HINT_NONE;
215 /* static */ nscoord
216 nsStyleFont::ZoomText(nsPresContext *aPresContext, nscoord aSize)
218 return nscoord(float(aSize) * aPresContext->TextZoom());
221 /* static */ nscoord
222 nsStyleFont::UnZoomText(nsPresContext *aPresContext, nscoord aSize)
224 return nscoord(float(aSize) / aPresContext->TextZoom());
227 nsChangeHint nsStyleFont::CalcFontDifference(const nsFont& aFont1, const nsFont& aFont2)
229 if ((aFont1.size == aFont2.size) &&
230 (aFont1.sizeAdjust == aFont2.sizeAdjust) &&
231 (aFont1.style == aFont2.style) &&
232 (aFont1.weight == aFont2.weight) &&
233 (aFont1.stretch == aFont2.stretch) &&
234 (aFont1.smoothing == aFont2.smoothing) &&
235 (aFont1.fontlist == aFont2.fontlist) &&
236 (aFont1.kerning == aFont2.kerning) &&
237 (aFont1.synthesis == aFont2.synthesis) &&
238 (aFont1.variantAlternates == aFont2.variantAlternates) &&
239 (aFont1.alternateValues == aFont2.alternateValues) &&
240 (aFont1.featureValueLookup == aFont2.featureValueLookup) &&
241 (aFont1.variantCaps == aFont2.variantCaps) &&
242 (aFont1.variantEastAsian == aFont2.variantEastAsian) &&
243 (aFont1.variantLigatures == aFont2.variantLigatures) &&
244 (aFont1.variantNumeric == aFont2.variantNumeric) &&
245 (aFont1.variantPosition == aFont2.variantPosition) &&
246 (aFont1.fontFeatureSettings == aFont2.fontFeatureSettings) &&
247 (aFont1.languageOverride == aFont2.languageOverride) &&
248 (aFont1.systemFont == aFont2.systemFont)) {
249 if ((aFont1.decorations == aFont2.decorations)) {
250 return NS_STYLE_HINT_NONE;
252 return NS_STYLE_HINT_VISUAL;
254 return NS_STYLE_HINT_REFLOW;
257 static bool IsFixedData(const nsStyleSides& aSides, bool aEnumOK)
259 NS_FOR_CSS_SIDES(side) {
260 if (!IsFixedUnit(aSides.Get(side), aEnumOK))
261 return false;
263 return true;
266 static nscoord CalcCoord(const nsStyleCoord& aCoord,
267 const nscoord* aEnumTable,
268 int32_t aNumEnums)
270 if (aCoord.GetUnit() == eStyleUnit_Enumerated) {
271 NS_ABORT_IF_FALSE(aEnumTable, "must have enum table");
272 int32_t value = aCoord.GetIntValue();
273 if (0 <= value && value < aNumEnums) {
274 return aEnumTable[aCoord.GetIntValue()];
276 NS_NOTREACHED("unexpected enum value");
277 return 0;
279 NS_ABORT_IF_FALSE(aCoord.ConvertsToLength(), "unexpected unit");
280 return nsRuleNode::ComputeCoordPercentCalc(aCoord, 0);
283 nsStyleMargin::nsStyleMargin()
284 : mHasCachedMargin(false)
285 , mCachedMargin(0, 0, 0, 0)
287 MOZ_COUNT_CTOR(nsStyleMargin);
288 nsStyleCoord zero(0, nsStyleCoord::CoordConstructor);
289 NS_FOR_CSS_SIDES(side) {
290 mMargin.Set(side, zero);
294 nsStyleMargin::nsStyleMargin(const nsStyleMargin& aSrc)
295 : mMargin(aSrc.mMargin)
296 , mHasCachedMargin(false)
297 , mCachedMargin(0, 0, 0, 0)
299 MOZ_COUNT_CTOR(nsStyleMargin);
302 void
303 nsStyleMargin::Destroy(nsPresContext* aContext) {
304 this->~nsStyleMargin();
305 aContext->PresShell()->
306 FreeByObjectID(nsPresArena::nsStyleMargin_id, this);
310 void nsStyleMargin::RecalcData()
312 if (IsFixedData(mMargin, false)) {
313 NS_FOR_CSS_SIDES(side) {
314 mCachedMargin.Side(side) = CalcCoord(mMargin.Get(side), nullptr, 0);
316 mHasCachedMargin = true;
318 else
319 mHasCachedMargin = false;
322 nsChangeHint nsStyleMargin::CalcDifference(const nsStyleMargin& aOther) const
324 if (mMargin == aOther.mMargin) {
325 return NS_STYLE_HINT_NONE;
327 // Margin differences can't affect descendant intrinsic sizes and
328 // don't need to force children to reflow.
329 return NS_CombineHint(nsChangeHint_NeedReflow,
330 nsChangeHint_ClearAncestorIntrinsics);
333 nsStylePadding::nsStylePadding()
334 : mHasCachedPadding(false)
335 , mCachedPadding(0, 0, 0, 0)
337 MOZ_COUNT_CTOR(nsStylePadding);
338 nsStyleCoord zero(0, nsStyleCoord::CoordConstructor);
339 NS_FOR_CSS_SIDES(side) {
340 mPadding.Set(side, zero);
344 nsStylePadding::nsStylePadding(const nsStylePadding& aSrc)
345 : mPadding(aSrc.mPadding)
346 , mHasCachedPadding(false)
347 , mCachedPadding(0, 0, 0, 0)
349 MOZ_COUNT_CTOR(nsStylePadding);
352 void
353 nsStylePadding::Destroy(nsPresContext* aContext) {
354 this->~nsStylePadding();
355 aContext->PresShell()->
356 FreeByObjectID(nsPresArena::nsStylePadding_id, this);
359 void nsStylePadding::RecalcData()
361 if (IsFixedData(mPadding, false)) {
362 NS_FOR_CSS_SIDES(side) {
363 // Clamp negative calc() to 0.
364 mCachedPadding.Side(side) =
365 std::max(CalcCoord(mPadding.Get(side), nullptr, 0), 0);
367 mHasCachedPadding = true;
369 else
370 mHasCachedPadding = false;
373 nsChangeHint nsStylePadding::CalcDifference(const nsStylePadding& aOther) const
375 if (mPadding == aOther.mPadding) {
376 return NS_STYLE_HINT_NONE;
378 // Padding differences can't affect descendant intrinsic sizes, but do need
379 // to force children to reflow so that we can reposition them, since their
380 // offsets are from our frame bounds but our content rect's position within
381 // those bounds is moving.
382 return NS_SubtractHint(NS_STYLE_HINT_REFLOW,
383 nsChangeHint_ClearDescendantIntrinsics);
386 nsStyleBorder::nsStyleBorder(nsPresContext* aPresContext)
387 : mBorderColors(nullptr),
388 mBoxShadow(nullptr),
389 mBorderImageFill(NS_STYLE_BORDER_IMAGE_SLICE_NOFILL),
390 mBorderImageRepeatH(NS_STYLE_BORDER_IMAGE_REPEAT_STRETCH),
391 mBorderImageRepeatV(NS_STYLE_BORDER_IMAGE_REPEAT_STRETCH),
392 mFloatEdge(NS_STYLE_FLOAT_EDGE_CONTENT),
393 mBoxDecorationBreak(NS_STYLE_BOX_DECORATION_BREAK_SLICE),
394 mComputedBorder(0, 0, 0, 0)
396 MOZ_COUNT_CTOR(nsStyleBorder);
398 NS_FOR_CSS_HALF_CORNERS (corner) {
399 mBorderRadius.Set(corner, nsStyleCoord(0, nsStyleCoord::CoordConstructor));
402 nscoord medium =
403 (aPresContext->GetBorderWidthTable())[NS_STYLE_BORDER_WIDTH_MEDIUM];
404 NS_FOR_CSS_SIDES(side) {
405 mBorderImageSlice.Set(side, nsStyleCoord(1.0f, eStyleUnit_Percent));
406 mBorderImageWidth.Set(side, nsStyleCoord(1.0f, eStyleUnit_Factor));
407 mBorderImageOutset.Set(side, nsStyleCoord(0.0f, eStyleUnit_Factor));
409 mBorder.Side(side) = medium;
410 mBorderStyle[side] = NS_STYLE_BORDER_STYLE_NONE | BORDER_COLOR_FOREGROUND;
411 mBorderColor[side] = NS_RGB(0, 0, 0);
414 mTwipsPerPixel = aPresContext->DevPixelsToAppUnits(1);
417 nsBorderColors::~nsBorderColors()
419 NS_CSS_DELETE_LIST_MEMBER(nsBorderColors, this, mNext);
422 nsBorderColors*
423 nsBorderColors::Clone(bool aDeep) const
425 nsBorderColors* result = new nsBorderColors(mColor);
426 if (MOZ_UNLIKELY(!result))
427 return result;
428 if (aDeep)
429 NS_CSS_CLONE_LIST_MEMBER(nsBorderColors, this, mNext, result, (false));
430 return result;
433 nsStyleBorder::nsStyleBorder(const nsStyleBorder& aSrc)
434 : mBorderColors(nullptr),
435 mBoxShadow(aSrc.mBoxShadow),
436 mBorderRadius(aSrc.mBorderRadius),
437 mBorderImageSource(aSrc.mBorderImageSource),
438 mBorderImageSlice(aSrc.mBorderImageSlice),
439 mBorderImageWidth(aSrc.mBorderImageWidth),
440 mBorderImageOutset(aSrc.mBorderImageOutset),
441 mBorderImageFill(aSrc.mBorderImageFill),
442 mBorderImageRepeatH(aSrc.mBorderImageRepeatH),
443 mBorderImageRepeatV(aSrc.mBorderImageRepeatV),
444 mFloatEdge(aSrc.mFloatEdge),
445 mBoxDecorationBreak(aSrc.mBoxDecorationBreak),
446 mComputedBorder(aSrc.mComputedBorder),
447 mBorder(aSrc.mBorder),
448 mTwipsPerPixel(aSrc.mTwipsPerPixel)
450 MOZ_COUNT_CTOR(nsStyleBorder);
451 if (aSrc.mBorderColors) {
452 EnsureBorderColors();
453 for (int32_t i = 0; i < 4; i++)
454 if (aSrc.mBorderColors[i])
455 mBorderColors[i] = aSrc.mBorderColors[i]->Clone();
456 else
457 mBorderColors[i] = nullptr;
460 NS_FOR_CSS_SIDES(side) {
461 mBorderStyle[side] = aSrc.mBorderStyle[side];
462 mBorderColor[side] = aSrc.mBorderColor[side];
466 nsStyleBorder::~nsStyleBorder()
468 MOZ_COUNT_DTOR(nsStyleBorder);
469 if (mBorderColors) {
470 for (int32_t i = 0; i < 4; i++)
471 delete mBorderColors[i];
472 delete [] mBorderColors;
476 nsMargin
477 nsStyleBorder::GetImageOutset() const
479 // We don't check whether there is a border-image (which is OK since
480 // the initial values yields 0 outset) so that we don't have to
481 // reflow to update overflow areas when an image loads.
482 nsMargin outset;
483 NS_FOR_CSS_SIDES(s) {
484 nsStyleCoord coord = mBorderImageOutset.Get(s);
485 nscoord value;
486 switch (coord.GetUnit()) {
487 case eStyleUnit_Coord:
488 value = coord.GetCoordValue();
489 break;
490 case eStyleUnit_Factor:
491 value = coord.GetFactorValue() * mComputedBorder.Side(s);
492 break;
493 default:
494 NS_NOTREACHED("unexpected CSS unit for image outset");
495 value = 0;
496 break;
498 outset.Side(s) = value;
500 return outset;
503 void
504 nsStyleBorder::Destroy(nsPresContext* aContext) {
505 UntrackImage(aContext);
506 this->~nsStyleBorder();
507 aContext->PresShell()->
508 FreeByObjectID(nsPresArena::nsStyleBorder_id, this);
511 nsChangeHint nsStyleBorder::CalcDifference(const nsStyleBorder& aOther) const
513 nsChangeHint shadowDifference =
514 CalcShadowDifference(mBoxShadow, aOther.mBoxShadow);
515 NS_ABORT_IF_FALSE(shadowDifference == unsigned(NS_STYLE_HINT_REFLOW) ||
516 shadowDifference == unsigned(NS_STYLE_HINT_VISUAL) ||
517 shadowDifference == unsigned(NS_STYLE_HINT_NONE),
518 "should do more with shadowDifference");
520 // XXXbz we should be able to return a more specific change hint for
521 // at least GetComputedBorder() differences...
522 if (mTwipsPerPixel != aOther.mTwipsPerPixel ||
523 GetComputedBorder() != aOther.GetComputedBorder() ||
524 mFloatEdge != aOther.mFloatEdge ||
525 mBorderImageOutset != aOther.mBorderImageOutset ||
526 (shadowDifference & nsChangeHint_NeedReflow) ||
527 mBoxDecorationBreak != aOther.mBoxDecorationBreak)
528 return NS_STYLE_HINT_REFLOW;
530 NS_FOR_CSS_SIDES(ix) {
531 // See the explanation in nsChangeHint.h of
532 // nsChangeHint_BorderStyleNoneChange .
533 // Furthermore, even though we know *this* side is 0 width, just
534 // assume a visual hint for some other change rather than bother
535 // tracking this result through the rest of the function.
536 if (HasVisibleStyle(ix) != aOther.HasVisibleStyle(ix)) {
537 return NS_CombineHint(NS_STYLE_HINT_VISUAL,
538 nsChangeHint_BorderStyleNoneChange);
542 // Note that mBorderStyle stores not only the border style but also
543 // color-related flags. Given that we've already done an mComputedBorder
544 // comparison, border-style differences can only lead to a VISUAL hint. So
545 // it's OK to just compare the values directly -- if either the actual
546 // style or the color flags differ we want to repaint.
547 NS_FOR_CSS_SIDES(ix) {
548 if (mBorderStyle[ix] != aOther.mBorderStyle[ix] ||
549 mBorderColor[ix] != aOther.mBorderColor[ix])
550 return NS_STYLE_HINT_VISUAL;
553 if (mBorderRadius != aOther.mBorderRadius ||
554 !mBorderColors != !aOther.mBorderColors)
555 return NS_STYLE_HINT_VISUAL;
557 if (IsBorderImageLoaded() || aOther.IsBorderImageLoaded()) {
558 if (mBorderImageSource != aOther.mBorderImageSource ||
559 mBorderImageRepeatH != aOther.mBorderImageRepeatH ||
560 mBorderImageRepeatV != aOther.mBorderImageRepeatV ||
561 mBorderImageSlice != aOther.mBorderImageSlice ||
562 mBorderImageFill != aOther.mBorderImageFill ||
563 mBorderImageWidth != aOther.mBorderImageWidth ||
564 mBorderImageOutset != aOther.mBorderImageOutset)
565 return NS_STYLE_HINT_VISUAL;
568 // Note that at this point if mBorderColors is non-null so is
569 // aOther.mBorderColors
570 if (mBorderColors) {
571 NS_FOR_CSS_SIDES(ix) {
572 if (!nsBorderColors::Equal(mBorderColors[ix],
573 aOther.mBorderColors[ix]))
574 return NS_STYLE_HINT_VISUAL;
578 if (shadowDifference) {
579 return shadowDifference;
582 // mBorder is the specified border value. Changes to this don't
583 // need any change processing, since we operate on the computed
584 // border values instead.
585 if (mBorder != aOther.mBorder) {
586 return nsChangeHint_NeutralChange;
589 return NS_STYLE_HINT_NONE;
592 nsStyleOutline::nsStyleOutline(nsPresContext* aPresContext)
594 MOZ_COUNT_CTOR(nsStyleOutline);
595 // spacing values not inherited
596 nsStyleCoord zero(0, nsStyleCoord::CoordConstructor);
597 NS_FOR_CSS_HALF_CORNERS(corner) {
598 mOutlineRadius.Set(corner, zero);
601 mOutlineOffset = 0;
603 mOutlineWidth = nsStyleCoord(NS_STYLE_BORDER_WIDTH_MEDIUM, eStyleUnit_Enumerated);
604 mOutlineStyle = NS_STYLE_BORDER_STYLE_NONE;
605 mOutlineColor = NS_RGB(0, 0, 0);
607 mHasCachedOutline = false;
608 mTwipsPerPixel = aPresContext->DevPixelsToAppUnits(1);
611 nsStyleOutline::nsStyleOutline(const nsStyleOutline& aSrc)
612 : mOutlineRadius(aSrc.mOutlineRadius)
613 , mOutlineWidth(aSrc.mOutlineWidth)
614 , mOutlineOffset(aSrc.mOutlineOffset)
615 , mCachedOutlineWidth(aSrc.mCachedOutlineWidth)
616 , mOutlineColor(aSrc.mOutlineColor)
617 , mHasCachedOutline(aSrc.mHasCachedOutline)
618 , mOutlineStyle(aSrc.mOutlineStyle)
619 , mTwipsPerPixel(aSrc.mTwipsPerPixel)
621 MOZ_COUNT_CTOR(nsStyleOutline);
624 void
625 nsStyleOutline::RecalcData(nsPresContext* aContext)
627 if (NS_STYLE_BORDER_STYLE_NONE == GetOutlineStyle()) {
628 mCachedOutlineWidth = 0;
629 mHasCachedOutline = true;
630 } else if (IsFixedUnit(mOutlineWidth, true)) {
631 // Clamp negative calc() to 0.
632 mCachedOutlineWidth =
633 std::max(CalcCoord(mOutlineWidth, aContext->GetBorderWidthTable(), 3), 0);
634 mCachedOutlineWidth =
635 NS_ROUND_BORDER_TO_PIXELS(mCachedOutlineWidth, mTwipsPerPixel);
636 mHasCachedOutline = true;
638 else
639 mHasCachedOutline = false;
642 nsChangeHint nsStyleOutline::CalcDifference(const nsStyleOutline& aOther) const
644 bool outlineWasVisible =
645 mCachedOutlineWidth > 0 && mOutlineStyle != NS_STYLE_BORDER_STYLE_NONE;
646 bool outlineIsVisible =
647 aOther.mCachedOutlineWidth > 0 && aOther.mOutlineStyle != NS_STYLE_BORDER_STYLE_NONE;
648 if (outlineWasVisible != outlineIsVisible ||
649 (outlineIsVisible && (mOutlineOffset != aOther.mOutlineOffset ||
650 mOutlineWidth != aOther.mOutlineWidth ||
651 mTwipsPerPixel != aOther.mTwipsPerPixel))) {
652 return NS_CombineHint(nsChangeHint_AllReflowHints,
653 nsChangeHint_RepaintFrame);
656 if ((mOutlineStyle != aOther.mOutlineStyle) ||
657 (mOutlineColor != aOther.mOutlineColor) ||
658 (mOutlineRadius != aOther.mOutlineRadius)) {
659 return nsChangeHint_RepaintFrame;
662 // XXX Not exactly sure if we need to check the cached outline values.
663 if (mOutlineWidth != aOther.mOutlineWidth ||
664 mOutlineOffset != aOther.mOutlineOffset ||
665 mTwipsPerPixel != aOther.mTwipsPerPixel ||
666 mHasCachedOutline != aOther.mHasCachedOutline ||
667 (mHasCachedOutline &&
668 (mCachedOutlineWidth != aOther.mCachedOutlineWidth))) {
669 return nsChangeHint_NeutralChange;
672 return NS_STYLE_HINT_NONE;
675 // --------------------
676 // nsStyleList
678 nsStyleList::nsStyleList(nsPresContext* aPresContext)
679 : mListStylePosition(NS_STYLE_LIST_STYLE_POSITION_OUTSIDE),
680 mListStyleType(NS_LITERAL_STRING("disc")),
681 mCounterStyle(aPresContext->CounterStyleManager()->
682 BuildCounterStyle(mListStyleType))
684 MOZ_COUNT_CTOR(nsStyleList);
687 nsStyleList::~nsStyleList()
689 MOZ_COUNT_DTOR(nsStyleList);
692 nsStyleList::nsStyleList(const nsStyleList& aSource)
693 : mListStylePosition(aSource.mListStylePosition),
694 mListStyleType(aSource.mListStyleType),
695 mCounterStyle(aSource.mCounterStyle),
696 mImageRegion(aSource.mImageRegion)
698 SetListStyleImage(aSource.GetListStyleImage());
699 MOZ_COUNT_CTOR(nsStyleList);
702 nsChangeHint nsStyleList::CalcDifference(const nsStyleList& aOther) const
704 if (mListStylePosition != aOther.mListStylePosition)
705 return NS_STYLE_HINT_FRAMECHANGE;
706 if (EqualImages(mListStyleImage, aOther.mListStyleImage) &&
707 mCounterStyle == aOther.mCounterStyle) {
708 if (mImageRegion.IsEqualInterior(aOther.mImageRegion)) {
709 if (mListStyleType != aOther.mListStyleType)
710 return nsChangeHint_NeutralChange;
711 return NS_STYLE_HINT_NONE;
713 if (mImageRegion.width == aOther.mImageRegion.width &&
714 mImageRegion.height == aOther.mImageRegion.height)
715 return NS_STYLE_HINT_VISUAL;
717 return NS_STYLE_HINT_REFLOW;
720 // --------------------
721 // nsStyleXUL
723 nsStyleXUL::nsStyleXUL()
725 MOZ_COUNT_CTOR(nsStyleXUL);
726 mBoxAlign = NS_STYLE_BOX_ALIGN_STRETCH;
727 mBoxDirection = NS_STYLE_BOX_DIRECTION_NORMAL;
728 mBoxFlex = 0.0f;
729 mBoxOrient = NS_STYLE_BOX_ORIENT_HORIZONTAL;
730 mBoxPack = NS_STYLE_BOX_PACK_START;
731 mBoxOrdinal = 1;
732 mStretchStack = true;
735 nsStyleXUL::~nsStyleXUL()
737 MOZ_COUNT_DTOR(nsStyleXUL);
740 nsStyleXUL::nsStyleXUL(const nsStyleXUL& aSource)
741 : mBoxFlex(aSource.mBoxFlex)
742 , mBoxOrdinal(aSource.mBoxOrdinal)
743 , mBoxAlign(aSource.mBoxAlign)
744 , mBoxDirection(aSource.mBoxDirection)
745 , mBoxOrient(aSource.mBoxOrient)
746 , mBoxPack(aSource.mBoxPack)
747 , mStretchStack(aSource.mStretchStack)
749 MOZ_COUNT_CTOR(nsStyleXUL);
752 nsChangeHint nsStyleXUL::CalcDifference(const nsStyleXUL& aOther) const
754 if (mBoxAlign == aOther.mBoxAlign &&
755 mBoxDirection == aOther.mBoxDirection &&
756 mBoxFlex == aOther.mBoxFlex &&
757 mBoxOrient == aOther.mBoxOrient &&
758 mBoxPack == aOther.mBoxPack &&
759 mBoxOrdinal == aOther.mBoxOrdinal &&
760 mStretchStack == aOther.mStretchStack)
761 return NS_STYLE_HINT_NONE;
762 if (mBoxOrdinal != aOther.mBoxOrdinal)
763 return NS_STYLE_HINT_FRAMECHANGE;
764 return NS_STYLE_HINT_REFLOW;
767 // --------------------
768 // nsStyleColumn
770 /* static */ const uint32_t nsStyleColumn::kMaxColumnCount = 1000;
772 nsStyleColumn::nsStyleColumn(nsPresContext* aPresContext)
774 MOZ_COUNT_CTOR(nsStyleColumn);
775 mColumnCount = NS_STYLE_COLUMN_COUNT_AUTO;
776 mColumnWidth.SetAutoValue();
777 mColumnGap.SetNormalValue();
778 mColumnFill = NS_STYLE_COLUMN_FILL_BALANCE;
780 mColumnRuleWidth = (aPresContext->GetBorderWidthTable())[NS_STYLE_BORDER_WIDTH_MEDIUM];
781 mColumnRuleStyle = NS_STYLE_BORDER_STYLE_NONE;
782 mColumnRuleColor = NS_RGB(0, 0, 0);
783 mColumnRuleColorIsForeground = true;
785 mTwipsPerPixel = aPresContext->AppUnitsPerDevPixel();
788 nsStyleColumn::~nsStyleColumn()
790 MOZ_COUNT_DTOR(nsStyleColumn);
793 nsStyleColumn::nsStyleColumn(const nsStyleColumn& aSource)
794 : mColumnCount(aSource.mColumnCount)
795 , mColumnWidth(aSource.mColumnWidth)
796 , mColumnGap(aSource.mColumnGap)
797 , mColumnRuleColor(aSource.mColumnRuleColor)
798 , mColumnRuleStyle(aSource.mColumnRuleStyle)
799 , mColumnFill(aSource.mColumnFill)
800 , mColumnRuleColorIsForeground(aSource.mColumnRuleColorIsForeground)
801 , mColumnRuleWidth(aSource.mColumnRuleWidth)
802 , mTwipsPerPixel(aSource.mTwipsPerPixel)
804 MOZ_COUNT_CTOR(nsStyleColumn);
807 nsChangeHint nsStyleColumn::CalcDifference(const nsStyleColumn& aOther) const
809 if ((mColumnWidth.GetUnit() == eStyleUnit_Auto)
810 != (aOther.mColumnWidth.GetUnit() == eStyleUnit_Auto) ||
811 mColumnCount != aOther.mColumnCount)
812 // We force column count changes to do a reframe, because it's tricky to handle
813 // some edge cases where the column count gets smaller and content overflows.
814 // XXX not ideal
815 return NS_STYLE_HINT_FRAMECHANGE;
817 if (mColumnWidth != aOther.mColumnWidth ||
818 mColumnGap != aOther.mColumnGap ||
819 mColumnFill != aOther.mColumnFill)
820 return NS_STYLE_HINT_REFLOW;
822 if (GetComputedColumnRuleWidth() != aOther.GetComputedColumnRuleWidth() ||
823 mColumnRuleStyle != aOther.mColumnRuleStyle ||
824 mColumnRuleColor != aOther.mColumnRuleColor ||
825 mColumnRuleColorIsForeground != aOther.mColumnRuleColorIsForeground)
826 return NS_STYLE_HINT_VISUAL;
828 // XXX Is it right that we never check mTwipsPerPixel to return a
829 // non-nsChangeHint_NeutralChange hint?
830 if (mColumnRuleWidth != aOther.mColumnRuleWidth ||
831 mTwipsPerPixel != aOther.mTwipsPerPixel) {
832 return nsChangeHint_NeutralChange;
835 return NS_STYLE_HINT_NONE;
838 // --------------------
839 // nsStyleSVG
841 nsStyleSVG::nsStyleSVG()
843 MOZ_COUNT_CTOR(nsStyleSVG);
844 mFill.mType = eStyleSVGPaintType_Color;
845 mFill.mPaint.mColor = NS_RGB(0,0,0);
846 mFill.mFallbackColor = NS_RGB(0,0,0);
847 mStroke.mType = eStyleSVGPaintType_None;
848 mStroke.mPaint.mColor = NS_RGB(0,0,0);
849 mStroke.mFallbackColor = NS_RGB(0,0,0);
850 mStrokeDasharray = nullptr;
852 mStrokeDashoffset.SetCoordValue(0);
853 mStrokeWidth.SetCoordValue(nsPresContext::CSSPixelsToAppUnits(1));
855 mFillOpacity = 1.0f;
856 mStrokeMiterlimit = 4.0f;
857 mStrokeOpacity = 1.0f;
859 mStrokeDasharrayLength = 0;
860 mClipRule = NS_STYLE_FILL_RULE_NONZERO;
861 mColorInterpolation = NS_STYLE_COLOR_INTERPOLATION_SRGB;
862 mColorInterpolationFilters = NS_STYLE_COLOR_INTERPOLATION_LINEARRGB;
863 mFillRule = NS_STYLE_FILL_RULE_NONZERO;
864 mImageRendering = NS_STYLE_IMAGE_RENDERING_AUTO;
865 mPaintOrder = NS_STYLE_PAINT_ORDER_NORMAL;
866 mShapeRendering = NS_STYLE_SHAPE_RENDERING_AUTO;
867 mStrokeLinecap = NS_STYLE_STROKE_LINECAP_BUTT;
868 mStrokeLinejoin = NS_STYLE_STROKE_LINEJOIN_MITER;
869 mTextAnchor = NS_STYLE_TEXT_ANCHOR_START;
870 mTextRendering = NS_STYLE_TEXT_RENDERING_AUTO;
871 mFillOpacitySource = eStyleSVGOpacitySource_Normal;
872 mStrokeOpacitySource = eStyleSVGOpacitySource_Normal;
873 mStrokeDasharrayFromObject = false;
874 mStrokeDashoffsetFromObject = false;
875 mStrokeWidthFromObject = false;
878 nsStyleSVG::~nsStyleSVG()
880 MOZ_COUNT_DTOR(nsStyleSVG);
881 delete [] mStrokeDasharray;
884 nsStyleSVG::nsStyleSVG(const nsStyleSVG& aSource)
886 MOZ_COUNT_CTOR(nsStyleSVG);
887 mFill = aSource.mFill;
888 mStroke = aSource.mStroke;
890 mMarkerEnd = aSource.mMarkerEnd;
891 mMarkerMid = aSource.mMarkerMid;
892 mMarkerStart = aSource.mMarkerStart;
894 mStrokeDasharrayLength = aSource.mStrokeDasharrayLength;
895 if (aSource.mStrokeDasharray) {
896 mStrokeDasharray = new nsStyleCoord[mStrokeDasharrayLength];
897 if (mStrokeDasharray) {
898 for (size_t i = 0; i < mStrokeDasharrayLength; i++) {
899 mStrokeDasharray[i] = aSource.mStrokeDasharray[i];
901 } else {
902 mStrokeDasharrayLength = 0;
904 } else {
905 mStrokeDasharray = nullptr;
908 mStrokeDashoffset = aSource.mStrokeDashoffset;
909 mStrokeWidth = aSource.mStrokeWidth;
911 mFillOpacity = aSource.mFillOpacity;
912 mStrokeMiterlimit = aSource.mStrokeMiterlimit;
913 mStrokeOpacity = aSource.mStrokeOpacity;
915 mClipRule = aSource.mClipRule;
916 mColorInterpolation = aSource.mColorInterpolation;
917 mColorInterpolationFilters = aSource.mColorInterpolationFilters;
918 mFillRule = aSource.mFillRule;
919 mImageRendering = aSource.mImageRendering;
920 mPaintOrder = aSource.mPaintOrder;
921 mShapeRendering = aSource.mShapeRendering;
922 mStrokeLinecap = aSource.mStrokeLinecap;
923 mStrokeLinejoin = aSource.mStrokeLinejoin;
924 mTextAnchor = aSource.mTextAnchor;
925 mTextRendering = aSource.mTextRendering;
926 mFillOpacitySource = aSource.mFillOpacitySource;
927 mStrokeOpacitySource = aSource.mStrokeOpacitySource;
928 mStrokeDasharrayFromObject = aSource.mStrokeDasharrayFromObject;
929 mStrokeDashoffsetFromObject = aSource.mStrokeDashoffsetFromObject;
930 mStrokeWidthFromObject = aSource.mStrokeWidthFromObject;
933 static bool PaintURIChanged(const nsStyleSVGPaint& aPaint1,
934 const nsStyleSVGPaint& aPaint2)
936 if (aPaint1.mType != aPaint2.mType) {
937 return aPaint1.mType == eStyleSVGPaintType_Server ||
938 aPaint2.mType == eStyleSVGPaintType_Server;
940 return aPaint1.mType == eStyleSVGPaintType_Server &&
941 !EqualURIs(aPaint1.mPaint.mPaintServer, aPaint2.mPaint.mPaintServer);
944 nsChangeHint nsStyleSVG::CalcDifference(const nsStyleSVG& aOther) const
946 nsChangeHint hint = nsChangeHint(0);
948 if (!EqualURIs(mMarkerEnd, aOther.mMarkerEnd) ||
949 !EqualURIs(mMarkerMid, aOther.mMarkerMid) ||
950 !EqualURIs(mMarkerStart, aOther.mMarkerStart)) {
951 // Markers currently contribute to nsSVGPathGeometryFrame::mRect,
952 // so we need a reflow as well as a repaint. No intrinsic sizes need
953 // to change, so nsChangeHint_NeedReflow is sufficient.
954 NS_UpdateHint(hint, nsChangeHint_UpdateEffects);
955 NS_UpdateHint(hint, nsChangeHint_NeedReflow);
956 NS_UpdateHint(hint, nsChangeHint_NeedDirtyReflow); // XXX remove me: bug 876085
957 NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
958 return hint;
961 if (mFill != aOther.mFill ||
962 mStroke != aOther.mStroke ||
963 mFillOpacity != aOther.mFillOpacity ||
964 mStrokeOpacity != aOther.mStrokeOpacity) {
965 NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
966 if (HasStroke() != aOther.HasStroke() ||
967 (!HasStroke() && HasFill() != aOther.HasFill())) {
968 // Frame bounds and overflow rects depend on whether we "have" fill or
969 // stroke. Whether we have stroke or not just changed, or else we have no
970 // stroke (in which case whether we have fill or not is significant to frame
971 // bounds) and whether we have fill or not just changed. In either case we
972 // need to reflow so the frame rect is updated.
973 // XXXperf this is a waste on non nsSVGPathGeometryFrames.
974 NS_UpdateHint(hint, nsChangeHint_NeedReflow);
975 NS_UpdateHint(hint, nsChangeHint_NeedDirtyReflow); // XXX remove me: bug 876085
977 if (PaintURIChanged(mFill, aOther.mFill) ||
978 PaintURIChanged(mStroke, aOther.mStroke)) {
979 NS_UpdateHint(hint, nsChangeHint_UpdateEffects);
983 // Stroke currently contributes to nsSVGPathGeometryFrame::mRect, so
984 // we need a reflow here. No intrinsic sizes need to change, so
985 // nsChangeHint_NeedReflow is sufficient.
986 // Note that stroke-dashoffset does not affect nsSVGPathGeometryFrame::mRect.
987 // text-anchor and text-rendering changes also require a reflow since they
988 // change frames' rects.
989 if (mStrokeWidth != aOther.mStrokeWidth ||
990 mStrokeMiterlimit != aOther.mStrokeMiterlimit ||
991 mStrokeLinecap != aOther.mStrokeLinecap ||
992 mStrokeLinejoin != aOther.mStrokeLinejoin ||
993 mTextAnchor != aOther.mTextAnchor ||
994 mTextRendering != aOther.mTextRendering) {
995 NS_UpdateHint(hint, nsChangeHint_NeedReflow);
996 NS_UpdateHint(hint, nsChangeHint_NeedDirtyReflow); // XXX remove me: bug 876085
997 NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
998 return hint;
1001 if (hint & nsChangeHint_RepaintFrame) {
1002 return hint; // we don't add anything else below
1005 if ( mStrokeDashoffset != aOther.mStrokeDashoffset ||
1006 mClipRule != aOther.mClipRule ||
1007 mColorInterpolation != aOther.mColorInterpolation ||
1008 mColorInterpolationFilters != aOther.mColorInterpolationFilters ||
1009 mFillRule != aOther.mFillRule ||
1010 mImageRendering != aOther.mImageRendering ||
1011 mPaintOrder != aOther.mPaintOrder ||
1012 mShapeRendering != aOther.mShapeRendering ||
1013 mStrokeDasharrayLength != aOther.mStrokeDasharrayLength ||
1014 mFillOpacitySource != aOther.mFillOpacitySource ||
1015 mStrokeOpacitySource != aOther.mStrokeOpacitySource ||
1016 mStrokeDasharrayFromObject != aOther.mStrokeDasharrayFromObject ||
1017 mStrokeDashoffsetFromObject != aOther.mStrokeDashoffsetFromObject ||
1018 mStrokeWidthFromObject != aOther.mStrokeWidthFromObject) {
1019 NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
1020 return hint;
1023 // length of stroke dasharrays are the same (tested above) - check entries
1024 for (uint32_t i=0; i<mStrokeDasharrayLength; i++)
1025 if (mStrokeDasharray[i] != aOther.mStrokeDasharray[i]) {
1026 NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
1027 return hint;
1030 return hint;
1033 // --------------------
1034 // nsStyleClipPath
1036 nsStyleClipPath::nsStyleClipPath()
1037 : mType(NS_STYLE_CLIP_PATH_NONE)
1038 , mURL(nullptr)
1039 , mSizingBox(NS_STYLE_CLIP_SHAPE_SIZING_NOBOX)
1043 nsStyleClipPath::nsStyleClipPath(const nsStyleClipPath& aSource)
1044 : mType(NS_STYLE_CLIP_PATH_NONE)
1045 , mURL(nullptr)
1046 , mSizingBox(NS_STYLE_CLIP_SHAPE_SIZING_NOBOX)
1048 if (aSource.mType == NS_STYLE_CLIP_PATH_URL) {
1049 SetURL(aSource.mURL);
1050 } else if (aSource.mType == NS_STYLE_CLIP_PATH_SHAPE) {
1051 SetBasicShape(aSource.mBasicShape, aSource.mSizingBox);
1052 } else if (aSource.mType == NS_STYLE_CLIP_PATH_SHAPE) {
1053 SetSizingBox(aSource.mSizingBox);
1057 nsStyleClipPath::~nsStyleClipPath()
1059 ReleaseRef();
1062 nsStyleClipPath&
1063 nsStyleClipPath::operator=(const nsStyleClipPath& aOther)
1065 if (this == &aOther) {
1066 return *this;
1069 ReleaseRef();
1071 if (aOther.mType == NS_STYLE_CLIP_PATH_URL) {
1072 SetURL(aOther.mURL);
1073 } else if (aOther.mType == NS_STYLE_CLIP_PATH_SHAPE) {
1074 SetBasicShape(aOther.mBasicShape, aOther.mSizingBox);
1075 } else if (aOther.mType == NS_STYLE_CLIP_PATH_BOX) {
1076 SetSizingBox(aOther.mSizingBox);
1077 } else {
1078 mSizingBox = NS_STYLE_CLIP_SHAPE_SIZING_NOBOX;
1079 mType = NS_STYLE_CLIP_PATH_NONE;
1081 return *this;
1085 bool
1086 nsStyleClipPath::operator==(const nsStyleClipPath& aOther) const
1088 if (mType != aOther.mType) {
1089 return false;
1092 if (mType == NS_STYLE_CLIP_PATH_URL) {
1093 return EqualURIs(mURL, aOther.mURL);
1094 } else if (mType == NS_STYLE_CLIP_PATH_SHAPE) {
1095 return *mBasicShape == *aOther.mBasicShape &&
1096 mSizingBox == aOther.mSizingBox;
1097 } else if (mType == NS_STYLE_CLIP_PATH_BOX) {
1098 return mSizingBox == aOther.mSizingBox;
1101 return true;
1104 void
1105 nsStyleClipPath::ReleaseRef()
1107 if (mType == NS_STYLE_CLIP_PATH_SHAPE) {
1108 NS_ASSERTION(mBasicShape, "expected pointer");
1109 mBasicShape->Release();
1110 } else if (mType == NS_STYLE_CLIP_PATH_URL) {
1111 NS_ASSERTION(mURL, "expected pointer");
1112 mURL->Release();
1114 mURL = nullptr;
1117 void
1118 nsStyleClipPath::SetURL(nsIURI* aURL)
1120 NS_ASSERTION(aURL, "expected pointer");
1121 ReleaseRef();
1122 mURL = aURL;
1123 mURL->AddRef();
1124 mType = NS_STYLE_CLIP_PATH_URL;
1127 void
1128 nsStyleClipPath::SetBasicShape(nsStyleBasicShape* aBasicShape, uint8_t aSizingBox)
1130 NS_ASSERTION(aBasicShape, "expected pointer");
1131 ReleaseRef();
1132 mBasicShape = aBasicShape;
1133 mBasicShape->AddRef();
1134 mSizingBox = aSizingBox;
1135 mType = NS_STYLE_CLIP_PATH_SHAPE;
1138 void
1139 nsStyleClipPath::SetSizingBox(uint8_t aSizingBox)
1141 ReleaseRef();
1142 mSizingBox = aSizingBox;
1143 mType = NS_STYLE_CLIP_PATH_BOX;
1146 // --------------------
1147 // nsStyleFilter
1149 nsStyleFilter::nsStyleFilter()
1150 : mType(NS_STYLE_FILTER_NONE)
1151 , mDropShadow(nullptr)
1153 MOZ_COUNT_CTOR(nsStyleFilter);
1156 nsStyleFilter::nsStyleFilter(const nsStyleFilter& aSource)
1157 : mType(NS_STYLE_FILTER_NONE)
1158 , mDropShadow(nullptr)
1160 MOZ_COUNT_CTOR(nsStyleFilter);
1161 if (aSource.mType == NS_STYLE_FILTER_URL) {
1162 SetURL(aSource.mURL);
1163 } else if (aSource.mType == NS_STYLE_FILTER_DROP_SHADOW) {
1164 SetDropShadow(aSource.mDropShadow);
1165 } else if (aSource.mType != NS_STYLE_FILTER_NONE) {
1166 SetFilterParameter(aSource.mFilterParameter, aSource.mType);
1170 nsStyleFilter::~nsStyleFilter()
1172 ReleaseRef();
1173 MOZ_COUNT_DTOR(nsStyleFilter);
1176 nsStyleFilter&
1177 nsStyleFilter::operator=(const nsStyleFilter& aOther)
1179 if (this == &aOther)
1180 return *this;
1182 if (aOther.mType == NS_STYLE_FILTER_URL) {
1183 SetURL(aOther.mURL);
1184 } else if (aOther.mType == NS_STYLE_FILTER_DROP_SHADOW) {
1185 SetDropShadow(aOther.mDropShadow);
1186 } else if (aOther.mType != NS_STYLE_FILTER_NONE) {
1187 SetFilterParameter(aOther.mFilterParameter, aOther.mType);
1189 return *this;
1193 bool
1194 nsStyleFilter::operator==(const nsStyleFilter& aOther) const
1196 if (mType != aOther.mType) {
1197 return false;
1200 if (mType == NS_STYLE_FILTER_URL) {
1201 return EqualURIs(mURL, aOther.mURL);
1202 } else if (mType == NS_STYLE_FILTER_DROP_SHADOW) {
1203 return *mDropShadow == *aOther.mDropShadow;
1204 } else if (mType != NS_STYLE_FILTER_NONE) {
1205 return mFilterParameter == aOther.mFilterParameter;
1208 return true;
1211 void
1212 nsStyleFilter::ReleaseRef()
1214 if (mType == NS_STYLE_FILTER_DROP_SHADOW) {
1215 NS_ASSERTION(mDropShadow, "expected pointer");
1216 mDropShadow->Release();
1217 } else if (mType == NS_STYLE_FILTER_URL) {
1218 NS_ASSERTION(mURL, "expected pointer");
1219 mURL->Release();
1223 void
1224 nsStyleFilter::SetFilterParameter(const nsStyleCoord& aFilterParameter,
1225 int32_t aType)
1227 ReleaseRef();
1228 mFilterParameter = aFilterParameter;
1229 mType = aType;
1232 void
1233 nsStyleFilter::SetURL(nsIURI* aURL)
1235 NS_ASSERTION(aURL, "expected pointer");
1236 ReleaseRef();
1237 mURL = aURL;
1238 mURL->AddRef();
1239 mType = NS_STYLE_FILTER_URL;
1242 void
1243 nsStyleFilter::SetDropShadow(nsCSSShadowArray* aDropShadow)
1245 NS_ASSERTION(aDropShadow, "expected pointer");
1246 ReleaseRef();
1247 mDropShadow = aDropShadow;
1248 mDropShadow->AddRef();
1249 mType = NS_STYLE_FILTER_DROP_SHADOW;
1252 // --------------------
1253 // nsStyleSVGReset
1255 nsStyleSVGReset::nsStyleSVGReset()
1257 MOZ_COUNT_CTOR(nsStyleSVGReset);
1258 mStopColor = NS_RGB(0,0,0);
1259 mFloodColor = NS_RGB(0,0,0);
1260 mLightingColor = NS_RGB(255,255,255);
1261 mMask = nullptr;
1262 mStopOpacity = 1.0f;
1263 mFloodOpacity = 1.0f;
1264 mDominantBaseline = NS_STYLE_DOMINANT_BASELINE_AUTO;
1265 mVectorEffect = NS_STYLE_VECTOR_EFFECT_NONE;
1266 mMaskType = NS_STYLE_MASK_TYPE_LUMINANCE;
1269 nsStyleSVGReset::~nsStyleSVGReset()
1271 MOZ_COUNT_DTOR(nsStyleSVGReset);
1274 nsStyleSVGReset::nsStyleSVGReset(const nsStyleSVGReset& aSource)
1276 MOZ_COUNT_CTOR(nsStyleSVGReset);
1277 mStopColor = aSource.mStopColor;
1278 mFloodColor = aSource.mFloodColor;
1279 mLightingColor = aSource.mLightingColor;
1280 mClipPath = aSource.mClipPath;
1281 mFilters = aSource.mFilters;
1282 mMask = aSource.mMask;
1283 mStopOpacity = aSource.mStopOpacity;
1284 mFloodOpacity = aSource.mFloodOpacity;
1285 mDominantBaseline = aSource.mDominantBaseline;
1286 mVectorEffect = aSource.mVectorEffect;
1287 mMaskType = aSource.mMaskType;
1290 nsChangeHint nsStyleSVGReset::CalcDifference(const nsStyleSVGReset& aOther) const
1292 nsChangeHint hint = nsChangeHint(0);
1294 if (mClipPath != aOther.mClipPath ||
1295 !EqualURIs(mMask, aOther.mMask) ||
1296 mFilters != aOther.mFilters) {
1297 NS_UpdateHint(hint, nsChangeHint_UpdateEffects);
1298 NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
1299 // We only actually need to update the overflow area for filter
1300 // changes. However, mask and clip-path changes require that we
1301 // update the PreEffectsBBoxProperty, which is done during overflow
1302 // computation.
1303 NS_UpdateHint(hint, nsChangeHint_UpdateOverflow);
1306 if (mDominantBaseline != aOther.mDominantBaseline) {
1307 // XXXjwatt: why NS_STYLE_HINT_REFLOW? Isn't that excessive?
1308 NS_UpdateHint(hint, NS_STYLE_HINT_REFLOW);
1309 } else if (mVectorEffect != aOther.mVectorEffect) {
1310 // Stroke currently affects nsSVGPathGeometryFrame::mRect, and
1311 // vector-effect affect stroke. As a result we need to reflow if
1312 // vector-effect changes in order to have nsSVGPathGeometryFrame::
1313 // ReflowSVG called to update its mRect. No intrinsic sizes need
1314 // to change so nsChangeHint_NeedReflow is sufficient.
1315 NS_UpdateHint(hint, nsChangeHint_NeedReflow);
1316 NS_UpdateHint(hint, nsChangeHint_NeedDirtyReflow); // XXX remove me: bug 876085
1317 NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
1318 } else if (mStopColor != aOther.mStopColor ||
1319 mFloodColor != aOther.mFloodColor ||
1320 mLightingColor != aOther.mLightingColor ||
1321 mStopOpacity != aOther.mStopOpacity ||
1322 mFloodOpacity != aOther.mFloodOpacity ||
1323 mMaskType != aOther.mMaskType) {
1324 NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
1327 return hint;
1330 // nsStyleSVGPaint implementation
1331 nsStyleSVGPaint::~nsStyleSVGPaint()
1333 if (mType == eStyleSVGPaintType_Server) {
1334 NS_IF_RELEASE(mPaint.mPaintServer);
1338 void
1339 nsStyleSVGPaint::SetType(nsStyleSVGPaintType aType)
1341 if (mType == eStyleSVGPaintType_Server) {
1342 this->~nsStyleSVGPaint();
1343 new (this) nsStyleSVGPaint();
1345 mType = aType;
1348 nsStyleSVGPaint& nsStyleSVGPaint::operator=(const nsStyleSVGPaint& aOther)
1350 if (this == &aOther)
1351 return *this;
1353 SetType(aOther.mType);
1355 mFallbackColor = aOther.mFallbackColor;
1356 if (mType == eStyleSVGPaintType_Server) {
1357 mPaint.mPaintServer = aOther.mPaint.mPaintServer;
1358 NS_IF_ADDREF(mPaint.mPaintServer);
1359 } else {
1360 mPaint.mColor = aOther.mPaint.mColor;
1362 return *this;
1365 bool nsStyleSVGPaint::operator==(const nsStyleSVGPaint& aOther) const
1367 if (mType != aOther.mType)
1368 return false;
1369 if (mType == eStyleSVGPaintType_Server)
1370 return EqualURIs(mPaint.mPaintServer, aOther.mPaint.mPaintServer) &&
1371 mFallbackColor == aOther.mFallbackColor;
1372 if (mType == eStyleSVGPaintType_Color)
1373 return mPaint.mColor == aOther.mPaint.mColor;
1374 return true;
1378 // --------------------
1379 // nsStylePosition
1381 nsStylePosition::nsStylePosition(void)
1383 MOZ_COUNT_CTOR(nsStylePosition);
1385 // positioning values not inherited
1387 mObjectPosition.SetInitialPercentValues(0.5f);
1389 nsStyleCoord autoCoord(eStyleUnit_Auto);
1390 mOffset.SetLeft(autoCoord);
1391 mOffset.SetTop(autoCoord);
1392 mOffset.SetRight(autoCoord);
1393 mOffset.SetBottom(autoCoord);
1394 mWidth.SetAutoValue();
1395 mMinWidth.SetAutoValue();
1396 mMaxWidth.SetNoneValue();
1397 mHeight.SetAutoValue();
1398 mMinHeight.SetAutoValue();
1399 mMaxHeight.SetNoneValue();
1400 mFlexBasis.SetAutoValue();
1402 // The initial value of grid-auto-columns and grid-auto-rows is 'auto',
1403 // which computes to 'minmax(min-content, max-content)'.
1404 mGridAutoColumnsMin.SetIntValue(NS_STYLE_GRID_TRACK_BREADTH_MIN_CONTENT,
1405 eStyleUnit_Enumerated);
1406 mGridAutoColumnsMax.SetIntValue(NS_STYLE_GRID_TRACK_BREADTH_MAX_CONTENT,
1407 eStyleUnit_Enumerated);
1408 mGridAutoRowsMin.SetIntValue(NS_STYLE_GRID_TRACK_BREADTH_MIN_CONTENT,
1409 eStyleUnit_Enumerated);
1410 mGridAutoRowsMax.SetIntValue(NS_STYLE_GRID_TRACK_BREADTH_MAX_CONTENT,
1411 eStyleUnit_Enumerated);
1413 mGridAutoFlow = NS_STYLE_GRID_AUTO_FLOW_ROW;
1414 mBoxSizing = NS_STYLE_BOX_SIZING_CONTENT;
1415 mAlignContent = NS_STYLE_ALIGN_CONTENT_STRETCH;
1416 mAlignItems = NS_STYLE_ALIGN_ITEMS_INITIAL_VALUE;
1417 mAlignSelf = NS_STYLE_ALIGN_SELF_AUTO;
1418 mFlexDirection = NS_STYLE_FLEX_DIRECTION_ROW;
1419 mFlexWrap = NS_STYLE_FLEX_WRAP_NOWRAP;
1420 mJustifyContent = NS_STYLE_JUSTIFY_CONTENT_FLEX_START;
1421 mObjectFit = NS_STYLE_OBJECT_FIT_FILL;
1422 mOrder = NS_STYLE_ORDER_INITIAL;
1423 mFlexGrow = 0.0f;
1424 mFlexShrink = 1.0f;
1425 mZIndex.SetAutoValue();
1426 // Other members get their default constructors
1427 // which initialize them to representations of their respective initial value.
1428 // mGridTemplateAreas: nullptr for 'none'
1429 // mGridTemplate{Rows,Columns}: false and empty arrays for 'none'
1430 // mGrid{Column,Row}{Start,End}: false/0/empty values for 'auto'
1433 nsStylePosition::~nsStylePosition(void)
1435 MOZ_COUNT_DTOR(nsStylePosition);
1438 nsStylePosition::nsStylePosition(const nsStylePosition& aSource)
1439 : mObjectPosition(aSource.mObjectPosition)
1440 , mOffset(aSource.mOffset)
1441 , mWidth(aSource.mWidth)
1442 , mMinWidth(aSource.mMinWidth)
1443 , mMaxWidth(aSource.mMaxWidth)
1444 , mHeight(aSource.mHeight)
1445 , mMinHeight(aSource.mMinHeight)
1446 , mMaxHeight(aSource.mMaxHeight)
1447 , mFlexBasis(aSource.mFlexBasis)
1448 , mGridAutoColumnsMin(aSource.mGridAutoColumnsMin)
1449 , mGridAutoColumnsMax(aSource.mGridAutoColumnsMax)
1450 , mGridAutoRowsMin(aSource.mGridAutoRowsMin)
1451 , mGridAutoRowsMax(aSource.mGridAutoRowsMax)
1452 , mGridAutoFlow(aSource.mGridAutoFlow)
1453 , mBoxSizing(aSource.mBoxSizing)
1454 , mAlignContent(aSource.mAlignContent)
1455 , mAlignItems(aSource.mAlignItems)
1456 , mAlignSelf(aSource.mAlignSelf)
1457 , mFlexDirection(aSource.mFlexDirection)
1458 , mFlexWrap(aSource.mFlexWrap)
1459 , mJustifyContent(aSource.mJustifyContent)
1460 , mObjectFit(aSource.mObjectFit)
1461 , mOrder(aSource.mOrder)
1462 , mFlexGrow(aSource.mFlexGrow)
1463 , mFlexShrink(aSource.mFlexShrink)
1464 , mZIndex(aSource.mZIndex)
1465 , mGridTemplateColumns(aSource.mGridTemplateColumns)
1466 , mGridTemplateRows(aSource.mGridTemplateRows)
1467 , mGridTemplateAreas(aSource.mGridTemplateAreas)
1468 , mGridColumnStart(aSource.mGridColumnStart)
1469 , mGridColumnEnd(aSource.mGridColumnEnd)
1470 , mGridRowStart(aSource.mGridRowStart)
1471 , mGridRowEnd(aSource.mGridRowEnd)
1473 MOZ_COUNT_CTOR(nsStylePosition);
1476 static bool
1477 IsAutonessEqual(const nsStyleSides& aSides1, const nsStyleSides& aSides2)
1479 NS_FOR_CSS_SIDES(side) {
1480 if ((aSides1.GetUnit(side) == eStyleUnit_Auto) !=
1481 (aSides2.GetUnit(side) == eStyleUnit_Auto)) {
1482 return false;
1485 return true;
1488 nsChangeHint nsStylePosition::CalcDifference(const nsStylePosition& aOther) const
1490 nsChangeHint hint = nsChangeHint(0);
1492 // Changes to "z-index" require a repaint.
1493 if (mZIndex != aOther.mZIndex) {
1494 NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
1497 // Changes to "object-fit" & "object-position" require a repaint. They
1498 // may also require a reflow, if we have a nsSubDocumentFrame, so that we
1499 // can adjust the size & position of the subdocument.
1500 if (mObjectFit != aOther.mObjectFit ||
1501 mObjectPosition != aOther.mObjectPosition) {
1502 NS_UpdateHint(hint, NS_CombineHint(nsChangeHint_RepaintFrame,
1503 nsChangeHint_NeedReflow));
1506 if (mOrder != aOther.mOrder) {
1507 // "order" impacts both layout order and stacking order, so we need both a
1508 // reflow and a repaint when it changes. (Technically, we only need a
1509 // reflow if we're in a multi-line flexbox (which we can't be sure about,
1510 // since that's determined by styling on our parent) -- there, "order" can
1511 // affect which flex line we end up on, & hence can affect our sizing by
1512 // changing the group of flex items we're competing with for space.)
1513 return NS_CombineHint(hint, NS_CombineHint(nsChangeHint_RepaintFrame,
1514 nsChangeHint_AllReflowHints));
1517 if (mBoxSizing != aOther.mBoxSizing) {
1518 // Can affect both widths and heights; just a bad scene.
1519 return NS_CombineHint(hint, nsChangeHint_AllReflowHints);
1522 // Properties that apply to flex items:
1523 // XXXdholbert These should probably be more targeted (bug 819536)
1524 if (mAlignSelf != aOther.mAlignSelf ||
1525 mFlexBasis != aOther.mFlexBasis ||
1526 mFlexGrow != aOther.mFlexGrow ||
1527 mFlexShrink != aOther.mFlexShrink) {
1528 return NS_CombineHint(hint, nsChangeHint_AllReflowHints);
1531 // Properties that apply to flex containers:
1532 // - flex-direction can swap a flex container between vertical & horizontal.
1533 // - align-items can change the sizing of a flex container & the positioning
1534 // of its children.
1535 // - flex-wrap changes whether a flex container's children are wrapped, which
1536 // impacts their sizing/positioning and hence impacts the container's size.
1537 if (mAlignItems != aOther.mAlignItems ||
1538 mFlexDirection != aOther.mFlexDirection ||
1539 mFlexWrap != aOther.mFlexWrap) {
1540 return NS_CombineHint(hint, nsChangeHint_AllReflowHints);
1543 // Properties that apply to grid containers:
1544 // FIXME: only for grid containers
1545 // (ie. 'display: grid' or 'display: inline-grid')
1546 if (mGridTemplateColumns != aOther.mGridTemplateColumns ||
1547 mGridTemplateRows != aOther.mGridTemplateRows ||
1548 mGridTemplateAreas != aOther.mGridTemplateAreas ||
1549 mGridAutoColumnsMin != aOther.mGridAutoColumnsMin ||
1550 mGridAutoColumnsMax != aOther.mGridAutoColumnsMax ||
1551 mGridAutoRowsMin != aOther.mGridAutoRowsMin ||
1552 mGridAutoRowsMax != aOther.mGridAutoRowsMax ||
1553 mGridAutoFlow != aOther.mGridAutoFlow) {
1554 return NS_CombineHint(hint, nsChangeHint_AllReflowHints);
1557 // Properties that apply to grid items:
1558 // FIXME: only for grid items
1559 // (ie. parent frame is 'display: grid' or 'display: inline-grid')
1560 if (mGridColumnStart != aOther.mGridColumnStart ||
1561 mGridColumnEnd != aOther.mGridColumnEnd ||
1562 mGridRowStart != aOther.mGridRowStart ||
1563 mGridRowEnd != aOther.mGridRowEnd) {
1564 return NS_CombineHint(hint, nsChangeHint_AllReflowHints);
1567 // Changing justify-content on a flexbox might affect the positioning of its
1568 // children, but it won't affect any sizing.
1569 if (mJustifyContent != aOther.mJustifyContent) {
1570 NS_UpdateHint(hint, nsChangeHint_NeedReflow);
1573 // Properties that apply only to multi-line flex containers:
1574 // 'align-content' can change the positioning & sizing of a multi-line flex
1575 // container's children when there's extra space in the cross axis, but it
1576 // shouldn't affect the container's own sizing.
1578 // NOTE: If we get here, we know that mFlexWrap == aOther.mFlexWrap
1579 // (otherwise, we would've returned earlier). So it doesn't matter which one
1580 // of those we check to see if we're multi-line.
1581 if (mFlexWrap != NS_STYLE_FLEX_WRAP_NOWRAP &&
1582 mAlignContent != aOther.mAlignContent) {
1583 NS_UpdateHint(hint, nsChangeHint_NeedReflow);
1586 if (mHeight != aOther.mHeight ||
1587 mMinHeight != aOther.mMinHeight ||
1588 mMaxHeight != aOther.mMaxHeight) {
1589 // Height changes can affect descendant intrinsic sizes due to replaced
1590 // elements with percentage heights in descendants which also have
1591 // percentage heights. And due to our not-so-great computation of mVResize
1592 // in nsHTMLReflowState, they do need to force reflow of the whole subtree.
1593 // XXXbz due to XUL caching heights as well, height changes also need to
1594 // clear ancestor intrinsics!
1595 return NS_CombineHint(hint, nsChangeHint_AllReflowHints);
1598 if (mWidth != aOther.mWidth ||
1599 mMinWidth != aOther.mMinWidth ||
1600 mMaxWidth != aOther.mMaxWidth) {
1601 // None of our width differences can affect descendant intrinsic
1602 // sizes and none of them need to force children to reflow.
1603 return
1604 NS_CombineHint(hint,
1605 NS_SubtractHint(nsChangeHint_AllReflowHints,
1606 NS_CombineHint(nsChangeHint_ClearDescendantIntrinsics,
1607 nsChangeHint_NeedDirtyReflow)));
1610 // If width and height have not changed, but any of the offsets have changed,
1611 // then return the respective hints so that we would hopefully be able to
1612 // avoid reflowing.
1613 // Note that it is possible that we'll need to reflow when processing
1614 // restyles, but we don't have enough information to make a good decision
1615 // right now.
1616 // Don't try to handle changes between "auto" and non-auto efficiently;
1617 // that's tricky to do and will hardly ever be able to avoid a reflow.
1618 if (mOffset != aOther.mOffset) {
1619 if (IsAutonessEqual(mOffset, aOther.mOffset)) {
1620 NS_UpdateHint(hint, nsChangeHint(nsChangeHint_RecomputePosition |
1621 nsChangeHint_UpdateOverflow));
1622 } else {
1623 return NS_CombineHint(hint, nsChangeHint_AllReflowHints);
1626 return hint;
1629 /* static */ bool
1630 nsStylePosition::WidthCoordDependsOnContainer(const nsStyleCoord &aCoord)
1632 return aCoord.HasPercent() ||
1633 (aCoord.GetUnit() == eStyleUnit_Enumerated &&
1634 (aCoord.GetIntValue() == NS_STYLE_WIDTH_FIT_CONTENT ||
1635 aCoord.GetIntValue() == NS_STYLE_WIDTH_AVAILABLE));
1638 // --------------------
1639 // nsStyleTable
1642 nsStyleTable::nsStyleTable()
1644 MOZ_COUNT_CTOR(nsStyleTable);
1645 // values not inherited
1646 mLayoutStrategy = NS_STYLE_TABLE_LAYOUT_AUTO;
1647 mSpan = 1;
1650 nsStyleTable::~nsStyleTable(void)
1652 MOZ_COUNT_DTOR(nsStyleTable);
1655 nsStyleTable::nsStyleTable(const nsStyleTable& aSource)
1656 : mLayoutStrategy(aSource.mLayoutStrategy)
1657 , mSpan(aSource.mSpan)
1659 MOZ_COUNT_CTOR(nsStyleTable);
1662 nsChangeHint nsStyleTable::CalcDifference(const nsStyleTable& aOther) const
1664 if (mSpan != aOther.mSpan ||
1665 mLayoutStrategy != aOther.mLayoutStrategy)
1666 return NS_STYLE_HINT_FRAMECHANGE;
1667 return NS_STYLE_HINT_NONE;
1670 // -----------------------
1671 // nsStyleTableBorder
1673 nsStyleTableBorder::nsStyleTableBorder()
1675 MOZ_COUNT_CTOR(nsStyleTableBorder);
1676 mBorderCollapse = NS_STYLE_BORDER_SEPARATE;
1678 mEmptyCells = NS_STYLE_TABLE_EMPTY_CELLS_SHOW;
1679 mCaptionSide = NS_STYLE_CAPTION_SIDE_TOP;
1680 mBorderSpacingX = 0;
1681 mBorderSpacingY = 0;
1684 nsStyleTableBorder::~nsStyleTableBorder(void)
1686 MOZ_COUNT_DTOR(nsStyleTableBorder);
1689 nsStyleTableBorder::nsStyleTableBorder(const nsStyleTableBorder& aSource)
1690 : mBorderSpacingX(aSource.mBorderSpacingX)
1691 , mBorderSpacingY(aSource.mBorderSpacingY)
1692 , mBorderCollapse(aSource.mBorderCollapse)
1693 , mCaptionSide(aSource.mCaptionSide)
1694 , mEmptyCells(aSource.mEmptyCells)
1696 MOZ_COUNT_CTOR(nsStyleTableBorder);
1699 nsChangeHint nsStyleTableBorder::CalcDifference(const nsStyleTableBorder& aOther) const
1701 // Border-collapse changes need a reframe, because we use a different frame
1702 // class for table cells in the collapsed border model. This is used to
1703 // conserve memory when using the separated border model (collapsed borders
1704 // require extra state to be stored).
1705 if (mBorderCollapse != aOther.mBorderCollapse) {
1706 return NS_STYLE_HINT_FRAMECHANGE;
1709 if ((mCaptionSide == aOther.mCaptionSide) &&
1710 (mBorderSpacingX == aOther.mBorderSpacingX) &&
1711 (mBorderSpacingY == aOther.mBorderSpacingY)) {
1712 if (mEmptyCells == aOther.mEmptyCells)
1713 return NS_STYLE_HINT_NONE;
1714 return NS_STYLE_HINT_VISUAL;
1716 else
1717 return NS_STYLE_HINT_REFLOW;
1720 // --------------------
1721 // nsStyleColor
1724 nsStyleColor::nsStyleColor(nsPresContext* aPresContext)
1726 MOZ_COUNT_CTOR(nsStyleColor);
1727 mColor = aPresContext->DefaultColor();
1730 nsStyleColor::nsStyleColor(const nsStyleColor& aSource)
1732 MOZ_COUNT_CTOR(nsStyleColor);
1733 mColor = aSource.mColor;
1736 nsChangeHint nsStyleColor::CalcDifference(const nsStyleColor& aOther) const
1738 if (mColor == aOther.mColor)
1739 return NS_STYLE_HINT_NONE;
1740 return NS_STYLE_HINT_VISUAL;
1743 // --------------------
1744 // nsStyleGradient
1746 bool
1747 nsStyleGradient::operator==(const nsStyleGradient& aOther) const
1749 NS_ABORT_IF_FALSE(mSize == NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER ||
1750 mShape != NS_STYLE_GRADIENT_SHAPE_LINEAR,
1751 "incorrect combination of shape and size");
1752 NS_ABORT_IF_FALSE(aOther.mSize == NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER ||
1753 aOther.mShape != NS_STYLE_GRADIENT_SHAPE_LINEAR,
1754 "incorrect combination of shape and size");
1756 if (mShape != aOther.mShape ||
1757 mSize != aOther.mSize ||
1758 mRepeating != aOther.mRepeating ||
1759 mLegacySyntax != aOther.mLegacySyntax ||
1760 mBgPosX != aOther.mBgPosX ||
1761 mBgPosY != aOther.mBgPosY ||
1762 mAngle != aOther.mAngle ||
1763 mRadiusX != aOther.mRadiusX ||
1764 mRadiusY != aOther.mRadiusY)
1765 return false;
1767 if (mStops.Length() != aOther.mStops.Length())
1768 return false;
1770 for (uint32_t i = 0; i < mStops.Length(); i++) {
1771 const auto& stop1 = mStops[i];
1772 const auto& stop2 = aOther.mStops[i];
1773 if (stop1.mLocation != stop2.mLocation ||
1774 stop1.mIsInterpolationHint != stop2.mIsInterpolationHint ||
1775 (!stop1.mIsInterpolationHint && stop1.mColor != stop2.mColor))
1776 return false;
1779 return true;
1782 nsStyleGradient::nsStyleGradient(void)
1783 : mShape(NS_STYLE_GRADIENT_SHAPE_LINEAR)
1784 , mSize(NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER)
1785 , mRepeating(false)
1786 , mLegacySyntax(false)
1790 bool
1791 nsStyleGradient::IsOpaque()
1793 for (uint32_t i = 0; i < mStops.Length(); i++) {
1794 if (NS_GET_A(mStops[i].mColor) < 255)
1795 return false;
1797 return true;
1800 bool
1801 nsStyleGradient::HasCalc()
1803 for (uint32_t i = 0; i < mStops.Length(); i++) {
1804 if (mStops[i].mLocation.IsCalcUnit())
1805 return true;
1807 return mBgPosX.IsCalcUnit() || mBgPosY.IsCalcUnit() || mAngle.IsCalcUnit() ||
1808 mRadiusX.IsCalcUnit() || mRadiusY.IsCalcUnit();
1811 // --------------------
1812 // nsStyleImage
1815 nsStyleImage::nsStyleImage()
1816 : mType(eStyleImageType_Null)
1817 , mCropRect(nullptr)
1818 #ifdef DEBUG
1819 , mImageTracked(false)
1820 #endif
1822 MOZ_COUNT_CTOR(nsStyleImage);
1825 nsStyleImage::~nsStyleImage()
1827 MOZ_COUNT_DTOR(nsStyleImage);
1828 if (mType != eStyleImageType_Null)
1829 SetNull();
1832 nsStyleImage::nsStyleImage(const nsStyleImage& aOther)
1833 : mType(eStyleImageType_Null)
1834 , mCropRect(nullptr)
1835 #ifdef DEBUG
1836 , mImageTracked(false)
1837 #endif
1839 // We need our own copy constructor because we don't want
1840 // to copy the reference count
1841 MOZ_COUNT_CTOR(nsStyleImage);
1842 DoCopy(aOther);
1845 nsStyleImage&
1846 nsStyleImage::operator=(const nsStyleImage& aOther)
1848 if (this != &aOther)
1849 DoCopy(aOther);
1851 return *this;
1854 void
1855 nsStyleImage::DoCopy(const nsStyleImage& aOther)
1857 SetNull();
1859 if (aOther.mType == eStyleImageType_Image)
1860 SetImageData(aOther.mImage);
1861 else if (aOther.mType == eStyleImageType_Gradient)
1862 SetGradientData(aOther.mGradient);
1863 else if (aOther.mType == eStyleImageType_Element)
1864 SetElementId(aOther.mElementId);
1866 SetCropRect(aOther.mCropRect);
1869 void
1870 nsStyleImage::SetNull()
1872 NS_ABORT_IF_FALSE(!mImageTracked,
1873 "Calling SetNull() with image tracked!");
1875 if (mType == eStyleImageType_Gradient)
1876 mGradient->Release();
1877 else if (mType == eStyleImageType_Image)
1878 NS_RELEASE(mImage);
1879 else if (mType == eStyleImageType_Element)
1880 NS_Free(mElementId);
1882 mType = eStyleImageType_Null;
1883 mCropRect = nullptr;
1886 void
1887 nsStyleImage::SetImageData(imgRequestProxy* aImage)
1889 NS_ABORT_IF_FALSE(!mImageTracked,
1890 "Setting a new image without untracking the old one!");
1892 NS_IF_ADDREF(aImage);
1894 if (mType != eStyleImageType_Null)
1895 SetNull();
1897 if (aImage) {
1898 mImage = aImage;
1899 mType = eStyleImageType_Image;
1901 mSubImages.Clear();
1904 void
1905 nsStyleImage::TrackImage(nsPresContext* aContext)
1907 // Sanity
1908 NS_ABORT_IF_FALSE(!mImageTracked, "Already tracking image!");
1909 NS_ABORT_IF_FALSE(mType == eStyleImageType_Image,
1910 "Can't track image when there isn't one!");
1912 // Register the image with the document
1913 nsIDocument* doc = aContext->Document();
1914 if (doc)
1915 doc->AddImage(mImage);
1917 // Mark state
1918 #ifdef DEBUG
1919 mImageTracked = true;
1920 #endif
1923 void
1924 nsStyleImage::UntrackImage(nsPresContext* aContext)
1926 // Sanity
1927 NS_ABORT_IF_FALSE(mImageTracked, "Image not tracked!");
1928 NS_ABORT_IF_FALSE(mType == eStyleImageType_Image,
1929 "Can't untrack image when there isn't one!");
1931 // Unregister the image with the document
1932 nsIDocument* doc = aContext->Document();
1933 if (doc)
1934 doc->RemoveImage(mImage, nsIDocument::REQUEST_DISCARD);
1936 // Mark state
1937 #ifdef DEBUG
1938 mImageTracked = false;
1939 #endif
1942 void
1943 nsStyleImage::SetGradientData(nsStyleGradient* aGradient)
1945 if (aGradient)
1946 aGradient->AddRef();
1948 if (mType != eStyleImageType_Null)
1949 SetNull();
1951 if (aGradient) {
1952 mGradient = aGradient;
1953 mType = eStyleImageType_Gradient;
1957 void
1958 nsStyleImage::SetElementId(const char16_t* aElementId)
1960 if (mType != eStyleImageType_Null)
1961 SetNull();
1963 if (aElementId) {
1964 mElementId = NS_strdup(aElementId);
1965 mType = eStyleImageType_Element;
1969 void
1970 nsStyleImage::SetCropRect(nsStyleSides* aCropRect)
1972 if (aCropRect) {
1973 mCropRect = new nsStyleSides(*aCropRect);
1974 // There is really not much we can do if 'new' fails
1975 } else {
1976 mCropRect = nullptr;
1980 static int32_t
1981 ConvertToPixelCoord(const nsStyleCoord& aCoord, int32_t aPercentScale)
1983 double pixelValue;
1984 switch (aCoord.GetUnit()) {
1985 case eStyleUnit_Percent:
1986 pixelValue = aCoord.GetPercentValue() * aPercentScale;
1987 break;
1988 case eStyleUnit_Factor:
1989 pixelValue = aCoord.GetFactorValue();
1990 break;
1991 default:
1992 NS_NOTREACHED("unexpected unit for image crop rect");
1993 return 0;
1995 NS_ABORT_IF_FALSE(pixelValue >= 0, "we ensured non-negative while parsing");
1996 pixelValue = std::min(pixelValue, double(INT32_MAX)); // avoid overflow
1997 return NS_lround(pixelValue);
2000 bool
2001 nsStyleImage::ComputeActualCropRect(nsIntRect& aActualCropRect,
2002 bool* aIsEntireImage) const
2004 if (mType != eStyleImageType_Image)
2005 return false;
2007 nsCOMPtr<imgIContainer> imageContainer;
2008 mImage->GetImage(getter_AddRefs(imageContainer));
2009 if (!imageContainer)
2010 return false;
2012 nsIntSize imageSize;
2013 imageContainer->GetWidth(&imageSize.width);
2014 imageContainer->GetHeight(&imageSize.height);
2015 if (imageSize.width <= 0 || imageSize.height <= 0)
2016 return false;
2018 int32_t left = ConvertToPixelCoord(mCropRect->GetLeft(), imageSize.width);
2019 int32_t top = ConvertToPixelCoord(mCropRect->GetTop(), imageSize.height);
2020 int32_t right = ConvertToPixelCoord(mCropRect->GetRight(), imageSize.width);
2021 int32_t bottom = ConvertToPixelCoord(mCropRect->GetBottom(), imageSize.height);
2023 // IntersectRect() returns an empty rect if we get negative width or height
2024 nsIntRect cropRect(left, top, right - left, bottom - top);
2025 nsIntRect imageRect(nsIntPoint(0, 0), imageSize);
2026 aActualCropRect.IntersectRect(imageRect, cropRect);
2028 if (aIsEntireImage)
2029 *aIsEntireImage = aActualCropRect.IsEqualInterior(imageRect);
2030 return true;
2033 nsresult
2034 nsStyleImage::StartDecoding() const
2036 if ((mType == eStyleImageType_Image) && mImage)
2037 return mImage->StartDecoding();
2038 return NS_OK;
2041 bool
2042 nsStyleImage::IsOpaque() const
2044 if (!IsComplete())
2045 return false;
2047 if (mType == eStyleImageType_Gradient)
2048 return mGradient->IsOpaque();
2050 if (mType == eStyleImageType_Element)
2051 return false;
2053 NS_ABORT_IF_FALSE(mType == eStyleImageType_Image, "unexpected image type");
2055 nsCOMPtr<imgIContainer> imageContainer;
2056 mImage->GetImage(getter_AddRefs(imageContainer));
2057 NS_ABORT_IF_FALSE(imageContainer, "IsComplete() said image container is ready");
2059 // Check if the crop region of the image is opaque.
2060 if (imageContainer->IsOpaque()) {
2061 if (!mCropRect)
2062 return true;
2064 // Must make sure if mCropRect contains at least a pixel.
2065 // XXX Is this optimization worth it? Maybe I should just return false.
2066 nsIntRect actualCropRect;
2067 bool rv = ComputeActualCropRect(actualCropRect);
2068 NS_ASSERTION(rv, "ComputeActualCropRect() can not fail here");
2069 return rv && !actualCropRect.IsEmpty();
2072 return false;
2075 bool
2076 nsStyleImage::IsComplete() const
2078 switch (mType) {
2079 case eStyleImageType_Null:
2080 return false;
2081 case eStyleImageType_Gradient:
2082 case eStyleImageType_Element:
2083 return true;
2084 case eStyleImageType_Image:
2086 uint32_t status = imgIRequest::STATUS_ERROR;
2087 return NS_SUCCEEDED(mImage->GetImageStatus(&status)) &&
2088 (status & imgIRequest::STATUS_SIZE_AVAILABLE) &&
2089 (status & imgIRequest::STATUS_FRAME_COMPLETE);
2091 default:
2092 NS_NOTREACHED("unexpected image type");
2093 return false;
2097 bool
2098 nsStyleImage::IsLoaded() const
2100 switch (mType) {
2101 case eStyleImageType_Null:
2102 return false;
2103 case eStyleImageType_Gradient:
2104 case eStyleImageType_Element:
2105 return true;
2106 case eStyleImageType_Image:
2108 uint32_t status = imgIRequest::STATUS_ERROR;
2109 return NS_SUCCEEDED(mImage->GetImageStatus(&status)) &&
2110 !(status & imgIRequest::STATUS_ERROR) &&
2111 (status & imgIRequest::STATUS_LOAD_COMPLETE);
2113 default:
2114 NS_NOTREACHED("unexpected image type");
2115 return false;
2119 static inline bool
2120 EqualRects(const nsStyleSides* aRect1, const nsStyleSides* aRect2)
2122 return aRect1 == aRect2 || /* handles null== null, and optimize */
2123 (aRect1 && aRect2 && *aRect1 == *aRect2);
2126 bool
2127 nsStyleImage::operator==(const nsStyleImage& aOther) const
2129 if (mType != aOther.mType)
2130 return false;
2132 if (!EqualRects(mCropRect, aOther.mCropRect))
2133 return false;
2135 if (mType == eStyleImageType_Image)
2136 return EqualImages(mImage, aOther.mImage);
2138 if (mType == eStyleImageType_Gradient)
2139 return *mGradient == *aOther.mGradient;
2141 if (mType == eStyleImageType_Element)
2142 return NS_strcmp(mElementId, aOther.mElementId) == 0;
2144 return true;
2147 // --------------------
2148 // nsStyleBackground
2151 nsStyleBackground::nsStyleBackground()
2152 : mAttachmentCount(1)
2153 , mClipCount(1)
2154 , mOriginCount(1)
2155 , mRepeatCount(1)
2156 , mPositionCount(1)
2157 , mImageCount(1)
2158 , mSizeCount(1)
2159 , mBlendModeCount(1)
2160 , mBackgroundColor(NS_RGBA(0, 0, 0, 0))
2162 MOZ_COUNT_CTOR(nsStyleBackground);
2163 Layer *onlyLayer = mLayers.AppendElement();
2164 NS_ASSERTION(onlyLayer, "auto array must have room for 1 element");
2165 onlyLayer->SetInitialValues();
2168 nsStyleBackground::nsStyleBackground(const nsStyleBackground& aSource)
2169 : mAttachmentCount(aSource.mAttachmentCount)
2170 , mClipCount(aSource.mClipCount)
2171 , mOriginCount(aSource.mOriginCount)
2172 , mRepeatCount(aSource.mRepeatCount)
2173 , mPositionCount(aSource.mPositionCount)
2174 , mImageCount(aSource.mImageCount)
2175 , mSizeCount(aSource.mSizeCount)
2176 , mBlendModeCount(aSource.mBlendModeCount)
2177 , mLayers(aSource.mLayers) // deep copy
2178 , mBackgroundColor(aSource.mBackgroundColor)
2180 MOZ_COUNT_CTOR(nsStyleBackground);
2181 // If the deep copy of mLayers failed, truncate the counts.
2182 uint32_t count = mLayers.Length();
2183 if (count != aSource.mLayers.Length()) {
2184 NS_WARNING("truncating counts due to out-of-memory");
2185 mAttachmentCount = std::max(mAttachmentCount, count);
2186 mClipCount = std::max(mClipCount, count);
2187 mOriginCount = std::max(mOriginCount, count);
2188 mRepeatCount = std::max(mRepeatCount, count);
2189 mPositionCount = std::max(mPositionCount, count);
2190 mImageCount = std::max(mImageCount, count);
2191 mSizeCount = std::max(mSizeCount, count);
2192 mBlendModeCount = std::max(mSizeCount, count);
2196 nsStyleBackground::~nsStyleBackground()
2198 MOZ_COUNT_DTOR(nsStyleBackground);
2201 void
2202 nsStyleBackground::Destroy(nsPresContext* aContext)
2204 // Untrack all the images stored in our layers
2205 for (uint32_t i = 0; i < mImageCount; ++i)
2206 mLayers[i].UntrackImages(aContext);
2208 this->~nsStyleBackground();
2209 aContext->PresShell()->
2210 FreeByObjectID(nsPresArena::nsStyleBackground_id, this);
2213 nsChangeHint nsStyleBackground::CalcDifference(const nsStyleBackground& aOther) const
2215 const nsStyleBackground* moreLayers =
2216 mImageCount > aOther.mImageCount ? this : &aOther;
2217 const nsStyleBackground* lessLayers =
2218 mImageCount > aOther.mImageCount ? &aOther : this;
2220 bool hasVisualDifference = false;
2222 NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, moreLayers) {
2223 if (i < lessLayers->mImageCount) {
2224 if (moreLayers->mLayers[i] != lessLayers->mLayers[i]) {
2225 if ((moreLayers->mLayers[i].mImage.GetType() == eStyleImageType_Element) ||
2226 (lessLayers->mLayers[i].mImage.GetType() == eStyleImageType_Element))
2227 return NS_CombineHint(nsChangeHint_UpdateEffects, NS_STYLE_HINT_VISUAL);
2228 hasVisualDifference = true;
2230 } else {
2231 if (moreLayers->mLayers[i].mImage.GetType() == eStyleImageType_Element)
2232 return NS_CombineHint(nsChangeHint_UpdateEffects, NS_STYLE_HINT_VISUAL);
2233 hasVisualDifference = true;
2237 if (hasVisualDifference || mBackgroundColor != aOther.mBackgroundColor)
2238 return NS_STYLE_HINT_VISUAL;
2240 if (mAttachmentCount != aOther.mAttachmentCount ||
2241 mClipCount != aOther.mClipCount ||
2242 mOriginCount != aOther.mOriginCount ||
2243 mRepeatCount != aOther.mRepeatCount ||
2244 mPositionCount != aOther.mPositionCount ||
2245 mSizeCount != aOther.mSizeCount) {
2246 return nsChangeHint_NeutralChange;
2249 return NS_STYLE_HINT_NONE;
2252 bool nsStyleBackground::HasFixedBackground() const
2254 NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, this) {
2255 const Layer &layer = mLayers[i];
2256 if (layer.mAttachment == NS_STYLE_BG_ATTACHMENT_FIXED &&
2257 !layer.mImage.IsEmpty()) {
2258 return true;
2261 return false;
2264 bool nsStyleBackground::IsTransparent() const
2266 return BottomLayer().mImage.IsEmpty() &&
2267 mImageCount == 1 &&
2268 NS_GET_A(mBackgroundColor) == 0;
2271 void
2272 nsStyleBackground::Position::SetInitialPercentValues(float aPercentVal)
2274 mXPosition.mPercent = aPercentVal;
2275 mXPosition.mLength = 0;
2276 mXPosition.mHasPercent = true;
2277 mYPosition.mPercent = aPercentVal;
2278 mYPosition.mLength = 0;
2279 mYPosition.mHasPercent = true;
2282 bool
2283 nsStyleBackground::Size::DependsOnPositioningAreaSize(const nsStyleImage& aImage) const
2285 NS_ABORT_IF_FALSE(aImage.GetType() != eStyleImageType_Null,
2286 "caller should have handled this");
2288 // If either dimension contains a non-zero percentage, rendering for that
2289 // dimension straightforwardly depends on frame size.
2290 if ((mWidthType == eLengthPercentage && mWidth.mPercent != 0.0f) ||
2291 (mHeightType == eLengthPercentage && mHeight.mPercent != 0.0f)) {
2292 return true;
2295 // So too for contain and cover.
2296 if (mWidthType == eContain || mWidthType == eCover) {
2297 return true;
2300 // If both dimensions are fixed lengths, there's no dependency.
2301 if (mWidthType == eLengthPercentage && mHeightType == eLengthPercentage) {
2302 return false;
2305 NS_ABORT_IF_FALSE((mWidthType == eLengthPercentage && mHeightType == eAuto) ||
2306 (mWidthType == eAuto && mHeightType == eLengthPercentage) ||
2307 (mWidthType == eAuto && mHeightType == eAuto),
2308 "logic error");
2310 nsStyleImageType type = aImage.GetType();
2312 // Gradient rendering depends on frame size when auto is involved because
2313 // gradients have no intrinsic ratio or dimensions, and therefore the relevant
2314 // dimension is "treat[ed] as 100%".
2315 if (type == eStyleImageType_Gradient) {
2316 return true;
2319 // XXX Element rendering for auto or fixed length doesn't depend on frame size
2320 // according to the spec. However, we don't implement the spec yet, so
2321 // for now we bail and say element() plus auto affects ultimate size.
2322 if (type == eStyleImageType_Element) {
2323 return true;
2326 if (type == eStyleImageType_Image) {
2327 nsCOMPtr<imgIContainer> imgContainer;
2328 aImage.GetImageData()->GetImage(getter_AddRefs(imgContainer));
2329 if (imgContainer) {
2330 nsIntSize imageSize;
2331 nsSize imageRatio;
2332 bool hasWidth, hasHeight;
2333 nsLayoutUtils::ComputeSizeForDrawing(imgContainer, imageSize, imageRatio,
2334 hasWidth, hasHeight);
2336 // If the image has a fixed width and height, rendering never depends on
2337 // the frame size.
2338 if (hasWidth && hasHeight) {
2339 return false;
2342 // If the image has an intrinsic ratio, rendering will depend on frame
2343 // size when background-size is all auto.
2344 if (imageRatio != nsSize(0, 0)) {
2345 return mWidthType == mHeightType;
2348 // Otherwise, rendering depends on frame size when the image dimensions
2349 // and background-size don't complement each other.
2350 return !(hasWidth && mHeightType == eLengthPercentage) &&
2351 !(hasHeight && mWidthType == eLengthPercentage);
2353 } else {
2354 NS_NOTREACHED("missed an enum value");
2357 // Passed the gauntlet: no dependency.
2358 return false;
2361 void
2362 nsStyleBackground::Size::SetInitialValues()
2364 mWidthType = mHeightType = eAuto;
2367 bool
2368 nsStyleBackground::Size::operator==(const Size& aOther) const
2370 NS_ABORT_IF_FALSE(mWidthType < eDimensionType_COUNT,
2371 "bad mWidthType for this");
2372 NS_ABORT_IF_FALSE(mHeightType < eDimensionType_COUNT,
2373 "bad mHeightType for this");
2374 NS_ABORT_IF_FALSE(aOther.mWidthType < eDimensionType_COUNT,
2375 "bad mWidthType for aOther");
2376 NS_ABORT_IF_FALSE(aOther.mHeightType < eDimensionType_COUNT,
2377 "bad mHeightType for aOther");
2379 return mWidthType == aOther.mWidthType &&
2380 mHeightType == aOther.mHeightType &&
2381 (mWidthType != eLengthPercentage || mWidth == aOther.mWidth) &&
2382 (mHeightType != eLengthPercentage || mHeight == aOther.mHeight);
2385 void
2386 nsStyleBackground::Repeat::SetInitialValues()
2388 mXRepeat = NS_STYLE_BG_REPEAT_REPEAT;
2389 mYRepeat = NS_STYLE_BG_REPEAT_REPEAT;
2392 nsStyleBackground::Layer::Layer()
2396 nsStyleBackground::Layer::~Layer()
2400 void
2401 nsStyleBackground::Layer::SetInitialValues()
2403 mAttachment = NS_STYLE_BG_ATTACHMENT_SCROLL;
2404 mClip = NS_STYLE_BG_CLIP_BORDER;
2405 mOrigin = NS_STYLE_BG_ORIGIN_PADDING;
2406 mRepeat.SetInitialValues();
2407 mBlendMode = NS_STYLE_BLEND_NORMAL;
2408 mPosition.SetInitialPercentValues(0.0f); // Initial value is "0% 0%"
2409 mSize.SetInitialValues();
2410 mImage.SetNull();
2413 bool
2414 nsStyleBackground::Layer::RenderingMightDependOnPositioningAreaSizeChange() const
2416 // Do we even have an image?
2417 if (mImage.IsEmpty()) {
2418 return false;
2421 return mPosition.DependsOnPositioningAreaSize() ||
2422 mSize.DependsOnPositioningAreaSize(mImage);
2425 bool
2426 nsStyleBackground::Layer::operator==(const Layer& aOther) const
2428 return mAttachment == aOther.mAttachment &&
2429 mClip == aOther.mClip &&
2430 mOrigin == aOther.mOrigin &&
2431 mRepeat == aOther.mRepeat &&
2432 mBlendMode == aOther.mBlendMode &&
2433 mPosition == aOther.mPosition &&
2434 mSize == aOther.mSize &&
2435 mImage == aOther.mImage;
2438 // --------------------
2439 // nsStyleDisplay
2441 void nsTimingFunction::AssignFromKeyword(int32_t aTimingFunctionType)
2443 switch (aTimingFunctionType) {
2444 case NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_START:
2445 mType = StepStart;
2446 mSteps = 1;
2447 return;
2448 case NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END:
2449 mType = StepEnd;
2450 mSteps = 1;
2451 return;
2452 default:
2453 mType = Function;
2454 break;
2457 static_assert(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE == 0 &&
2458 NS_STYLE_TRANSITION_TIMING_FUNCTION_LINEAR == 1 &&
2459 NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE_IN == 2 &&
2460 NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE_OUT == 3 &&
2461 NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE_IN_OUT == 4,
2462 "transition timing function constants not as expected");
2464 static const float timingFunctionValues[5][4] = {
2465 { 0.25f, 0.10f, 0.25f, 1.00f }, // ease
2466 { 0.00f, 0.00f, 1.00f, 1.00f }, // linear
2467 { 0.42f, 0.00f, 1.00f, 1.00f }, // ease-in
2468 { 0.00f, 0.00f, 0.58f, 1.00f }, // ease-out
2469 { 0.42f, 0.00f, 0.58f, 1.00f } // ease-in-out
2472 NS_ABORT_IF_FALSE(0 <= aTimingFunctionType && aTimingFunctionType < 5,
2473 "keyword out of range");
2474 mFunc.mX1 = timingFunctionValues[aTimingFunctionType][0];
2475 mFunc.mY1 = timingFunctionValues[aTimingFunctionType][1];
2476 mFunc.mX2 = timingFunctionValues[aTimingFunctionType][2];
2477 mFunc.mY2 = timingFunctionValues[aTimingFunctionType][3];
2480 mozilla::StyleTransition::StyleTransition(const StyleTransition& aCopy)
2481 : mTimingFunction(aCopy.mTimingFunction)
2482 , mDuration(aCopy.mDuration)
2483 , mDelay(aCopy.mDelay)
2484 , mProperty(aCopy.mProperty)
2485 , mUnknownProperty(aCopy.mUnknownProperty)
2489 void
2490 mozilla::StyleTransition::SetInitialValues()
2492 mTimingFunction = nsTimingFunction(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE);
2493 mDuration = 0.0;
2494 mDelay = 0.0;
2495 mProperty = eCSSPropertyExtra_all_properties;
2498 void
2499 mozilla::StyleTransition::SetUnknownProperty(const nsAString& aUnknownProperty)
2501 NS_ASSERTION(nsCSSProps::LookupProperty(aUnknownProperty,
2502 nsCSSProps::eEnabledForAllContent) ==
2503 eCSSProperty_UNKNOWN,
2504 "should be unknown property");
2505 mProperty = eCSSProperty_UNKNOWN;
2506 mUnknownProperty = do_GetAtom(aUnknownProperty);
2509 bool
2510 mozilla::StyleTransition::operator==(const mozilla::StyleTransition& aOther) const
2512 return mTimingFunction == aOther.mTimingFunction &&
2513 mDuration == aOther.mDuration &&
2514 mDelay == aOther.mDelay &&
2515 mProperty == aOther.mProperty &&
2516 (mProperty != eCSSProperty_UNKNOWN ||
2517 mUnknownProperty == aOther.mUnknownProperty);
2520 mozilla::StyleAnimation::StyleAnimation(const mozilla::StyleAnimation& aCopy)
2521 : mTimingFunction(aCopy.mTimingFunction)
2522 , mDuration(aCopy.mDuration)
2523 , mDelay(aCopy.mDelay)
2524 , mName(aCopy.mName)
2525 , mDirection(aCopy.mDirection)
2526 , mFillMode(aCopy.mFillMode)
2527 , mPlayState(aCopy.mPlayState)
2528 , mIterationCount(aCopy.mIterationCount)
2532 void
2533 mozilla::StyleAnimation::SetInitialValues()
2535 mTimingFunction = nsTimingFunction(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE);
2536 mDuration = 0.0;
2537 mDelay = 0.0;
2538 mName = EmptyString();
2539 mDirection = NS_STYLE_ANIMATION_DIRECTION_NORMAL;
2540 mFillMode = NS_STYLE_ANIMATION_FILL_MODE_NONE;
2541 mPlayState = NS_STYLE_ANIMATION_PLAY_STATE_RUNNING;
2542 mIterationCount = 1.0f;
2545 bool
2546 mozilla::StyleAnimation::operator==(const mozilla::StyleAnimation& aOther) const
2548 return mTimingFunction == aOther.mTimingFunction &&
2549 mDuration == aOther.mDuration &&
2550 mDelay == aOther.mDelay &&
2551 mName == aOther.mName &&
2552 mDirection == aOther.mDirection &&
2553 mFillMode == aOther.mFillMode &&
2554 mPlayState == aOther.mPlayState &&
2555 mIterationCount == aOther.mIterationCount;
2558 nsStyleDisplay::nsStyleDisplay()
2559 : mWillChangeBitField(0)
2561 MOZ_COUNT_CTOR(nsStyleDisplay);
2562 mAppearance = NS_THEME_NONE;
2563 mDisplay = NS_STYLE_DISPLAY_INLINE;
2564 mOriginalDisplay = mDisplay;
2565 mPosition = NS_STYLE_POSITION_STATIC;
2566 mFloats = NS_STYLE_FLOAT_NONE;
2567 mOriginalFloats = mFloats;
2568 mBreakType = NS_STYLE_CLEAR_NONE;
2569 mBreakInside = NS_STYLE_PAGE_BREAK_AUTO;
2570 mBreakBefore = false;
2571 mBreakAfter = false;
2572 mOverflowX = NS_STYLE_OVERFLOW_VISIBLE;
2573 mOverflowY = NS_STYLE_OVERFLOW_VISIBLE;
2574 mOverflowClipBox = NS_STYLE_OVERFLOW_CLIP_BOX_PADDING_BOX;
2575 mResize = NS_STYLE_RESIZE_NONE;
2576 mClipFlags = NS_STYLE_CLIP_AUTO;
2577 mClip.SetRect(0,0,0,0);
2578 mOpacity = 1.0f;
2579 mSpecifiedTransform = nullptr;
2580 mTransformOrigin[0].SetPercentValue(0.5f); // Transform is centered on origin
2581 mTransformOrigin[1].SetPercentValue(0.5f);
2582 mTransformOrigin[2].SetCoordValue(0);
2583 mPerspectiveOrigin[0].SetPercentValue(0.5f);
2584 mPerspectiveOrigin[1].SetPercentValue(0.5f);
2585 mChildPerspective.SetNoneValue();
2586 mBackfaceVisibility = NS_STYLE_BACKFACE_VISIBILITY_VISIBLE;
2587 mTransformStyle = NS_STYLE_TRANSFORM_STYLE_FLAT;
2588 mOrient = NS_STYLE_ORIENT_AUTO;
2589 mMixBlendMode = NS_STYLE_BLEND_NORMAL;
2590 mIsolation = NS_STYLE_ISOLATION_AUTO;
2591 mTouchAction = NS_STYLE_TOUCH_ACTION_AUTO;
2592 mScrollBehavior = NS_STYLE_SCROLL_BEHAVIOR_AUTO;
2594 mTransitions.AppendElement();
2595 NS_ABORT_IF_FALSE(mTransitions.Length() == 1,
2596 "appending within auto buffer should never fail");
2597 mTransitions[0].SetInitialValues();
2598 mTransitionTimingFunctionCount = 1;
2599 mTransitionDurationCount = 1;
2600 mTransitionDelayCount = 1;
2601 mTransitionPropertyCount = 1;
2603 mAnimations.AppendElement();
2604 NS_ABORT_IF_FALSE(mAnimations.Length() == 1,
2605 "appending within auto buffer should never fail");
2606 mAnimations[0].SetInitialValues();
2607 mAnimationTimingFunctionCount = 1;
2608 mAnimationDurationCount = 1;
2609 mAnimationDelayCount = 1;
2610 mAnimationNameCount = 1;
2611 mAnimationDirectionCount = 1;
2612 mAnimationFillModeCount = 1;
2613 mAnimationPlayStateCount = 1;
2614 mAnimationIterationCountCount = 1;
2617 nsStyleDisplay::nsStyleDisplay(const nsStyleDisplay& aSource)
2618 : mBinding(aSource.mBinding)
2619 , mClip(aSource.mClip)
2620 , mOpacity(aSource.mOpacity)
2621 , mDisplay(aSource.mDisplay)
2622 , mOriginalDisplay(aSource.mOriginalDisplay)
2623 , mAppearance(aSource.mAppearance)
2624 , mPosition(aSource.mPosition)
2625 , mFloats(aSource.mFloats)
2626 , mOriginalFloats(aSource.mOriginalFloats)
2627 , mBreakType(aSource.mBreakType)
2628 , mBreakInside(aSource.mBreakInside)
2629 , mBreakBefore(aSource.mBreakBefore)
2630 , mBreakAfter(aSource.mBreakAfter)
2631 , mOverflowX(aSource.mOverflowX)
2632 , mOverflowY(aSource.mOverflowY)
2633 , mOverflowClipBox(aSource.mOverflowClipBox)
2634 , mResize(aSource.mResize)
2635 , mClipFlags(aSource.mClipFlags)
2636 , mOrient(aSource.mOrient)
2637 , mMixBlendMode(aSource.mMixBlendMode)
2638 , mIsolation(aSource.mIsolation)
2639 , mWillChangeBitField(aSource.mWillChangeBitField)
2640 , mWillChange(aSource.mWillChange)
2641 , mTouchAction(aSource.mTouchAction)
2642 , mScrollBehavior(aSource.mScrollBehavior)
2643 , mBackfaceVisibility(aSource.mBackfaceVisibility)
2644 , mTransformStyle(aSource.mTransformStyle)
2645 , mSpecifiedTransform(aSource.mSpecifiedTransform)
2646 , mChildPerspective(aSource.mChildPerspective)
2647 , mTransitions(aSource.mTransitions)
2648 , mTransitionTimingFunctionCount(aSource.mTransitionTimingFunctionCount)
2649 , mTransitionDurationCount(aSource.mTransitionDurationCount)
2650 , mTransitionDelayCount(aSource.mTransitionDelayCount)
2651 , mTransitionPropertyCount(aSource.mTransitionPropertyCount)
2652 , mAnimations(aSource.mAnimations)
2653 , mAnimationTimingFunctionCount(aSource.mAnimationTimingFunctionCount)
2654 , mAnimationDurationCount(aSource.mAnimationDurationCount)
2655 , mAnimationDelayCount(aSource.mAnimationDelayCount)
2656 , mAnimationNameCount(aSource.mAnimationNameCount)
2657 , mAnimationDirectionCount(aSource.mAnimationDirectionCount)
2658 , mAnimationFillModeCount(aSource.mAnimationFillModeCount)
2659 , mAnimationPlayStateCount(aSource.mAnimationPlayStateCount)
2660 , mAnimationIterationCountCount(aSource.mAnimationIterationCountCount)
2662 MOZ_COUNT_CTOR(nsStyleDisplay);
2664 /* Copy over transform origin. */
2665 mTransformOrigin[0] = aSource.mTransformOrigin[0];
2666 mTransformOrigin[1] = aSource.mTransformOrigin[1];
2667 mTransformOrigin[2] = aSource.mTransformOrigin[2];
2668 mPerspectiveOrigin[0] = aSource.mPerspectiveOrigin[0];
2669 mPerspectiveOrigin[1] = aSource.mPerspectiveOrigin[1];
2672 nsChangeHint nsStyleDisplay::CalcDifference(const nsStyleDisplay& aOther) const
2674 nsChangeHint hint = nsChangeHint(0);
2676 if (!EqualURIs(mBinding, aOther.mBinding)
2677 || mPosition != aOther.mPosition
2678 || mDisplay != aOther.mDisplay
2679 || (mFloats == NS_STYLE_FLOAT_NONE) != (aOther.mFloats == NS_STYLE_FLOAT_NONE)
2680 || mOverflowX != aOther.mOverflowX
2681 || mOverflowY != aOther.mOverflowY
2682 || mScrollBehavior != aOther.mScrollBehavior
2683 || mResize != aOther.mResize)
2684 NS_UpdateHint(hint, nsChangeHint_ReconstructFrame);
2686 /* Note: When mScrollBehavior is changed, the nsChangeHint_NeutralChange is
2687 * not sufficient to enter nsCSSFrameConstructor::PropagateScrollToViewport.
2688 * By using the same hint as used when the overflow css property changes,
2689 * nsChangeHint_ReconstructFrame, PropagateScrollToViewport will be called.
2691 * The scroll-behavior css property is not expected to change often (the
2692 * CSSOM-View DOM methods are likely to be used in those cases); however,
2693 * if this does become common perhaps a faster-path might be worth while.
2696 if ((mAppearance == NS_THEME_TEXTFIELD &&
2697 aOther.mAppearance != NS_THEME_TEXTFIELD) ||
2698 (mAppearance != NS_THEME_TEXTFIELD &&
2699 aOther.mAppearance == NS_THEME_TEXTFIELD)) {
2700 // This is for <input type=number> where we allow authors to specify a
2701 // |-moz-appearance:textfield| to get a control without a spinner. (The
2702 // spinner is present for |-moz-appearance:number-input| but also other
2703 // values such as 'none'.) We need to reframe since we want to use
2704 // nsTextControlFrame instead of nsNumberControlFrame if the author
2705 // specifies 'textfield'.
2706 return nsChangeHint_ReconstructFrame;
2709 if (mFloats != aOther.mFloats) {
2710 // Changing which side we float on doesn't affect descendants directly
2711 NS_UpdateHint(hint,
2712 NS_SubtractHint(nsChangeHint_AllReflowHints,
2713 NS_CombineHint(nsChangeHint_ClearDescendantIntrinsics,
2714 nsChangeHint_NeedDirtyReflow)));
2717 // XXX the following is conservative, for now: changing float breaking shouldn't
2718 // necessarily require a repaint, reflow should suffice.
2719 if (mBreakType != aOther.mBreakType
2720 || mBreakInside != aOther.mBreakInside
2721 || mBreakBefore != aOther.mBreakBefore
2722 || mBreakAfter != aOther.mBreakAfter
2723 || mAppearance != aOther.mAppearance
2724 || mOrient != aOther.mOrient
2725 || mOverflowClipBox != aOther.mOverflowClipBox
2726 || mClipFlags != aOther.mClipFlags)
2727 NS_UpdateHint(hint, NS_CombineHint(nsChangeHint_AllReflowHints,
2728 nsChangeHint_RepaintFrame));
2730 if (!mClip.IsEqualInterior(aOther.mClip)) {
2731 // If the clip has changed, we just need to update overflow areas. DLBI
2732 // will handle the invalidation.
2733 NS_UpdateHint(hint, NS_CombineHint(nsChangeHint_UpdateOverflow,
2734 nsChangeHint_SchedulePaint));
2737 if (mOpacity != aOther.mOpacity) {
2738 // If we're going from the optimized >=0.99 opacity value to 1.0 or back, then
2739 // repaint the frame because DLBI will not catch the invalidation. Otherwise,
2740 // just update the opacity layer.
2741 if ((mOpacity >= 0.99f && mOpacity < 1.0f && aOther.mOpacity == 1.0f) ||
2742 (aOther.mOpacity >= 0.99f && aOther.mOpacity < 1.0f && mOpacity == 1.0f)) {
2743 NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
2744 } else {
2745 NS_UpdateHint(hint, nsChangeHint_UpdateOpacityLayer);
2749 if (mMixBlendMode != aOther.mMixBlendMode
2750 || mIsolation != aOther.mIsolation) {
2751 NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
2754 /* If we've added or removed the transform property, we need to reconstruct the frame to add
2755 * or remove the view object, and also to handle abs-pos and fixed-pos containers.
2757 if (HasTransformStyle() != aOther.HasTransformStyle()) {
2758 // We do not need to apply nsChangeHint_UpdateTransformLayer since
2759 // nsChangeHint_RepaintFrame will forcibly invalidate the frame area and
2760 // ensure layers are rebuilt (or removed).
2761 NS_UpdateHint(hint, NS_CombineHint(nsChangeHint_AddOrRemoveTransform,
2762 NS_CombineHint(nsChangeHint_UpdateOverflow,
2763 nsChangeHint_RepaintFrame)));
2764 } else {
2765 /* Otherwise, if we've kept the property lying around and we already had a
2766 * transform, we need to see whether or not we've changed the transform.
2767 * If so, we need to recompute its overflow rect (which probably changed
2768 * if the transform changed) and to redraw within the bounds of that new
2769 * overflow rect.
2771 * If the property isn't present in either style struct, we still do the
2772 * comparisons but turn all the resulting change hints into
2773 * nsChangeHint_NeutralChange.
2775 nsChangeHint transformHint = nsChangeHint(0);
2777 if (!mSpecifiedTransform != !aOther.mSpecifiedTransform ||
2778 (mSpecifiedTransform &&
2779 *mSpecifiedTransform != *aOther.mSpecifiedTransform)) {
2780 NS_UpdateHint(transformHint, nsChangeHint_UpdateTransformLayer);
2782 if (mSpecifiedTransform &&
2783 aOther.mSpecifiedTransform) {
2784 NS_UpdateHint(transformHint, nsChangeHint_UpdatePostTransformOverflow);
2785 } else {
2786 NS_UpdateHint(transformHint, nsChangeHint_UpdateOverflow);
2790 const nsChangeHint kUpdateOverflowAndRepaintHint =
2791 NS_CombineHint(nsChangeHint_UpdateOverflow, nsChangeHint_RepaintFrame);
2792 for (uint8_t index = 0; index < 3; ++index)
2793 if (mTransformOrigin[index] != aOther.mTransformOrigin[index]) {
2794 NS_UpdateHint(transformHint, kUpdateOverflowAndRepaintHint);
2795 break;
2798 for (uint8_t index = 0; index < 2; ++index)
2799 if (mPerspectiveOrigin[index] != aOther.mPerspectiveOrigin[index]) {
2800 NS_UpdateHint(transformHint, kUpdateOverflowAndRepaintHint);
2801 break;
2804 if (mChildPerspective != aOther.mChildPerspective ||
2805 mTransformStyle != aOther.mTransformStyle)
2806 NS_UpdateHint(transformHint, kUpdateOverflowAndRepaintHint);
2808 if (mBackfaceVisibility != aOther.mBackfaceVisibility)
2809 NS_UpdateHint(transformHint, nsChangeHint_RepaintFrame);
2811 if (transformHint) {
2812 if (HasTransformStyle()) {
2813 NS_UpdateHint(hint, transformHint);
2814 } else {
2815 NS_UpdateHint(hint, nsChangeHint_NeutralChange);
2820 // Note that the HasTransformStyle() != aOther.HasTransformStyle()
2821 // test above handles relevant changes in the
2822 // NS_STYLE_WILL_CHANGE_TRANSFORM bit, which in turn handles frame
2823 // reconstruction for changes in the containing block of
2824 // fixed-positioned elements. Other than that, all changes to
2825 // 'will-change' can be handled by a repaint.
2826 uint8_t willChangeBitsChanged =
2827 mWillChangeBitField ^ aOther.mWillChangeBitField;
2828 if (willChangeBitsChanged) {
2829 NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
2832 // Note: Our current behavior for handling changes to the
2833 // transition-duration, transition-delay, and transition-timing-function
2834 // properties is to do nothing. In other words, the transition
2835 // property that matters is what it is when the transition begins, and
2836 // we don't stop a transition later because the transition property
2837 // changed.
2838 // We do handle changes to transition-property, but we don't need to
2839 // bother with anything here, since the transition manager is notified
2840 // of any style context change anyway.
2842 // Note: Likewise, for animation-*, the animation manager gets
2843 // notified about every new style context constructed, and it uses
2844 // that opportunity to handle dynamic changes appropriately.
2846 // But we still need to return nsChangeHint_NeutralChange for these
2847 // properties, since some data did change in the style struct.
2849 if (!hint &&
2850 (!mClip.IsEqualEdges(aOther.mClip) ||
2851 mOriginalDisplay != aOther.mOriginalDisplay ||
2852 mOriginalFloats != aOther.mOriginalFloats ||
2853 mTransitions != aOther.mTransitions ||
2854 mTransitionTimingFunctionCount !=
2855 aOther.mTransitionTimingFunctionCount ||
2856 mTransitionDurationCount != aOther.mTransitionDurationCount ||
2857 mTransitionDelayCount != aOther.mTransitionDelayCount ||
2858 mTransitionPropertyCount != aOther.mTransitionPropertyCount ||
2859 mAnimations != aOther.mAnimations ||
2860 mAnimationTimingFunctionCount != aOther.mAnimationTimingFunctionCount ||
2861 mAnimationDurationCount != aOther.mAnimationDurationCount ||
2862 mAnimationDelayCount != aOther.mAnimationDelayCount ||
2863 mAnimationNameCount != aOther.mAnimationNameCount ||
2864 mAnimationDirectionCount != aOther.mAnimationDirectionCount ||
2865 mAnimationFillModeCount != aOther.mAnimationFillModeCount ||
2866 mAnimationPlayStateCount != aOther.mAnimationPlayStateCount ||
2867 mAnimationIterationCountCount != aOther.mAnimationIterationCountCount)) {
2868 NS_UpdateHint(hint, nsChangeHint_NeutralChange);
2871 return hint;
2874 // --------------------
2875 // nsStyleVisibility
2878 nsStyleVisibility::nsStyleVisibility(nsPresContext* aPresContext)
2880 MOZ_COUNT_CTOR(nsStyleVisibility);
2881 uint32_t bidiOptions = aPresContext->GetBidi();
2882 if (GET_BIDI_OPTION_DIRECTION(bidiOptions) == IBMBIDI_TEXTDIRECTION_RTL)
2883 mDirection = NS_STYLE_DIRECTION_RTL;
2884 else
2885 mDirection = NS_STYLE_DIRECTION_LTR;
2887 mVisible = NS_STYLE_VISIBILITY_VISIBLE;
2888 mPointerEvents = NS_STYLE_POINTER_EVENTS_AUTO;
2889 mWritingMode = NS_STYLE_WRITING_MODE_HORIZONTAL_TB;
2890 mTextOrientation = NS_STYLE_TEXT_ORIENTATION_MIXED;
2893 nsStyleVisibility::nsStyleVisibility(const nsStyleVisibility& aSource)
2895 MOZ_COUNT_CTOR(nsStyleVisibility);
2896 mImageOrientation = aSource.mImageOrientation;
2897 mDirection = aSource.mDirection;
2898 mVisible = aSource.mVisible;
2899 mPointerEvents = aSource.mPointerEvents;
2900 mWritingMode = aSource.mWritingMode;
2901 mTextOrientation = aSource.mTextOrientation;
2904 nsChangeHint nsStyleVisibility::CalcDifference(const nsStyleVisibility& aOther) const
2906 nsChangeHint hint = nsChangeHint(0);
2908 if (mDirection != aOther.mDirection || mWritingMode != aOther.mWritingMode) {
2909 NS_UpdateHint(hint, nsChangeHint_ReconstructFrame);
2910 } else {
2911 if ((mImageOrientation != aOther.mImageOrientation)) {
2912 NS_UpdateHint(hint, nsChangeHint_AllReflowHints);
2913 NS_UpdateHint(hint, nsChangeHint_RepaintFrame);
2915 if (mVisible != aOther.mVisible) {
2916 if ((NS_STYLE_VISIBILITY_COLLAPSE == mVisible) ||
2917 (NS_STYLE_VISIBILITY_COLLAPSE == aOther.mVisible)) {
2918 NS_UpdateHint(hint, NS_STYLE_HINT_REFLOW);
2919 } else {
2920 NS_UpdateHint(hint, NS_STYLE_HINT_VISUAL);
2923 if (mTextOrientation != aOther.mTextOrientation) {
2924 NS_UpdateHint(hint, NS_STYLE_HINT_REFLOW);
2926 if (mPointerEvents != aOther.mPointerEvents) {
2927 // nsSVGPathGeometryFrame's mRect depends on stroke _and_ on the value
2928 // of pointer-events. See nsSVGPathGeometryFrame::ReflowSVG's use of
2929 // GetHitTestFlags. (Only a reflow, no visual change.)
2930 NS_UpdateHint(hint, nsChangeHint_NeedReflow);
2931 NS_UpdateHint(hint, nsChangeHint_NeedDirtyReflow); // XXX remove me: bug 876085
2934 return hint;
2937 nsStyleContentData::~nsStyleContentData()
2939 NS_ABORT_IF_FALSE(!mImageTracked,
2940 "nsStyleContentData being destroyed while still tracking image!");
2941 if (mType == eStyleContentType_Image) {
2942 NS_IF_RELEASE(mContent.mImage);
2943 } else if (mType == eStyleContentType_Counter ||
2944 mType == eStyleContentType_Counters) {
2945 mContent.mCounters->Release();
2946 } else if (mContent.mString) {
2947 NS_Free(mContent.mString);
2951 nsStyleContentData& nsStyleContentData::operator=(const nsStyleContentData& aOther)
2953 if (this == &aOther)
2954 return *this;
2955 this->~nsStyleContentData();
2956 new (this) nsStyleContentData();
2958 mType = aOther.mType;
2959 if (mType == eStyleContentType_Image) {
2960 mContent.mImage = aOther.mContent.mImage;
2961 NS_IF_ADDREF(mContent.mImage);
2962 } else if (mType == eStyleContentType_Counter ||
2963 mType == eStyleContentType_Counters) {
2964 mContent.mCounters = aOther.mContent.mCounters;
2965 mContent.mCounters->AddRef();
2966 } else if (aOther.mContent.mString) {
2967 mContent.mString = NS_strdup(aOther.mContent.mString);
2968 } else {
2969 mContent.mString = nullptr;
2971 return *this;
2974 bool nsStyleContentData::operator==(const nsStyleContentData& aOther) const
2976 if (mType != aOther.mType)
2977 return false;
2978 if (mType == eStyleContentType_Image) {
2979 if (!mContent.mImage || !aOther.mContent.mImage)
2980 return mContent.mImage == aOther.mContent.mImage;
2981 bool eq;
2982 nsCOMPtr<nsIURI> thisURI, otherURI;
2983 mContent.mImage->GetURI(getter_AddRefs(thisURI));
2984 aOther.mContent.mImage->GetURI(getter_AddRefs(otherURI));
2985 return thisURI == otherURI || // handles null==null
2986 (thisURI && otherURI &&
2987 NS_SUCCEEDED(thisURI->Equals(otherURI, &eq)) &&
2988 eq);
2990 if (mType == eStyleContentType_Counter ||
2991 mType == eStyleContentType_Counters)
2992 return *mContent.mCounters == *aOther.mContent.mCounters;
2993 return safe_strcmp(mContent.mString, aOther.mContent.mString) == 0;
2996 void
2997 nsStyleContentData::TrackImage(nsPresContext* aContext)
2999 // Sanity
3000 NS_ABORT_IF_FALSE(!mImageTracked, "Already tracking image!");
3001 NS_ABORT_IF_FALSE(mType == eStyleContentType_Image,
3002 "Trying to do image tracking on non-image!");
3003 NS_ABORT_IF_FALSE(mContent.mImage,
3004 "Can't track image when there isn't one!");
3006 // Register the image with the document
3007 nsIDocument* doc = aContext->Document();
3008 if (doc)
3009 doc->AddImage(mContent.mImage);
3011 // Mark state
3012 #ifdef DEBUG
3013 mImageTracked = true;
3014 #endif
3017 void
3018 nsStyleContentData::UntrackImage(nsPresContext* aContext)
3020 // Sanity
3021 NS_ABORT_IF_FALSE(mImageTracked, "Image not tracked!");
3022 NS_ABORT_IF_FALSE(mType == eStyleContentType_Image,
3023 "Trying to do image tracking on non-image!");
3024 NS_ABORT_IF_FALSE(mContent.mImage,
3025 "Can't untrack image when there isn't one!");
3027 // Unregister the image with the document
3028 nsIDocument* doc = aContext->Document();
3029 if (doc)
3030 doc->RemoveImage(mContent.mImage, nsIDocument::REQUEST_DISCARD);
3032 // Mark state
3033 #ifdef DEBUG
3034 mImageTracked = false;
3035 #endif
3039 //-----------------------
3040 // nsStyleContent
3043 nsStyleContent::nsStyleContent(void)
3044 : mMarkerOffset(),
3045 mContents(nullptr),
3046 mIncrements(nullptr),
3047 mResets(nullptr),
3048 mContentCount(0),
3049 mIncrementCount(0),
3050 mResetCount(0)
3052 MOZ_COUNT_CTOR(nsStyleContent);
3053 mMarkerOffset.SetAutoValue();
3056 nsStyleContent::~nsStyleContent(void)
3058 MOZ_COUNT_DTOR(nsStyleContent);
3059 DELETE_ARRAY_IF(mContents);
3060 DELETE_ARRAY_IF(mIncrements);
3061 DELETE_ARRAY_IF(mResets);
3064 void
3065 nsStyleContent::Destroy(nsPresContext* aContext)
3067 // Unregister any images we might have with the document.
3068 for (uint32_t i = 0; i < mContentCount; ++i) {
3069 if ((mContents[i].mType == eStyleContentType_Image) &&
3070 mContents[i].mContent.mImage) {
3071 mContents[i].UntrackImage(aContext);
3075 this->~nsStyleContent();
3076 aContext->PresShell()->
3077 FreeByObjectID(nsPresArena::nsStyleContent_id, this);
3080 nsStyleContent::nsStyleContent(const nsStyleContent& aSource)
3081 :mMarkerOffset(),
3082 mContents(nullptr),
3083 mIncrements(nullptr),
3084 mResets(nullptr),
3085 mContentCount(0),
3086 mIncrementCount(0),
3087 mResetCount(0)
3090 MOZ_COUNT_CTOR(nsStyleContent);
3091 mMarkerOffset = aSource.mMarkerOffset;
3093 uint32_t index;
3094 if (NS_SUCCEEDED(AllocateContents(aSource.ContentCount()))) {
3095 for (index = 0; index < mContentCount; index++) {
3096 ContentAt(index) = aSource.ContentAt(index);
3100 if (NS_SUCCEEDED(AllocateCounterIncrements(aSource.CounterIncrementCount()))) {
3101 for (index = 0; index < mIncrementCount; index++) {
3102 const nsStyleCounterData *data = aSource.GetCounterIncrementAt(index);
3103 mIncrements[index].mCounter = data->mCounter;
3104 mIncrements[index].mValue = data->mValue;
3108 if (NS_SUCCEEDED(AllocateCounterResets(aSource.CounterResetCount()))) {
3109 for (index = 0; index < mResetCount; index++) {
3110 const nsStyleCounterData *data = aSource.GetCounterResetAt(index);
3111 mResets[index].mCounter = data->mCounter;
3112 mResets[index].mValue = data->mValue;
3117 nsChangeHint nsStyleContent::CalcDifference(const nsStyleContent& aOther) const
3119 // In ReResolveStyleContext we assume that if there's no existing
3120 // ::before or ::after and we don't have to restyle children of the
3121 // node then we can't end up with a ::before or ::after due to the
3122 // restyle of the node itself. That's not quite true, but the only
3123 // exception to the above is when the 'content' property of the node
3124 // changes and the pseudo-element inherits the changed value. Since
3125 // the code here triggers a frame change on the node in that case,
3126 // the optimization in ReResolveStyleContext is ok. But if we ever
3127 // change this code to not reconstruct frames on changes to the
3128 // 'content' property, then we will need to revisit the optimization
3129 // in ReResolveStyleContext.
3131 if (mContentCount != aOther.mContentCount ||
3132 mIncrementCount != aOther.mIncrementCount ||
3133 mResetCount != aOther.mResetCount) {
3134 return NS_STYLE_HINT_FRAMECHANGE;
3137 uint32_t ix = mContentCount;
3138 while (0 < ix--) {
3139 if (mContents[ix] != aOther.mContents[ix]) {
3140 // Unfortunately we need to reframe here; a simple reflow
3141 // will not pick up different text or different image URLs,
3142 // since we set all that up in the CSSFrameConstructor
3143 return NS_STYLE_HINT_FRAMECHANGE;
3146 ix = mIncrementCount;
3147 while (0 < ix--) {
3148 if ((mIncrements[ix].mValue != aOther.mIncrements[ix].mValue) ||
3149 (mIncrements[ix].mCounter != aOther.mIncrements[ix].mCounter)) {
3150 return NS_STYLE_HINT_FRAMECHANGE;
3153 ix = mResetCount;
3154 while (0 < ix--) {
3155 if ((mResets[ix].mValue != aOther.mResets[ix].mValue) ||
3156 (mResets[ix].mCounter != aOther.mResets[ix].mCounter)) {
3157 return NS_STYLE_HINT_FRAMECHANGE;
3160 if (mMarkerOffset != aOther.mMarkerOffset) {
3161 return NS_STYLE_HINT_REFLOW;
3163 return NS_STYLE_HINT_NONE;
3166 nsresult nsStyleContent::AllocateContents(uint32_t aCount)
3168 // We need to run the destructors of the elements of mContents, so we
3169 // delete and reallocate even if aCount == mContentCount. (If
3170 // nsStyleContentData had its members private and managed their
3171 // ownership on setting, we wouldn't need this, but that seems
3172 // unnecessary at this point.)
3173 DELETE_ARRAY_IF(mContents);
3174 if (aCount) {
3175 mContents = new nsStyleContentData[aCount];
3176 if (! mContents) {
3177 mContentCount = 0;
3178 return NS_ERROR_OUT_OF_MEMORY;
3181 mContentCount = aCount;
3182 return NS_OK;
3185 // ---------------------
3186 // nsStyleQuotes
3189 nsStyleQuotes::nsStyleQuotes(void)
3190 : mQuotesCount(0),
3191 mQuotes(nullptr)
3193 MOZ_COUNT_CTOR(nsStyleQuotes);
3194 SetInitial();
3197 nsStyleQuotes::~nsStyleQuotes(void)
3199 MOZ_COUNT_DTOR(nsStyleQuotes);
3200 DELETE_ARRAY_IF(mQuotes);
3203 nsStyleQuotes::nsStyleQuotes(const nsStyleQuotes& aSource)
3204 : mQuotesCount(0),
3205 mQuotes(nullptr)
3207 MOZ_COUNT_CTOR(nsStyleQuotes);
3208 CopyFrom(aSource);
3211 void
3212 nsStyleQuotes::SetInitial()
3214 // The initial value for quotes is the en-US typographic convention:
3215 // outermost are LEFT and RIGHT DOUBLE QUOTATION MARK, alternating
3216 // with LEFT and RIGHT SINGLE QUOTATION MARK.
3217 static const char16_t initialQuotes[8] = {
3218 0x201C, 0, 0x201D, 0, 0x2018, 0, 0x2019, 0
3221 if (NS_SUCCEEDED(AllocateQuotes(2))) {
3222 SetQuotesAt(0,
3223 nsDependentString(&initialQuotes[0], 1),
3224 nsDependentString(&initialQuotes[2], 1));
3225 SetQuotesAt(1,
3226 nsDependentString(&initialQuotes[4], 1),
3227 nsDependentString(&initialQuotes[6], 1));
3231 void
3232 nsStyleQuotes::CopyFrom(const nsStyleQuotes& aSource)
3234 if (NS_SUCCEEDED(AllocateQuotes(aSource.QuotesCount()))) {
3235 uint32_t count = (mQuotesCount * 2);
3236 for (uint32_t index = 0; index < count; index += 2) {
3237 aSource.GetQuotesAt(index, mQuotes[index], mQuotes[index + 1]);
3242 nsChangeHint nsStyleQuotes::CalcDifference(const nsStyleQuotes& aOther) const
3244 // If the quotes implementation is ever going to change we might not need
3245 // a framechange here and a reflow should be sufficient. See bug 35768.
3246 if (mQuotesCount == aOther.mQuotesCount) {
3247 uint32_t ix = (mQuotesCount * 2);
3248 while (0 < ix--) {
3249 if (mQuotes[ix] != aOther.mQuotes[ix]) {
3250 return NS_STYLE_HINT_FRAMECHANGE;
3254 return NS_STYLE_HINT_NONE;
3256 return NS_STYLE_HINT_FRAMECHANGE;
3259 // --------------------
3260 // nsStyleTextReset
3263 nsStyleTextReset::nsStyleTextReset(void)
3265 MOZ_COUNT_CTOR(nsStyleTextReset);
3266 mVerticalAlign.SetIntValue(NS_STYLE_VERTICAL_ALIGN_BASELINE, eStyleUnit_Enumerated);
3267 mTextDecorationLine = NS_STYLE_TEXT_DECORATION_LINE_NONE;
3268 mTextDecorationColor = NS_RGB(0,0,0);
3269 mTextDecorationStyle =
3270 NS_STYLE_TEXT_DECORATION_STYLE_SOLID | BORDER_COLOR_FOREGROUND;
3271 mUnicodeBidi = NS_STYLE_UNICODE_BIDI_NORMAL;
3274 nsStyleTextReset::nsStyleTextReset(const nsStyleTextReset& aSource)
3276 MOZ_COUNT_CTOR(nsStyleTextReset);
3277 *this = aSource;
3280 nsStyleTextReset::~nsStyleTextReset(void)
3282 MOZ_COUNT_DTOR(nsStyleTextReset);
3285 nsChangeHint nsStyleTextReset::CalcDifference(const nsStyleTextReset& aOther) const
3287 if (mVerticalAlign == aOther.mVerticalAlign
3288 && mUnicodeBidi == aOther.mUnicodeBidi) {
3289 uint8_t lineStyle = GetDecorationStyle();
3290 uint8_t otherLineStyle = aOther.GetDecorationStyle();
3291 if (mTextDecorationLine != aOther.mTextDecorationLine ||
3292 lineStyle != otherLineStyle) {
3293 // Repaint for other style decoration lines because they must be in
3294 // default overflow rect
3295 nsChangeHint hint = NS_STYLE_HINT_VISUAL;
3296 NS_UpdateHint(hint, nsChangeHint_UpdateSubtreeOverflow);
3297 return hint;
3300 // Repaint for decoration color changes
3301 nscolor decColor, otherDecColor;
3302 bool isFG, otherIsFG;
3303 GetDecorationColor(decColor, isFG);
3304 aOther.GetDecorationColor(otherDecColor, otherIsFG);
3305 if (isFG != otherIsFG || (!isFG && decColor != otherDecColor)) {
3306 return NS_STYLE_HINT_VISUAL;
3309 if (mTextOverflow != aOther.mTextOverflow) {
3310 return NS_STYLE_HINT_VISUAL;
3312 return NS_STYLE_HINT_NONE;
3314 return NS_STYLE_HINT_REFLOW;
3317 // Allowed to return one of NS_STYLE_HINT_NONE, NS_STYLE_HINT_REFLOW
3318 // or NS_STYLE_HINT_VISUAL. Currently we just return NONE or REFLOW, though.
3319 // XXXbz can this not return a more specific hint? If that's ever
3320 // changed, nsStyleBorder::CalcDifference will need changing too.
3321 static nsChangeHint
3322 CalcShadowDifference(nsCSSShadowArray* lhs,
3323 nsCSSShadowArray* rhs)
3325 if (lhs == rhs)
3326 return NS_STYLE_HINT_NONE;
3328 if (!lhs || !rhs || lhs->Length() != rhs->Length())
3329 return NS_STYLE_HINT_REFLOW;
3331 for (uint32_t i = 0; i < lhs->Length(); ++i) {
3332 if (*lhs->ShadowAt(i) != *rhs->ShadowAt(i))
3333 return NS_STYLE_HINT_REFLOW;
3335 return NS_STYLE_HINT_NONE;
3338 // --------------------
3339 // nsStyleText
3342 nsStyleText::nsStyleText(void)
3344 MOZ_COUNT_CTOR(nsStyleText);
3345 mTextAlign = NS_STYLE_TEXT_ALIGN_DEFAULT;
3346 mTextAlignLast = NS_STYLE_TEXT_ALIGN_AUTO;
3347 mTextAlignTrue = false;
3348 mTextAlignLastTrue = false;
3349 mTextTransform = NS_STYLE_TEXT_TRANSFORM_NONE;
3350 mWhiteSpace = NS_STYLE_WHITESPACE_NORMAL;
3351 mWordBreak = NS_STYLE_WORDBREAK_NORMAL;
3352 mWordWrap = NS_STYLE_WORDWRAP_NORMAL;
3353 mHyphens = NS_STYLE_HYPHENS_MANUAL;
3354 mRubyPosition = NS_STYLE_RUBY_POSITION_INITIAL;
3355 mTextSizeAdjust = NS_STYLE_TEXT_SIZE_ADJUST_AUTO;
3356 mTextCombineUpright = NS_STYLE_TEXT_COMBINE_UPRIGHT_NONE;
3357 mControlCharacterVisibility = NS_STYLE_CONTROL_CHARACTER_VISIBILITY_HIDDEN;
3359 mLetterSpacing.SetNormalValue();
3360 mLineHeight.SetNormalValue();
3361 mTextIndent.SetCoordValue(0);
3362 mWordSpacing = 0;
3364 mTextShadow = nullptr;
3365 mTabSize = NS_STYLE_TABSIZE_INITIAL;
3368 nsStyleText::nsStyleText(const nsStyleText& aSource)
3369 : mTextAlign(aSource.mTextAlign),
3370 mTextAlignLast(aSource.mTextAlignLast),
3371 mTextAlignTrue(false),
3372 mTextAlignLastTrue(false),
3373 mTextTransform(aSource.mTextTransform),
3374 mWhiteSpace(aSource.mWhiteSpace),
3375 mWordBreak(aSource.mWordBreak),
3376 mWordWrap(aSource.mWordWrap),
3377 mHyphens(aSource.mHyphens),
3378 mRubyPosition(aSource.mRubyPosition),
3379 mTextSizeAdjust(aSource.mTextSizeAdjust),
3380 mTextCombineUpright(aSource.mTextCombineUpright),
3381 mControlCharacterVisibility(aSource.mControlCharacterVisibility),
3382 mTabSize(aSource.mTabSize),
3383 mWordSpacing(aSource.mWordSpacing),
3384 mLetterSpacing(aSource.mLetterSpacing),
3385 mLineHeight(aSource.mLineHeight),
3386 mTextIndent(aSource.mTextIndent),
3387 mTextShadow(aSource.mTextShadow)
3389 MOZ_COUNT_CTOR(nsStyleText);
3392 nsStyleText::~nsStyleText(void)
3394 MOZ_COUNT_DTOR(nsStyleText);
3397 nsChangeHint nsStyleText::CalcDifference(const nsStyleText& aOther) const
3399 if (WhiteSpaceOrNewlineIsSignificant() !=
3400 aOther.WhiteSpaceOrNewlineIsSignificant()) {
3401 // This may require construction of suppressed text frames
3402 return NS_STYLE_HINT_FRAMECHANGE;
3405 if (mTextCombineUpright != aOther.mTextCombineUpright ||
3406 mControlCharacterVisibility != aOther.mControlCharacterVisibility) {
3407 return nsChangeHint_ReconstructFrame;
3410 if ((mTextAlign != aOther.mTextAlign) ||
3411 (mTextAlignLast != aOther.mTextAlignLast) ||
3412 (mTextAlignTrue != aOther.mTextAlignTrue) ||
3413 (mTextAlignLastTrue != aOther.mTextAlignLastTrue) ||
3414 (mTextTransform != aOther.mTextTransform) ||
3415 (mWhiteSpace != aOther.mWhiteSpace) ||
3416 (mWordBreak != aOther.mWordBreak) ||
3417 (mWordWrap != aOther.mWordWrap) ||
3418 (mHyphens != aOther.mHyphens) ||
3419 (mRubyPosition != aOther.mRubyPosition) ||
3420 (mTextSizeAdjust != aOther.mTextSizeAdjust) ||
3421 (mLetterSpacing != aOther.mLetterSpacing) ||
3422 (mLineHeight != aOther.mLineHeight) ||
3423 (mTextIndent != aOther.mTextIndent) ||
3424 (mWordSpacing != aOther.mWordSpacing) ||
3425 (mTabSize != aOther.mTabSize))
3426 return NS_STYLE_HINT_REFLOW;
3428 return CalcShadowDifference(mTextShadow, aOther.mTextShadow);
3431 //-----------------------
3432 // nsStyleUserInterface
3435 nsCursorImage::nsCursorImage()
3436 : mHaveHotspot(false)
3437 , mHotspotX(0.0f)
3438 , mHotspotY(0.0f)
3442 nsCursorImage::nsCursorImage(const nsCursorImage& aOther)
3443 : mHaveHotspot(aOther.mHaveHotspot)
3444 , mHotspotX(aOther.mHotspotX)
3445 , mHotspotY(aOther.mHotspotY)
3447 SetImage(aOther.GetImage());
3450 nsCursorImage::~nsCursorImage()
3452 SetImage(nullptr);
3455 nsCursorImage&
3456 nsCursorImage::operator=(const nsCursorImage& aOther)
3458 if (this != &aOther) {
3459 mHaveHotspot = aOther.mHaveHotspot;
3460 mHotspotX = aOther.mHotspotX;
3461 mHotspotY = aOther.mHotspotY;
3462 SetImage(aOther.GetImage());
3465 return *this;
3468 nsStyleUserInterface::nsStyleUserInterface(void)
3470 MOZ_COUNT_CTOR(nsStyleUserInterface);
3471 mUserInput = NS_STYLE_USER_INPUT_AUTO;
3472 mUserModify = NS_STYLE_USER_MODIFY_READ_ONLY;
3473 mUserFocus = NS_STYLE_USER_FOCUS_NONE;
3474 mWindowDragging = NS_STYLE_WINDOW_DRAGGING_NO_DRAG;
3476 mCursor = NS_STYLE_CURSOR_AUTO; // fix for bugzilla bug 51113
3478 mCursorArrayLength = 0;
3479 mCursorArray = nullptr;
3482 nsStyleUserInterface::nsStyleUserInterface(const nsStyleUserInterface& aSource) :
3483 mUserInput(aSource.mUserInput),
3484 mUserModify(aSource.mUserModify),
3485 mUserFocus(aSource.mUserFocus),
3486 mWindowDragging(aSource.mWindowDragging),
3487 mCursor(aSource.mCursor)
3489 MOZ_COUNT_CTOR(nsStyleUserInterface);
3490 CopyCursorArrayFrom(aSource);
3493 nsStyleUserInterface::~nsStyleUserInterface(void)
3495 MOZ_COUNT_DTOR(nsStyleUserInterface);
3496 delete [] mCursorArray;
3499 nsChangeHint nsStyleUserInterface::CalcDifference(const nsStyleUserInterface& aOther) const
3501 nsChangeHint hint = nsChangeHint(0);
3502 if (mCursor != aOther.mCursor)
3503 NS_UpdateHint(hint, nsChangeHint_UpdateCursor);
3505 // We could do better. But it wouldn't be worth it, URL-specified cursors are
3506 // rare.
3507 if (mCursorArrayLength > 0 || aOther.mCursorArrayLength > 0)
3508 NS_UpdateHint(hint, nsChangeHint_UpdateCursor);
3510 if (mUserModify != aOther.mUserModify)
3511 NS_UpdateHint(hint, NS_STYLE_HINT_VISUAL);
3513 if (mUserInput != aOther.mUserInput) {
3514 if (NS_STYLE_USER_INPUT_NONE == mUserInput ||
3515 NS_STYLE_USER_INPUT_NONE == aOther.mUserInput) {
3516 NS_UpdateHint(hint, NS_STYLE_HINT_FRAMECHANGE);
3517 } else {
3518 NS_UpdateHint(hint, nsChangeHint_NeutralChange);
3522 if (mUserFocus != aOther.mUserFocus) {
3523 NS_UpdateHint(hint, nsChangeHint_NeutralChange);
3526 if (mWindowDragging != aOther.mWindowDragging) {
3527 NS_UpdateHint(hint, nsChangeHint_SchedulePaint);
3530 return hint;
3533 void
3534 nsStyleUserInterface::CopyCursorArrayFrom(const nsStyleUserInterface& aSource)
3536 mCursorArray = nullptr;
3537 mCursorArrayLength = 0;
3538 if (aSource.mCursorArrayLength) {
3539 mCursorArray = new nsCursorImage[aSource.mCursorArrayLength];
3540 if (mCursorArray) {
3541 mCursorArrayLength = aSource.mCursorArrayLength;
3542 for (uint32_t i = 0; i < mCursorArrayLength; ++i)
3543 mCursorArray[i] = aSource.mCursorArray[i];
3548 //-----------------------
3549 // nsStyleUIReset
3552 nsStyleUIReset::nsStyleUIReset(void)
3554 MOZ_COUNT_CTOR(nsStyleUIReset);
3555 mUserSelect = NS_STYLE_USER_SELECT_AUTO;
3556 mForceBrokenImageIcon = 0;
3557 mIMEMode = NS_STYLE_IME_MODE_AUTO;
3558 mWindowShadow = NS_STYLE_WINDOW_SHADOW_DEFAULT;
3561 nsStyleUIReset::nsStyleUIReset(const nsStyleUIReset& aSource)
3563 MOZ_COUNT_CTOR(nsStyleUIReset);
3564 mUserSelect = aSource.mUserSelect;
3565 mForceBrokenImageIcon = aSource.mForceBrokenImageIcon;
3566 mIMEMode = aSource.mIMEMode;
3567 mWindowShadow = aSource.mWindowShadow;
3570 nsStyleUIReset::~nsStyleUIReset(void)
3572 MOZ_COUNT_DTOR(nsStyleUIReset);
3575 nsChangeHint nsStyleUIReset::CalcDifference(const nsStyleUIReset& aOther) const
3577 // ignore mIMEMode
3578 if (mForceBrokenImageIcon != aOther.mForceBrokenImageIcon)
3579 return NS_STYLE_HINT_FRAMECHANGE;
3580 if (mWindowShadow != aOther.mWindowShadow) {
3581 // We really need just an nsChangeHint_SyncFrameView, except
3582 // on an ancestor of the frame, so we get that by doing a
3583 // reflow.
3584 return NS_STYLE_HINT_REFLOW;
3586 if (mUserSelect != aOther.mUserSelect)
3587 return NS_STYLE_HINT_VISUAL;
3588 return NS_STYLE_HINT_NONE;
3591 //-----------------------
3592 // nsStyleVariables
3595 nsStyleVariables::nsStyleVariables()
3597 MOZ_COUNT_CTOR(nsStyleVariables);
3600 nsStyleVariables::nsStyleVariables(const nsStyleVariables& aSource)
3602 MOZ_COUNT_CTOR(nsStyleVariables);
3605 nsStyleVariables::~nsStyleVariables(void)
3607 MOZ_COUNT_DTOR(nsStyleVariables);
3610 nsChangeHint
3611 nsStyleVariables::CalcDifference(const nsStyleVariables& aOther) const
3613 return nsChangeHint(0);