Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 : /* This Source Code Form is subject to the terms of the Mozilla Public
4 : * License, v. 2.0. If a copy of the MPL was not distributed with this
5 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 :
7 : /*
8 : * structs that contain the data provided by nsStyleContext, the
9 : * internal API for computed style data for an element
10 : */
11 :
12 : #include "nsStyleStruct.h"
13 : #include "nsStyleStructInlines.h"
14 : #include "nsStyleConsts.h"
15 : #include "nsThemeConstants.h"
16 : #include "nsString.h"
17 : #include "nsPresContext.h"
18 : #include "nsIAppShellService.h"
19 : #include "nsIWidget.h"
20 : #include "nsCRTGlue.h"
21 : #include "nsCSSParser.h"
22 : #include "nsCSSProps.h"
23 : #include "nsDeviceContext.h"
24 : #include "nsStyleUtil.h"
25 :
26 : #include "nsCOMPtr.h"
27 :
28 : #include "nsBidiUtils.h"
29 : #include "nsLayoutUtils.h"
30 :
31 : #include "imgIRequest.h"
32 : #include "imgIContainer.h"
33 : #include "CounterStyleManager.h"
34 :
35 : #include "mozilla/dom/AnimationEffectReadOnlyBinding.h" // for PlaybackDirection
36 : #include "mozilla/dom/DocGroup.h"
37 : #include "mozilla/dom/ImageTracker.h"
38 : #include "mozilla/Likely.h"
39 : #include "nsIURI.h"
40 : #include "nsIDocument.h"
41 : #include <algorithm>
42 : #include "ImageLoader.h"
43 :
44 : using namespace mozilla;
45 : using namespace mozilla::dom;
46 :
47 : static_assert((((1 << nsStyleStructID_Length) - 1) &
48 : ~(NS_STYLE_INHERIT_MASK)) == 0,
49 : "Not enough bits in NS_STYLE_INHERIT_MASK");
50 :
51 : /* static */ const int32_t nsStyleGridLine::kMinLine;
52 : /* static */ const int32_t nsStyleGridLine::kMaxLine;
53 :
54 : static bool
55 748 : DefinitelyEqualURIs(css::URLValueData* aURI1,
56 : css::URLValueData* aURI2)
57 : {
58 1483 : return aURI1 == aURI2 ||
59 759 : (aURI1 && aURI2 && aURI1->DefinitelyEqualURIs(*aURI2));
60 : }
61 :
62 : static bool
63 358 : DefinitelyEqualURIsAndPrincipal(css::URLValueData* aURI1,
64 : css::URLValueData* aURI2)
65 : {
66 711 : return aURI1 == aURI2 ||
67 363 : (aURI1 && aURI2 && aURI1->DefinitelyEqualURIsAndPrincipal(*aURI2));
68 : }
69 :
70 : static bool
71 106 : DefinitelyEqualImages(nsStyleImageRequest* aRequest1,
72 : nsStyleImageRequest* aRequest2)
73 : {
74 106 : if (aRequest1 == aRequest2) {
75 11 : return true;
76 : }
77 :
78 95 : if (!aRequest1 || !aRequest2) {
79 1 : return false;
80 : }
81 :
82 94 : return aRequest1->DefinitelyEquals(*aRequest2);
83 : }
84 :
85 : // A nullsafe wrapper for strcmp. We depend on null-safety.
86 : static int
87 6 : safe_strcmp(const char16_t* a, const char16_t* b)
88 : {
89 6 : if (!a || !b) {
90 0 : return (int)(a - b);
91 : }
92 6 : return NS_strcmp(a, b);
93 : }
94 :
95 : static bool AreShadowArraysEqual(nsCSSShadowArray* lhs, nsCSSShadowArray* rhs);
96 :
97 : // --------------------
98 : // nsStyleFont
99 : //
100 73 : nsStyleFont::nsStyleFont(const nsFont& aFont, const nsPresContext* aContext)
101 : : mFont(aFont)
102 73 : , mSize(nsStyleFont::ZoomText(aContext, mFont.size))
103 : , mGenericID(kGenericFont_NONE)
104 : , mScriptLevel(0)
105 : , mMathVariant(NS_MATHML_MATHVARIANT_NONE)
106 : , mMathDisplay(NS_MATHML_DISPLAYSTYLE_INLINE)
107 : , mMinFontSizeRatio(100) // 100%
108 : , mExplicitLanguage(false)
109 : , mAllowZoom(true)
110 73 : , mScriptUnconstrainedSize(mSize)
111 73 : , mScriptMinSize(nsPresContext::CSSTwipsToAppUnits(
112 : NS_POINTS_TO_TWIPS(NS_MATHML_DEFAULT_SCRIPT_MIN_SIZE_PT)))
113 : , mScriptSizeMultiplier(NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER)
114 292 : , mLanguage(GetLanguage(aContext))
115 : {
116 73 : MOZ_COUNT_CTOR(nsStyleFont);
117 73 : mFont.size = mSize;
118 73 : }
119 :
120 12 : nsStyleFont::nsStyleFont(const nsStyleFont& aSrc)
121 : : mFont(aSrc.mFont)
122 12 : , mSize(aSrc.mSize)
123 12 : , mGenericID(aSrc.mGenericID)
124 12 : , mScriptLevel(aSrc.mScriptLevel)
125 12 : , mMathVariant(aSrc.mMathVariant)
126 12 : , mMathDisplay(aSrc.mMathDisplay)
127 12 : , mMinFontSizeRatio(aSrc.mMinFontSizeRatio)
128 12 : , mExplicitLanguage(aSrc.mExplicitLanguage)
129 12 : , mAllowZoom(aSrc.mAllowZoom)
130 12 : , mScriptUnconstrainedSize(aSrc.mScriptUnconstrainedSize)
131 12 : , mScriptMinSize(aSrc.mScriptMinSize)
132 12 : , mScriptSizeMultiplier(aSrc.mScriptSizeMultiplier)
133 144 : , mLanguage(aSrc.mLanguage)
134 : {
135 12 : MOZ_COUNT_CTOR(nsStyleFont);
136 12 : }
137 :
138 73 : nsStyleFont::nsStyleFont(const nsPresContext* aContext)
139 73 : : nsStyleFont(*aContext->GetDefaultFont(kPresContext_DefaultVariableFont_ID,
140 : nullptr),
141 73 : aContext)
142 : {
143 73 : }
144 :
145 : void
146 10 : nsStyleFont::Destroy(nsPresContext* aContext) {
147 10 : this->~nsStyleFont();
148 : aContext->PresShell()->
149 10 : FreeByObjectID(eArenaObjectID_nsStyleFont, this);
150 10 : }
151 :
152 : void
153 0 : nsStyleFont::EnableZoom(nsPresContext* aContext, bool aEnable)
154 : {
155 0 : if (mAllowZoom == aEnable) {
156 0 : return;
157 : }
158 0 : mAllowZoom = aEnable;
159 0 : if (mAllowZoom) {
160 0 : mSize = nsStyleFont::ZoomText(aContext, mSize);
161 0 : mFont.size = nsStyleFont::ZoomText(aContext, mFont.size);
162 0 : mScriptUnconstrainedSize =
163 0 : nsStyleFont::ZoomText(aContext, mScriptUnconstrainedSize);
164 : } else {
165 0 : mSize = nsStyleFont::UnZoomText(aContext, mSize);
166 0 : mFont.size = nsStyleFont::UnZoomText(aContext, mFont.size);
167 0 : mScriptUnconstrainedSize =
168 0 : nsStyleFont::UnZoomText(aContext, mScriptUnconstrainedSize);
169 : }
170 : }
171 :
172 : nsChangeHint
173 36 : nsStyleFont::CalcDifference(const nsStyleFont& aNewData) const
174 : {
175 36 : MOZ_ASSERT(mAllowZoom == aNewData.mAllowZoom,
176 : "expected mAllowZoom to be the same on both nsStyleFonts");
177 108 : if (mSize != aNewData.mSize ||
178 72 : mFont != aNewData.mFont ||
179 68 : mLanguage != aNewData.mLanguage ||
180 64 : mExplicitLanguage != aNewData.mExplicitLanguage ||
181 64 : mMathVariant != aNewData.mMathVariant ||
182 100 : mMathDisplay != aNewData.mMathDisplay ||
183 32 : mMinFontSizeRatio != aNewData.mMinFontSizeRatio) {
184 4 : return NS_STYLE_HINT_REFLOW;
185 : }
186 :
187 : // XXX Should any of these cause a non-nsChangeHint_NeutralChange change?
188 64 : if (mGenericID != aNewData.mGenericID ||
189 64 : mScriptLevel != aNewData.mScriptLevel ||
190 64 : mScriptUnconstrainedSize != aNewData.mScriptUnconstrainedSize ||
191 64 : mScriptMinSize != aNewData.mScriptMinSize ||
192 32 : mScriptSizeMultiplier != aNewData.mScriptSizeMultiplier) {
193 0 : return nsChangeHint_NeutralChange;
194 : }
195 :
196 32 : return nsChangeHint(0);
197 : }
198 :
199 : /* static */ nscoord
200 79 : nsStyleFont::ZoomText(const nsPresContext* aPresContext, nscoord aSize)
201 : {
202 : // aSize can be negative (e.g.: calc(-1px)) so we can't assert that here.
203 : // The caller is expected deal with that.
204 79 : return NSToCoordTruncClamped(float(aSize) * aPresContext->EffectiveTextZoom());
205 : }
206 :
207 : /* static */ nscoord
208 0 : nsStyleFont::UnZoomText(nsPresContext *aPresContext, nscoord aSize)
209 : {
210 : // aSize can be negative (e.g.: calc(-1px)) so we can't assert that here.
211 : // The caller is expected deal with that.
212 0 : return NSToCoordTruncClamped(float(aSize) / aPresContext->EffectiveTextZoom());
213 : }
214 :
215 : /* static */ already_AddRefed<nsIAtom>
216 73 : nsStyleFont::GetLanguage(const nsPresContext* aPresContext)
217 : {
218 146 : RefPtr<nsIAtom> language = aPresContext->GetContentLanguage();
219 73 : if (!language) {
220 : // we didn't find a (usable) Content-Language, so we fall back
221 : // to whatever the presContext guessed from the charset
222 : // NOTE this should not be used elsewhere, because we want websites
223 : // to use UTF-8 with proper language tag, instead of relying on
224 : // deriving language from charset. See bug 1040668 comment 67.
225 73 : language = aPresContext->GetLanguageFromCharset();
226 : }
227 146 : return language.forget();
228 : }
229 :
230 126 : nsStyleMargin::nsStyleMargin(const nsPresContext* aContext)
231 : {
232 126 : MOZ_COUNT_CTOR(nsStyleMargin);
233 252 : nsStyleCoord zero(0, nsStyleCoord::CoordConstructor);
234 630 : NS_FOR_CSS_SIDES(side) {
235 504 : mMargin.Set(side, zero);
236 : }
237 126 : }
238 :
239 88 : nsStyleMargin::nsStyleMargin(const nsStyleMargin& aSrc)
240 88 : : mMargin(aSrc.mMargin)
241 : {
242 88 : MOZ_COUNT_CTOR(nsStyleMargin);
243 88 : }
244 :
245 : void
246 101 : nsStyleMargin::Destroy(nsPresContext* aContext) {
247 101 : this->~nsStyleMargin();
248 : aContext->PresShell()->
249 101 : FreeByObjectID(eArenaObjectID_nsStyleMargin, this);
250 101 : }
251 :
252 : nsChangeHint
253 300 : nsStyleMargin::CalcDifference(const nsStyleMargin& aNewData) const
254 : {
255 300 : if (mMargin == aNewData.mMargin) {
256 299 : return nsChangeHint(0);
257 : }
258 : // Margin differences can't affect descendant intrinsic sizes and
259 : // don't need to force children to reflow.
260 : return nsChangeHint_NeedReflow |
261 1 : nsChangeHint_ReflowChangesSizeOrPosition |
262 1 : nsChangeHint_ClearAncestorIntrinsics;
263 : }
264 :
265 136 : nsStylePadding::nsStylePadding(const nsPresContext* aContext)
266 : {
267 136 : MOZ_COUNT_CTOR(nsStylePadding);
268 272 : nsStyleCoord zero(0, nsStyleCoord::CoordConstructor);
269 680 : NS_FOR_CSS_SIDES(side) {
270 544 : mPadding.Set(side, zero);
271 : }
272 136 : }
273 :
274 9 : nsStylePadding::nsStylePadding(const nsStylePadding& aSrc)
275 9 : : mPadding(aSrc.mPadding)
276 : {
277 9 : MOZ_COUNT_CTOR(nsStylePadding);
278 9 : }
279 :
280 : void
281 67 : nsStylePadding::Destroy(nsPresContext* aContext) {
282 67 : this->~nsStylePadding();
283 : aContext->PresShell()->
284 67 : FreeByObjectID(eArenaObjectID_nsStylePadding, this);
285 67 : }
286 :
287 : nsChangeHint
288 249 : nsStylePadding::CalcDifference(const nsStylePadding& aNewData) const
289 : {
290 249 : if (mPadding == aNewData.mPadding) {
291 249 : return nsChangeHint(0);
292 : }
293 : // Padding differences can't affect descendant intrinsic sizes, but do need
294 : // to force children to reflow so that we can reposition them, since their
295 : // offsets are from our frame bounds but our content rect's position within
296 : // those bounds is moving.
297 : // FIXME: It would be good to return a weaker hint here that doesn't
298 : // force reflow of all descendants, but the hint would need to force
299 : // reflow of the frame's children (see how
300 : // ReflowInput::InitResizeFlags initializes the inline-resize flag).
301 0 : return NS_STYLE_HINT_REFLOW & ~nsChangeHint_ClearDescendantIntrinsics;
302 : }
303 :
304 26 : nsStyleBorder::nsStyleBorder(const nsPresContext* aContext)
305 : : mBorderColors(nullptr)
306 : , mBorderImageFill(NS_STYLE_BORDER_IMAGE_SLICE_NOFILL)
307 : , mBorderImageRepeatH(NS_STYLE_BORDER_IMAGE_REPEAT_STRETCH)
308 : , mBorderImageRepeatV(NS_STYLE_BORDER_IMAGE_REPEAT_STRETCH)
309 : , mFloatEdge(StyleFloatEdge::ContentBox)
310 : , mBoxDecorationBreak(StyleBoxDecorationBreak::Slice)
311 26 : , mComputedBorder(0, 0, 0, 0)
312 : {
313 26 : MOZ_COUNT_CTOR(nsStyleBorder);
314 :
315 234 : NS_FOR_CSS_HALF_CORNERS (corner) {
316 208 : mBorderRadius.Set(corner, nsStyleCoord(0, nsStyleCoord::CoordConstructor));
317 : }
318 :
319 : nscoord medium =
320 26 : (StaticPresData::Get()->GetBorderWidthTable())[NS_STYLE_BORDER_WIDTH_MEDIUM];
321 130 : NS_FOR_CSS_SIDES(side) {
322 104 : mBorderImageSlice.Set(side, nsStyleCoord(1.0f, eStyleUnit_Percent));
323 104 : mBorderImageWidth.Set(side, nsStyleCoord(1.0f, eStyleUnit_Factor));
324 104 : mBorderImageOutset.Set(side, nsStyleCoord(0.0f, eStyleUnit_Factor));
325 :
326 104 : mBorder.Side(side) = medium;
327 104 : mBorderStyle[side] = NS_STYLE_BORDER_STYLE_NONE;
328 104 : mBorderColor[side] = StyleComplexColor::CurrentColor();
329 : }
330 :
331 26 : mTwipsPerPixel = aContext->DevPixelsToAppUnits(1);
332 26 : }
333 :
334 0 : nsBorderColors::~nsBorderColors()
335 : {
336 0 : NS_CSS_DELETE_LIST_MEMBER(nsBorderColors, this, mNext);
337 0 : }
338 :
339 : nsBorderColors*
340 0 : nsBorderColors::Clone(bool aDeep) const
341 : {
342 0 : nsBorderColors* result = new nsBorderColors(mColor);
343 0 : if (MOZ_UNLIKELY(!result)) {
344 0 : return result;
345 : }
346 0 : if (aDeep) {
347 0 : NS_CSS_CLONE_LIST_MEMBER(nsBorderColors, this, mNext, result, (false));
348 : }
349 0 : return result;
350 : }
351 :
352 135 : nsStyleBorder::nsStyleBorder(const nsStyleBorder& aSrc)
353 : : mBorderColors(nullptr)
354 : , mBorderRadius(aSrc.mBorderRadius)
355 : , mBorderImageSource(aSrc.mBorderImageSource)
356 : , mBorderImageSlice(aSrc.mBorderImageSlice)
357 : , mBorderImageWidth(aSrc.mBorderImageWidth)
358 : , mBorderImageOutset(aSrc.mBorderImageOutset)
359 135 : , mBorderImageFill(aSrc.mBorderImageFill)
360 135 : , mBorderImageRepeatH(aSrc.mBorderImageRepeatH)
361 135 : , mBorderImageRepeatV(aSrc.mBorderImageRepeatV)
362 135 : , mFloatEdge(aSrc.mFloatEdge)
363 135 : , mBoxDecorationBreak(aSrc.mBoxDecorationBreak)
364 : , mComputedBorder(aSrc.mComputedBorder)
365 : , mBorder(aSrc.mBorder)
366 810 : , mTwipsPerPixel(aSrc.mTwipsPerPixel)
367 : {
368 135 : MOZ_COUNT_CTOR(nsStyleBorder);
369 135 : if (aSrc.mBorderColors) {
370 0 : NS_FOR_CSS_SIDES(side) {
371 0 : CopyBorderColorsFrom(aSrc.mBorderColors[side], side);
372 : }
373 : }
374 :
375 675 : NS_FOR_CSS_SIDES(side) {
376 540 : mBorderStyle[side] = aSrc.mBorderStyle[side];
377 540 : mBorderColor[side] = aSrc.mBorderColor[side];
378 : }
379 135 : }
380 :
381 184 : nsStyleBorder::~nsStyleBorder()
382 : {
383 92 : MOZ_COUNT_DTOR(nsStyleBorder);
384 92 : if (mBorderColors) {
385 0 : for (int32_t i = 0; i < 4; i++) {
386 0 : delete mBorderColors[i];
387 : }
388 0 : delete [] mBorderColors;
389 : }
390 92 : }
391 :
392 : void
393 0 : nsStyleBorder::FinishStyle(nsPresContext* aPresContext)
394 : {
395 0 : MOZ_ASSERT(NS_IsMainThread());
396 0 : MOZ_ASSERT(aPresContext->StyleSet()->IsServo());
397 :
398 0 : mBorderImageSource.ResolveImage(aPresContext);
399 0 : }
400 :
401 : nsMargin
402 1557 : nsStyleBorder::GetImageOutset() const
403 : {
404 : // We don't check whether there is a border-image (which is OK since
405 : // the initial values yields 0 outset) so that we don't have to
406 : // reflow to update overflow areas when an image loads.
407 1557 : nsMargin outset;
408 7785 : NS_FOR_CSS_SIDES(s) {
409 12456 : nsStyleCoord coord = mBorderImageOutset.Get(s);
410 : nscoord value;
411 6228 : switch (coord.GetUnit()) {
412 : case eStyleUnit_Coord:
413 0 : value = coord.GetCoordValue();
414 0 : break;
415 : case eStyleUnit_Factor:
416 6228 : value = coord.GetFactorValue() * mComputedBorder.Side(s);
417 6228 : break;
418 : default:
419 0 : NS_NOTREACHED("unexpected CSS unit for image outset");
420 0 : value = 0;
421 0 : break;
422 : }
423 6228 : outset.Side(s) = value;
424 : }
425 1557 : return outset;
426 : }
427 :
428 : void
429 92 : nsStyleBorder::Destroy(nsPresContext* aContext)
430 : {
431 92 : this->~nsStyleBorder();
432 : aContext->PresShell()->
433 92 : FreeByObjectID(eArenaObjectID_nsStyleBorder, this);
434 92 : }
435 :
436 : nsChangeHint
437 334 : nsStyleBorder::CalcDifference(const nsStyleBorder& aNewData) const
438 : {
439 : // FIXME: XXXbz: As in nsStylePadding::CalcDifference, many of these
440 : // differences should not need to clear descendant intrinsics.
441 : // FIXME: It would be good to return a weaker hint for the
442 : // GetComputedBorder() differences (and perhaps others) that doesn't
443 : // force reflow of all descendants, but the hint would need to force
444 : // reflow of the frame's children (see how
445 : // ReflowInput::InitResizeFlags initializes the inline-resize flag).
446 1002 : if (mTwipsPerPixel != aNewData.mTwipsPerPixel ||
447 667 : GetComputedBorder() != aNewData.GetComputedBorder() ||
448 666 : mFloatEdge != aNewData.mFloatEdge ||
449 1000 : mBorderImageOutset != aNewData.mBorderImageOutset ||
450 333 : mBoxDecorationBreak != aNewData.mBoxDecorationBreak) {
451 1 : return NS_STYLE_HINT_REFLOW;
452 : }
453 :
454 1665 : NS_FOR_CSS_SIDES(ix) {
455 : // See the explanation in nsChangeHint.h of
456 : // nsChangeHint_BorderStyleNoneChange .
457 : // Furthermore, even though we know *this* side is 0 width, just
458 : // assume a repaint hint for some other change rather than bother
459 : // tracking this result through the rest of the function.
460 1332 : if (HasVisibleStyle(ix) != aNewData.HasVisibleStyle(ix)) {
461 : return nsChangeHint_RepaintFrame |
462 0 : nsChangeHint_BorderStyleNoneChange;
463 : }
464 : }
465 :
466 : // Note that mBorderStyle stores not only the border style but also
467 : // color-related flags. Given that we've already done an mComputedBorder
468 : // comparison, border-style differences can only lead to a repaint hint. So
469 : // it's OK to just compare the values directly -- if either the actual
470 : // style or the color flags differ we want to repaint.
471 1661 : NS_FOR_CSS_SIDES(ix) {
472 2658 : if (mBorderStyle[ix] != aNewData.mBorderStyle[ix] ||
473 1329 : mBorderColor[ix] != aNewData.mBorderColor[ix]) {
474 1 : return nsChangeHint_RepaintFrame;
475 : }
476 : }
477 :
478 664 : if (mBorderRadius != aNewData.mBorderRadius ||
479 332 : !mBorderColors != !aNewData.mBorderColors) {
480 0 : return nsChangeHint_RepaintFrame;
481 : }
482 :
483 : // Loading status of the border image can be accessed in main thread only
484 : // while CalcDifference might be executed on a background thread. As a
485 : // result, we have to check mBorderImage* fields even before border image was
486 : // actually loaded.
487 332 : if (!mBorderImageSource.IsEmpty() || !aNewData.mBorderImageSource.IsEmpty()) {
488 3 : if (mBorderImageSource != aNewData.mBorderImageSource ||
489 2 : mBorderImageRepeatH != aNewData.mBorderImageRepeatH ||
490 2 : mBorderImageRepeatV != aNewData.mBorderImageRepeatV ||
491 2 : mBorderImageSlice != aNewData.mBorderImageSlice ||
492 3 : mBorderImageFill != aNewData.mBorderImageFill ||
493 1 : mBorderImageWidth != aNewData.mBorderImageWidth) {
494 0 : return nsChangeHint_RepaintFrame;
495 : }
496 : }
497 :
498 : // Note that at this point if mBorderColors is non-null so is
499 : // aNewData.mBorderColors
500 332 : if (mBorderColors) {
501 0 : NS_FOR_CSS_SIDES(ix) {
502 0 : if (!nsBorderColors::Equal(mBorderColors[ix],
503 0 : aNewData.mBorderColors[ix])) {
504 0 : return nsChangeHint_RepaintFrame;
505 : }
506 : }
507 : }
508 :
509 : // mBorder is the specified border value. Changes to this don't
510 : // need any change processing, since we operate on the computed
511 : // border values instead.
512 332 : if (mBorder != aNewData.mBorder) {
513 0 : return nsChangeHint_NeutralChange;
514 : }
515 :
516 : // mBorderImage* fields are checked only when border-image is not 'none'.
517 996 : if (mBorderImageSource != aNewData.mBorderImageSource ||
518 664 : mBorderImageRepeatH != aNewData.mBorderImageRepeatH ||
519 664 : mBorderImageRepeatV != aNewData.mBorderImageRepeatV ||
520 664 : mBorderImageSlice != aNewData.mBorderImageSlice ||
521 996 : mBorderImageFill != aNewData.mBorderImageFill ||
522 332 : mBorderImageWidth != aNewData.mBorderImageWidth) {
523 0 : return nsChangeHint_NeutralChange;
524 : }
525 :
526 332 : return nsChangeHint(0);
527 : }
528 :
529 26 : nsStyleOutline::nsStyleOutline(const nsPresContext* aContext)
530 : : mOutlineWidth((StaticPresData::Get()
531 26 : ->GetBorderWidthTable())[NS_STYLE_BORDER_WIDTH_MEDIUM])
532 : , mOutlineOffset(0)
533 : , mOutlineColor(StyleComplexColor::CurrentColor())
534 : , mOutlineStyle(NS_STYLE_BORDER_STYLE_NONE)
535 : , mActualOutlineWidth(0)
536 52 : , mTwipsPerPixel(aContext->DevPixelsToAppUnits(1))
537 : {
538 26 : MOZ_COUNT_CTOR(nsStyleOutline);
539 : // spacing values not inherited
540 52 : nsStyleCoord zero(0, nsStyleCoord::CoordConstructor);
541 234 : NS_FOR_CSS_HALF_CORNERS(corner) {
542 208 : mOutlineRadius.Set(corner, zero);
543 : }
544 26 : }
545 :
546 0 : nsStyleOutline::nsStyleOutline(const nsStyleOutline& aSrc)
547 : : mOutlineRadius(aSrc.mOutlineRadius)
548 0 : , mOutlineWidth(aSrc.mOutlineWidth)
549 0 : , mOutlineOffset(aSrc.mOutlineOffset)
550 : , mOutlineColor(aSrc.mOutlineColor)
551 0 : , mOutlineStyle(aSrc.mOutlineStyle)
552 0 : , mActualOutlineWidth(aSrc.mActualOutlineWidth)
553 0 : , mTwipsPerPixel(aSrc.mTwipsPerPixel)
554 : {
555 0 : MOZ_COUNT_CTOR(nsStyleOutline);
556 0 : }
557 :
558 : void
559 26 : nsStyleOutline::RecalcData()
560 : {
561 26 : if (NS_STYLE_BORDER_STYLE_NONE == mOutlineStyle) {
562 26 : mActualOutlineWidth = 0;
563 : } else {
564 0 : mActualOutlineWidth =
565 0 : NS_ROUND_BORDER_TO_PIXELS(mOutlineWidth, mTwipsPerPixel);
566 : }
567 26 : }
568 :
569 : nsChangeHint
570 254 : nsStyleOutline::CalcDifference(const nsStyleOutline& aNewData) const
571 : {
572 508 : if (mActualOutlineWidth != aNewData.mActualOutlineWidth ||
573 254 : (mActualOutlineWidth > 0 &&
574 0 : mOutlineOffset != aNewData.mOutlineOffset)) {
575 : return nsChangeHint_UpdateOverflow |
576 0 : nsChangeHint_SchedulePaint |
577 0 : nsChangeHint_RepaintFrame;
578 : }
579 :
580 762 : if (mOutlineStyle != aNewData.mOutlineStyle ||
581 508 : mOutlineColor != aNewData.mOutlineColor ||
582 254 : mOutlineRadius != aNewData.mOutlineRadius) {
583 0 : if (mActualOutlineWidth > 0) {
584 0 : return nsChangeHint_RepaintFrame;
585 : }
586 0 : return nsChangeHint_NeutralChange;
587 : }
588 :
589 508 : if (mOutlineWidth != aNewData.mOutlineWidth ||
590 508 : mOutlineOffset != aNewData.mOutlineOffset ||
591 254 : mTwipsPerPixel != aNewData.mTwipsPerPixel) {
592 0 : return nsChangeHint_NeutralChange;
593 : }
594 :
595 254 : return nsChangeHint(0);
596 : }
597 :
598 : // --------------------
599 : // nsStyleList
600 : //
601 3 : nsStyleList::nsStyleList(const nsPresContext* aContext)
602 3 : : mListStylePosition(NS_STYLE_LIST_STYLE_POSITION_OUTSIDE)
603 : {
604 3 : MOZ_COUNT_CTOR(nsStyleList);
605 3 : mCounterStyle = CounterStyleManager::GetDiscStyle();
606 3 : SetQuotesInitial();
607 3 : }
608 :
609 210 : nsStyleList::~nsStyleList()
610 : {
611 105 : MOZ_COUNT_DTOR(nsStyleList);
612 105 : }
613 :
614 130 : nsStyleList::nsStyleList(const nsStyleList& aSource)
615 130 : : mListStylePosition(aSource.mListStylePosition)
616 : , mListStyleImage(aSource.mListStyleImage)
617 : , mCounterStyle(aSource.mCounterStyle)
618 : , mQuotes(aSource.mQuotes)
619 130 : , mImageRegion(aSource.mImageRegion)
620 : {
621 130 : MOZ_COUNT_CTOR(nsStyleList);
622 130 : }
623 :
624 : void
625 0 : nsStyleList::FinishStyle(nsPresContext* aPresContext)
626 : {
627 0 : MOZ_ASSERT(NS_IsMainThread());
628 0 : MOZ_ASSERT(aPresContext->StyleSet()->IsServo());
629 :
630 0 : if (mListStyleImage && !mListStyleImage->IsResolved()) {
631 0 : mListStyleImage->Resolve(aPresContext);
632 : }
633 0 : mCounterStyle.Resolve(aPresContext->CounterStyleManager());
634 0 : }
635 :
636 : void
637 0 : nsStyleList::SetQuotesInherit(const nsStyleList* aOther)
638 : {
639 0 : mQuotes = aOther->mQuotes;
640 0 : }
641 :
642 : void
643 3 : nsStyleList::SetQuotesInitial()
644 : {
645 3 : if (!sInitialQuotes) {
646 : // The initial value for quotes is the en-US typographic convention:
647 : // outermost are LEFT and RIGHT DOUBLE QUOTATION MARK, alternating
648 : // with LEFT and RIGHT SINGLE QUOTATION MARK.
649 : static const char16_t initialQuotes[8] = {
650 : 0x201C, 0, 0x201D, 0, 0x2018, 0, 0x2019, 0
651 : };
652 :
653 1 : sInitialQuotes = new nsStyleQuoteValues;
654 1 : sInitialQuotes->mQuotePairs.AppendElement(
655 2 : std::make_pair(nsDependentString(&initialQuotes[0], 1),
656 3 : nsDependentString(&initialQuotes[2], 1)));
657 1 : sInitialQuotes->mQuotePairs.AppendElement(
658 2 : std::make_pair(nsDependentString(&initialQuotes[4], 1),
659 3 : nsDependentString(&initialQuotes[6], 1)));
660 : }
661 :
662 3 : mQuotes = sInitialQuotes;
663 3 : }
664 :
665 : void
666 0 : nsStyleList::SetQuotesNone()
667 : {
668 0 : if (!sNoneQuotes) {
669 0 : sNoneQuotes = new nsStyleQuoteValues;
670 : }
671 0 : mQuotes = sNoneQuotes;
672 0 : }
673 :
674 : void
675 0 : nsStyleList::SetQuotes(nsStyleQuoteValues::QuotePairArray&& aValues)
676 : {
677 0 : mQuotes = new nsStyleQuoteValues;
678 0 : mQuotes->mQuotePairs = Move(aValues);
679 0 : }
680 :
681 : const nsStyleQuoteValues::QuotePairArray&
682 0 : nsStyleList::GetQuotePairs() const
683 : {
684 0 : return mQuotes->mQuotePairs;
685 : }
686 :
687 : nsChangeHint
688 93 : nsStyleList::CalcDifference(const nsStyleList& aNewData,
689 : const nsStyleDisplay* aOldDisplay) const
690 : {
691 : // If the quotes implementation is ever going to change we might not need
692 : // a framechange here and a reflow should be sufficient. See bug 35768.
693 186 : if (mQuotes != aNewData.mQuotes &&
694 93 : (mQuotes || aNewData.mQuotes) &&
695 0 : GetQuotePairs() != aNewData.GetQuotePairs()) {
696 0 : return nsChangeHint_ReconstructFrame;
697 : }
698 93 : nsChangeHint hint = nsChangeHint(0);
699 : // Only elements whose display value is list-item can be affected by
700 : // list-style-position and list-style-type. If the old display struct
701 : // doesn't exist, assume it isn't affected by display value at all,
702 : // and thus these properties should not affect it either. This also
703 : // relies on that when the display value changes from something else
704 : // to list-item, that change itself would cause ReconstructFrame.
705 93 : if (aOldDisplay && aOldDisplay->mDisplay == StyleDisplay::ListItem) {
706 0 : if (mListStylePosition != aNewData.mListStylePosition) {
707 0 : return nsChangeHint_ReconstructFrame;
708 : }
709 0 : if (mCounterStyle != aNewData.mCounterStyle) {
710 0 : return NS_STYLE_HINT_REFLOW;
711 : }
712 186 : } else if (mListStylePosition != aNewData.mListStylePosition ||
713 93 : mCounterStyle != aNewData.mCounterStyle) {
714 0 : hint = nsChangeHint_NeutralChange;
715 : }
716 : // list-style-image and -moz-image-region may affect some XUL elements
717 : // regardless of display value, so we still need to check them.
718 93 : if (!DefinitelyEqualImages(mListStyleImage, aNewData.mListStyleImage)) {
719 12 : return NS_STYLE_HINT_REFLOW;
720 : }
721 81 : if (!mImageRegion.IsEqualInterior(aNewData.mImageRegion)) {
722 0 : if (mImageRegion.width != aNewData.mImageRegion.width ||
723 0 : mImageRegion.height != aNewData.mImageRegion.height) {
724 0 : return NS_STYLE_HINT_REFLOW;
725 : }
726 0 : return NS_STYLE_HINT_VISUAL;
727 : }
728 81 : return hint;
729 : }
730 :
731 : already_AddRefed<nsIURI>
732 0 : nsStyleList::GetListStyleImageURI() const
733 : {
734 0 : if (!mListStyleImage) {
735 0 : return nullptr;
736 : }
737 :
738 0 : nsCOMPtr<nsIURI> uri = mListStyleImage->GetImageURI();
739 0 : return uri.forget();
740 : }
741 :
742 : StaticRefPtr<nsStyleQuoteValues>
743 3 : nsStyleList::sInitialQuotes;
744 :
745 : StaticRefPtr<nsStyleQuoteValues>
746 3 : nsStyleList::sNoneQuotes;
747 :
748 :
749 : // --------------------
750 : // nsStyleXUL
751 : //
752 5 : nsStyleXUL::nsStyleXUL(const nsPresContext* aContext)
753 : : mBoxFlex(0.0f)
754 : , mBoxOrdinal(1)
755 : , mBoxAlign(StyleBoxAlign::Stretch)
756 : , mBoxDirection(StyleBoxDirection::Normal)
757 : , mBoxOrient(StyleBoxOrient::Horizontal)
758 : , mBoxPack(StyleBoxPack::Start)
759 5 : , mStackSizing(StyleStackSizing::StretchToFit)
760 : {
761 5 : MOZ_COUNT_CTOR(nsStyleXUL);
762 5 : }
763 :
764 174 : nsStyleXUL::~nsStyleXUL()
765 : {
766 87 : MOZ_COUNT_DTOR(nsStyleXUL);
767 87 : }
768 :
769 153 : nsStyleXUL::nsStyleXUL(const nsStyleXUL& aSource)
770 153 : : mBoxFlex(aSource.mBoxFlex)
771 153 : , mBoxOrdinal(aSource.mBoxOrdinal)
772 153 : , mBoxAlign(aSource.mBoxAlign)
773 153 : , mBoxDirection(aSource.mBoxDirection)
774 153 : , mBoxOrient(aSource.mBoxOrient)
775 153 : , mBoxPack(aSource.mBoxPack)
776 918 : , mStackSizing(aSource.mStackSizing)
777 : {
778 153 : MOZ_COUNT_CTOR(nsStyleXUL);
779 153 : }
780 :
781 : nsChangeHint
782 309 : nsStyleXUL::CalcDifference(const nsStyleXUL& aNewData) const
783 : {
784 618 : if (mBoxAlign == aNewData.mBoxAlign &&
785 618 : mBoxDirection == aNewData.mBoxDirection &&
786 618 : mBoxFlex == aNewData.mBoxFlex &&
787 618 : mBoxOrient == aNewData.mBoxOrient &&
788 618 : mBoxPack == aNewData.mBoxPack &&
789 618 : mBoxOrdinal == aNewData.mBoxOrdinal &&
790 309 : mStackSizing == aNewData.mStackSizing) {
791 309 : return nsChangeHint(0);
792 : }
793 0 : if (mBoxOrdinal != aNewData.mBoxOrdinal) {
794 0 : return nsChangeHint_ReconstructFrame;
795 : }
796 0 : return NS_STYLE_HINT_REFLOW;
797 : }
798 :
799 : // --------------------
800 : // nsStyleColumn
801 : //
802 : /* static */ const uint32_t nsStyleColumn::kMaxColumnCount;
803 :
804 7 : nsStyleColumn::nsStyleColumn(const nsPresContext* aContext)
805 : : mColumnCount(NS_STYLE_COLUMN_COUNT_AUTO)
806 : , mColumnWidth(eStyleUnit_Auto)
807 : , mColumnGap(eStyleUnit_Normal)
808 : , mColumnRuleColor(StyleComplexColor::CurrentColor())
809 : , mColumnRuleStyle(NS_STYLE_BORDER_STYLE_NONE)
810 : , mColumnFill(NS_STYLE_COLUMN_FILL_BALANCE)
811 : , mColumnSpan(NS_STYLE_COLUMN_SPAN_NONE)
812 : , mColumnRuleWidth((StaticPresData::Get()
813 7 : ->GetBorderWidthTable())[NS_STYLE_BORDER_WIDTH_MEDIUM])
814 14 : , mTwipsPerPixel(aContext->AppUnitsPerDevPixel())
815 : {
816 7 : MOZ_COUNT_CTOR(nsStyleColumn);
817 7 : }
818 :
819 42 : nsStyleColumn::~nsStyleColumn()
820 : {
821 21 : MOZ_COUNT_DTOR(nsStyleColumn);
822 21 : }
823 :
824 25 : nsStyleColumn::nsStyleColumn(const nsStyleColumn& aSource)
825 25 : : mColumnCount(aSource.mColumnCount)
826 : , mColumnWidth(aSource.mColumnWidth)
827 : , mColumnGap(aSource.mColumnGap)
828 : , mColumnRuleColor(aSource.mColumnRuleColor)
829 25 : , mColumnRuleStyle(aSource.mColumnRuleStyle)
830 25 : , mColumnFill(aSource.mColumnFill)
831 25 : , mColumnSpan(aSource.mColumnSpan)
832 25 : , mColumnRuleWidth(aSource.mColumnRuleWidth)
833 125 : , mTwipsPerPixel(aSource.mTwipsPerPixel)
834 : {
835 25 : MOZ_COUNT_CTOR(nsStyleColumn);
836 25 : }
837 :
838 : nsChangeHint
839 74 : nsStyleColumn::CalcDifference(const nsStyleColumn& aNewData) const
840 : {
841 148 : if ((mColumnWidth.GetUnit() == eStyleUnit_Auto)
842 148 : != (aNewData.mColumnWidth.GetUnit() == eStyleUnit_Auto) ||
843 148 : mColumnCount != aNewData.mColumnCount ||
844 74 : mColumnSpan != aNewData.mColumnSpan) {
845 : // We force column count changes to do a reframe, because it's tricky to handle
846 : // some edge cases where the column count gets smaller and content overflows.
847 : // XXX not ideal
848 0 : return nsChangeHint_ReconstructFrame;
849 : }
850 :
851 222 : if (mColumnWidth != aNewData.mColumnWidth ||
852 148 : mColumnGap != aNewData.mColumnGap ||
853 74 : mColumnFill != aNewData.mColumnFill) {
854 0 : return NS_STYLE_HINT_REFLOW;
855 : }
856 :
857 222 : if (GetComputedColumnRuleWidth() != aNewData.GetComputedColumnRuleWidth() ||
858 148 : mColumnRuleStyle != aNewData.mColumnRuleStyle ||
859 74 : mColumnRuleColor != aNewData.mColumnRuleColor) {
860 0 : return NS_STYLE_HINT_VISUAL;
861 : }
862 :
863 : // XXX Is it right that we never check mTwipsPerPixel to return a
864 : // non-nsChangeHint_NeutralChange hint?
865 148 : if (mColumnRuleWidth != aNewData.mColumnRuleWidth ||
866 74 : mTwipsPerPixel != aNewData.mTwipsPerPixel) {
867 0 : return nsChangeHint_NeutralChange;
868 : }
869 :
870 74 : return nsChangeHint(0);
871 : }
872 :
873 : // --------------------
874 : // nsStyleSVG
875 : //
876 24 : nsStyleSVG::nsStyleSVG(const nsPresContext* aContext)
877 : : mFill(eStyleSVGPaintType_Color) // Will be initialized to NS_RGB(0, 0, 0)
878 : , mStroke(eStyleSVGPaintType_None)
879 : , mStrokeDashoffset(0, nsStyleCoord::CoordConstructor)
880 : , mStrokeWidth(nsPresContext::CSSPixelsToAppUnits(1), nsStyleCoord::CoordConstructor)
881 : , mFillOpacity(1.0f)
882 : , mStrokeMiterlimit(4.0f)
883 : , mStrokeOpacity(1.0f)
884 : , mClipRule(StyleFillRule::Nonzero)
885 : , mColorInterpolation(NS_STYLE_COLOR_INTERPOLATION_SRGB)
886 : , mColorInterpolationFilters(NS_STYLE_COLOR_INTERPOLATION_LINEARRGB)
887 : , mFillRule(StyleFillRule::Nonzero)
888 : , mPaintOrder(NS_STYLE_PAINT_ORDER_NORMAL)
889 : , mShapeRendering(NS_STYLE_SHAPE_RENDERING_AUTO)
890 : , mStrokeLinecap(NS_STYLE_STROKE_LINECAP_BUTT)
891 : , mStrokeLinejoin(NS_STYLE_STROKE_LINEJOIN_MITER)
892 : , mTextAnchor(NS_STYLE_TEXT_ANCHOR_START)
893 : , mContextPropsBits(0)
894 : , mContextFlags((eStyleSVGOpacitySource_Normal << FILL_OPACITY_SOURCE_SHIFT) |
895 24 : (eStyleSVGOpacitySource_Normal << STROKE_OPACITY_SOURCE_SHIFT))
896 : {
897 24 : MOZ_COUNT_CTOR(nsStyleSVG);
898 24 : }
899 :
900 36 : nsStyleSVG::~nsStyleSVG()
901 : {
902 18 : MOZ_COUNT_DTOR(nsStyleSVG);
903 18 : }
904 :
905 66 : nsStyleSVG::nsStyleSVG(const nsStyleSVG& aSource)
906 : : mFill(aSource.mFill)
907 : , mStroke(aSource.mStroke)
908 : , mMarkerEnd(aSource.mMarkerEnd)
909 : , mMarkerMid(aSource.mMarkerMid)
910 : , mMarkerStart(aSource.mMarkerStart)
911 : , mStrokeDasharray(aSource.mStrokeDasharray)
912 : , mContextProps(aSource.mContextProps)
913 : , mStrokeDashoffset(aSource.mStrokeDashoffset)
914 : , mStrokeWidth(aSource.mStrokeWidth)
915 66 : , mFillOpacity(aSource.mFillOpacity)
916 66 : , mStrokeMiterlimit(aSource.mStrokeMiterlimit)
917 66 : , mStrokeOpacity(aSource.mStrokeOpacity)
918 66 : , mClipRule(aSource.mClipRule)
919 66 : , mColorInterpolation(aSource.mColorInterpolation)
920 66 : , mColorInterpolationFilters(aSource.mColorInterpolationFilters)
921 66 : , mFillRule(aSource.mFillRule)
922 66 : , mPaintOrder(aSource.mPaintOrder)
923 66 : , mShapeRendering(aSource.mShapeRendering)
924 66 : , mStrokeLinecap(aSource.mStrokeLinecap)
925 66 : , mStrokeLinejoin(aSource.mStrokeLinejoin)
926 66 : , mTextAnchor(aSource.mTextAnchor)
927 66 : , mContextPropsBits(aSource.mContextPropsBits)
928 924 : , mContextFlags(aSource.mContextFlags)
929 : {
930 66 : MOZ_COUNT_CTOR(nsStyleSVG);
931 66 : }
932 :
933 : static bool
934 0 : PaintURIChanged(const nsStyleSVGPaint& aPaint1, const nsStyleSVGPaint& aPaint2)
935 : {
936 0 : if (aPaint1.Type() != aPaint2.Type()) {
937 0 : return aPaint1.Type() == eStyleSVGPaintType_Server ||
938 0 : aPaint2.Type() == eStyleSVGPaintType_Server;
939 : }
940 0 : return aPaint1.Type() == eStyleSVGPaintType_Server &&
941 0 : !DefinitelyEqualURIs(aPaint1.GetPaintServer(),
942 0 : aPaint2.GetPaintServer());
943 : }
944 :
945 : nsChangeHint
946 16 : nsStyleSVG::CalcDifference(const nsStyleSVG& aNewData) const
947 : {
948 16 : nsChangeHint hint = nsChangeHint(0);
949 :
950 48 : if (!DefinitelyEqualURIs(mMarkerEnd, aNewData.mMarkerEnd) ||
951 32 : !DefinitelyEqualURIs(mMarkerMid, aNewData.mMarkerMid) ||
952 16 : !DefinitelyEqualURIs(mMarkerStart, aNewData.mMarkerStart)) {
953 : // Markers currently contribute to SVGGeometryFrame::mRect,
954 : // so we need a reflow as well as a repaint. No intrinsic sizes need
955 : // to change, so nsChangeHint_NeedReflow is sufficient.
956 : return nsChangeHint_UpdateEffects |
957 : nsChangeHint_NeedReflow |
958 0 : nsChangeHint_NeedDirtyReflow | // XXX remove me: bug 876085
959 0 : nsChangeHint_RepaintFrame;
960 : }
961 :
962 48 : if (mFill != aNewData.mFill ||
963 32 : mStroke != aNewData.mStroke ||
964 48 : mFillOpacity != aNewData.mFillOpacity ||
965 16 : mStrokeOpacity != aNewData.mStrokeOpacity) {
966 0 : hint |= nsChangeHint_RepaintFrame;
967 0 : if (HasStroke() != aNewData.HasStroke() ||
968 0 : (!HasStroke() && HasFill() != aNewData.HasFill())) {
969 : // Frame bounds and overflow rects depend on whether we "have" fill or
970 : // stroke. Whether we have stroke or not just changed, or else we have no
971 : // stroke (in which case whether we have fill or not is significant to frame
972 : // bounds) and whether we have fill or not just changed. In either case we
973 : // need to reflow so the frame rect is updated.
974 : // XXXperf this is a waste on non SVGGeometryFrames.
975 : hint |= nsChangeHint_NeedReflow |
976 0 : nsChangeHint_NeedDirtyReflow; // XXX remove me: bug 876085
977 : }
978 0 : if (PaintURIChanged(mFill, aNewData.mFill) ||
979 0 : PaintURIChanged(mStroke, aNewData.mStroke)) {
980 0 : hint |= nsChangeHint_UpdateEffects;
981 : }
982 : }
983 :
984 : // Stroke currently contributes to SVGGeometryFrame::mRect, so
985 : // we need a reflow here. No intrinsic sizes need to change, so
986 : // nsChangeHint_NeedReflow is sufficient.
987 : // Note that stroke-dashoffset does not affect SVGGeometryFrame::mRect.
988 : // text-anchor changes also require a reflow since it changes frames' rects.
989 48 : if (mStrokeWidth != aNewData.mStrokeWidth ||
990 32 : mStrokeMiterlimit != aNewData.mStrokeMiterlimit ||
991 32 : mStrokeLinecap != aNewData.mStrokeLinecap ||
992 48 : mStrokeLinejoin != aNewData.mStrokeLinejoin ||
993 16 : mTextAnchor != aNewData.mTextAnchor) {
994 : return hint |
995 : nsChangeHint_NeedReflow |
996 0 : nsChangeHint_NeedDirtyReflow | // XXX remove me: bug 876085
997 0 : nsChangeHint_RepaintFrame;
998 : }
999 :
1000 16 : if (hint & nsChangeHint_RepaintFrame) {
1001 0 : return hint; // we don't add anything else below
1002 : }
1003 :
1004 48 : if ( mStrokeDashoffset != aNewData.mStrokeDashoffset ||
1005 32 : mClipRule != aNewData.mClipRule ||
1006 32 : mColorInterpolation != aNewData.mColorInterpolation ||
1007 32 : mColorInterpolationFilters != aNewData.mColorInterpolationFilters ||
1008 32 : mFillRule != aNewData.mFillRule ||
1009 32 : mPaintOrder != aNewData.mPaintOrder ||
1010 32 : mShapeRendering != aNewData.mShapeRendering ||
1011 32 : mStrokeDasharray != aNewData.mStrokeDasharray ||
1012 48 : mContextFlags != aNewData.mContextFlags ||
1013 16 : mContextPropsBits != aNewData.mContextPropsBits) {
1014 0 : return hint | nsChangeHint_RepaintFrame;
1015 : }
1016 :
1017 16 : if (!hint) {
1018 16 : if (mContextProps != aNewData.mContextProps) {
1019 0 : hint = nsChangeHint_NeutralChange;
1020 : }
1021 : }
1022 :
1023 16 : return hint;
1024 : }
1025 :
1026 : // --------------------
1027 : // StyleBasicShape
1028 :
1029 : nsCSSKeyword
1030 0 : StyleBasicShape::GetShapeTypeName() const
1031 : {
1032 0 : switch (mType) {
1033 : case StyleBasicShapeType::Polygon:
1034 0 : return eCSSKeyword_polygon;
1035 : case StyleBasicShapeType::Circle:
1036 0 : return eCSSKeyword_circle;
1037 : case StyleBasicShapeType::Ellipse:
1038 0 : return eCSSKeyword_ellipse;
1039 : case StyleBasicShapeType::Inset:
1040 0 : return eCSSKeyword_inset;
1041 : }
1042 0 : NS_NOTREACHED("unexpected type");
1043 0 : return eCSSKeyword_UNKNOWN;
1044 : }
1045 :
1046 : // --------------------
1047 : // nsStyleFilter
1048 : //
1049 0 : nsStyleFilter::nsStyleFilter()
1050 : : mType(NS_STYLE_FILTER_NONE)
1051 0 : , mDropShadow(nullptr)
1052 : {
1053 0 : MOZ_COUNT_CTOR(nsStyleFilter);
1054 0 : }
1055 :
1056 0 : nsStyleFilter::nsStyleFilter(const nsStyleFilter& aSource)
1057 : : mType(NS_STYLE_FILTER_NONE)
1058 0 : , mDropShadow(nullptr)
1059 : {
1060 0 : MOZ_COUNT_CTOR(nsStyleFilter);
1061 0 : if (aSource.mType == NS_STYLE_FILTER_URL) {
1062 0 : SetURL(aSource.mURL);
1063 0 : } else if (aSource.mType == NS_STYLE_FILTER_DROP_SHADOW) {
1064 0 : SetDropShadow(aSource.mDropShadow);
1065 0 : } else if (aSource.mType != NS_STYLE_FILTER_NONE) {
1066 0 : SetFilterParameter(aSource.mFilterParameter, aSource.mType);
1067 : }
1068 0 : }
1069 :
1070 0 : nsStyleFilter::~nsStyleFilter()
1071 : {
1072 0 : ReleaseRef();
1073 0 : MOZ_COUNT_DTOR(nsStyleFilter);
1074 0 : }
1075 :
1076 : nsStyleFilter&
1077 0 : nsStyleFilter::operator=(const nsStyleFilter& aOther)
1078 : {
1079 0 : if (this == &aOther) {
1080 0 : return *this;
1081 : }
1082 :
1083 0 : if (aOther.mType == NS_STYLE_FILTER_URL) {
1084 0 : SetURL(aOther.mURL);
1085 0 : } else if (aOther.mType == NS_STYLE_FILTER_DROP_SHADOW) {
1086 0 : SetDropShadow(aOther.mDropShadow);
1087 0 : } else if (aOther.mType != NS_STYLE_FILTER_NONE) {
1088 0 : SetFilterParameter(aOther.mFilterParameter, aOther.mType);
1089 : } else {
1090 0 : ReleaseRef();
1091 0 : mType = NS_STYLE_FILTER_NONE;
1092 : }
1093 :
1094 0 : return *this;
1095 : }
1096 :
1097 : bool
1098 0 : nsStyleFilter::operator==(const nsStyleFilter& aOther) const
1099 : {
1100 0 : if (mType != aOther.mType) {
1101 0 : return false;
1102 : }
1103 :
1104 0 : if (mType == NS_STYLE_FILTER_URL) {
1105 0 : return DefinitelyEqualURIs(mURL, aOther.mURL);
1106 0 : } else if (mType == NS_STYLE_FILTER_DROP_SHADOW) {
1107 0 : return *mDropShadow == *aOther.mDropShadow;
1108 0 : } else if (mType != NS_STYLE_FILTER_NONE) {
1109 0 : return mFilterParameter == aOther.mFilterParameter;
1110 : }
1111 :
1112 0 : return true;
1113 : }
1114 :
1115 : void
1116 0 : nsStyleFilter::ReleaseRef()
1117 : {
1118 0 : if (mType == NS_STYLE_FILTER_DROP_SHADOW) {
1119 0 : NS_ASSERTION(mDropShadow, "expected pointer");
1120 0 : mDropShadow->Release();
1121 0 : } else if (mType == NS_STYLE_FILTER_URL) {
1122 0 : NS_ASSERTION(mURL, "expected pointer");
1123 0 : mURL->Release();
1124 : }
1125 0 : mURL = nullptr;
1126 0 : }
1127 :
1128 : void
1129 0 : nsStyleFilter::SetFilterParameter(const nsStyleCoord& aFilterParameter,
1130 : int32_t aType)
1131 : {
1132 0 : ReleaseRef();
1133 0 : mFilterParameter = aFilterParameter;
1134 0 : mType = aType;
1135 0 : }
1136 :
1137 : bool
1138 0 : nsStyleFilter::SetURL(css::URLValue* aURL)
1139 : {
1140 0 : ReleaseRef();
1141 0 : mURL = aURL;
1142 0 : mURL->AddRef();
1143 0 : mType = NS_STYLE_FILTER_URL;
1144 0 : return true;
1145 : }
1146 :
1147 : void
1148 0 : nsStyleFilter::SetDropShadow(nsCSSShadowArray* aDropShadow)
1149 : {
1150 0 : NS_ASSERTION(aDropShadow, "expected pointer");
1151 0 : ReleaseRef();
1152 0 : mDropShadow = aDropShadow;
1153 0 : mDropShadow->AddRef();
1154 0 : mType = NS_STYLE_FILTER_DROP_SHADOW;
1155 0 : }
1156 :
1157 : // --------------------
1158 : // nsStyleSVGReset
1159 : //
1160 26 : nsStyleSVGReset::nsStyleSVGReset(const nsPresContext* aContext)
1161 : : mMask(nsStyleImageLayers::LayerType::Mask)
1162 : , mStopColor(NS_RGB(0, 0, 0))
1163 : , mFloodColor(NS_RGB(0, 0, 0))
1164 : , mLightingColor(NS_RGB(255, 255, 255))
1165 : , mStopOpacity(1.0f)
1166 : , mFloodOpacity(1.0f)
1167 : , mDominantBaseline(NS_STYLE_DOMINANT_BASELINE_AUTO)
1168 : , mVectorEffect(NS_STYLE_VECTOR_EFFECT_NONE)
1169 26 : , mMaskType(NS_STYLE_MASK_TYPE_LUMINANCE)
1170 : {
1171 26 : MOZ_COUNT_CTOR(nsStyleSVGReset);
1172 26 : }
1173 :
1174 4 : nsStyleSVGReset::~nsStyleSVGReset()
1175 : {
1176 2 : MOZ_COUNT_DTOR(nsStyleSVGReset);
1177 2 : }
1178 :
1179 4 : nsStyleSVGReset::nsStyleSVGReset(const nsStyleSVGReset& aSource)
1180 : : mMask(aSource.mMask)
1181 : , mClipPath(aSource.mClipPath)
1182 4 : , mStopColor(aSource.mStopColor)
1183 4 : , mFloodColor(aSource.mFloodColor)
1184 4 : , mLightingColor(aSource.mLightingColor)
1185 4 : , mStopOpacity(aSource.mStopOpacity)
1186 4 : , mFloodOpacity(aSource.mFloodOpacity)
1187 4 : , mDominantBaseline(aSource.mDominantBaseline)
1188 4 : , mVectorEffect(aSource.mVectorEffect)
1189 32 : , mMaskType(aSource.mMaskType)
1190 : {
1191 4 : MOZ_COUNT_CTOR(nsStyleSVGReset);
1192 4 : }
1193 :
1194 : void
1195 2 : nsStyleSVGReset::Destroy(nsPresContext* aContext)
1196 : {
1197 2 : this->~nsStyleSVGReset();
1198 : aContext->PresShell()->
1199 2 : FreeByObjectID(mozilla::eArenaObjectID_nsStyleSVGReset, this);
1200 2 : }
1201 :
1202 : void
1203 0 : nsStyleSVGReset::FinishStyle(nsPresContext* aPresContext)
1204 : {
1205 0 : MOZ_ASSERT(NS_IsMainThread());
1206 0 : MOZ_ASSERT(aPresContext->StyleSet()->IsServo());
1207 :
1208 0 : mMask.ResolveImages(aPresContext);
1209 0 : }
1210 :
1211 : nsChangeHint
1212 294 : nsStyleSVGReset::CalcDifference(const nsStyleSVGReset& aNewData) const
1213 : {
1214 294 : nsChangeHint hint = nsChangeHint(0);
1215 :
1216 294 : if (!mClipPath.DefinitelyEquals(aNewData.mClipPath)) {
1217 : hint |= nsChangeHint_UpdateEffects |
1218 0 : nsChangeHint_RepaintFrame;
1219 : // clip-path changes require that we update the PreEffectsBBoxProperty,
1220 : // which is done during overflow computation.
1221 0 : hint |= nsChangeHint_UpdateOverflow;
1222 : }
1223 :
1224 294 : if (mDominantBaseline != aNewData.mDominantBaseline) {
1225 : // XXXjwatt: why NS_STYLE_HINT_REFLOW? Isn't that excessive?
1226 0 : hint |= NS_STYLE_HINT_REFLOW;
1227 294 : } else if (mVectorEffect != aNewData.mVectorEffect) {
1228 : // Stroke currently affects SVGGeometryFrame::mRect, and
1229 : // vector-effect affect stroke. As a result we need to reflow if
1230 : // vector-effect changes in order to have SVGGeometryFrame::
1231 : // ReflowSVG called to update its mRect. No intrinsic sizes need
1232 : // to change so nsChangeHint_NeedReflow is sufficient.
1233 : hint |= nsChangeHint_NeedReflow |
1234 : nsChangeHint_NeedDirtyReflow | // XXX remove me: bug 876085
1235 0 : nsChangeHint_RepaintFrame;
1236 588 : } else if (mStopColor != aNewData.mStopColor ||
1237 588 : mFloodColor != aNewData.mFloodColor ||
1238 588 : mLightingColor != aNewData.mLightingColor ||
1239 588 : mStopOpacity != aNewData.mStopOpacity ||
1240 588 : mFloodOpacity != aNewData.mFloodOpacity ||
1241 294 : mMaskType != aNewData.mMaskType) {
1242 0 : hint |= nsChangeHint_RepaintFrame;
1243 : }
1244 :
1245 294 : if (HasMask() != aNewData.HasMask()) {
1246 : // A change from/to being a containing block for position:fixed.
1247 1 : hint |= nsChangeHint_UpdateContainingBlock;
1248 : }
1249 :
1250 : hint |= mMask.CalcDifference(aNewData.mMask,
1251 294 : nsStyleImageLayers::LayerType::Mask);
1252 :
1253 294 : return hint;
1254 : }
1255 :
1256 : bool
1257 3936 : nsStyleSVGReset::HasMask() const
1258 : {
1259 7838 : for (uint32_t i = 0; i < mMask.mImageCount; i++) {
1260 3936 : if (!mMask.mLayers[i].mImage.IsEmpty()) {
1261 34 : return true;
1262 : }
1263 : }
1264 :
1265 3902 : return false;
1266 : }
1267 :
1268 : // nsStyleSVGPaint implementation
1269 180 : nsStyleSVGPaint::nsStyleSVGPaint(nsStyleSVGPaintType aType)
1270 : : mType(aType)
1271 : , mFallbackType(eStyleSVGFallbackType_NotSet)
1272 180 : , mFallbackColor(NS_RGB(0, 0, 0))
1273 : {
1274 180 : MOZ_ASSERT(aType == nsStyleSVGPaintType(0) ||
1275 : aType == eStyleSVGPaintType_None ||
1276 : aType == eStyleSVGPaintType_Color);
1277 180 : mPaint.mColor = NS_RGB(0, 0, 0);
1278 180 : }
1279 :
1280 132 : nsStyleSVGPaint::nsStyleSVGPaint(const nsStyleSVGPaint& aSource)
1281 132 : : nsStyleSVGPaint(nsStyleSVGPaintType(0))
1282 : {
1283 132 : Assign(aSource);
1284 132 : }
1285 :
1286 72 : nsStyleSVGPaint::~nsStyleSVGPaint()
1287 : {
1288 36 : Reset();
1289 36 : }
1290 :
1291 : void
1292 235 : nsStyleSVGPaint::Reset()
1293 : {
1294 235 : switch (mType) {
1295 : case eStyleSVGPaintType_None:
1296 19 : break;
1297 : case eStyleSVGPaintType_Color:
1298 84 : mPaint.mColor = NS_RGB(0, 0, 0);
1299 84 : break;
1300 : case eStyleSVGPaintType_Server:
1301 0 : mPaint.mPaintServer->Release();
1302 0 : mPaint.mPaintServer = nullptr;
1303 : MOZ_FALLTHROUGH;
1304 : case eStyleSVGPaintType_ContextFill:
1305 : case eStyleSVGPaintType_ContextStroke:
1306 0 : mFallbackType = eStyleSVGFallbackType_NotSet;
1307 0 : mFallbackColor = NS_RGB(0, 0, 0);
1308 0 : break;
1309 : }
1310 235 : mType = nsStyleSVGPaintType(0);
1311 235 : }
1312 :
1313 : nsStyleSVGPaint&
1314 0 : nsStyleSVGPaint::operator=(const nsStyleSVGPaint& aOther)
1315 : {
1316 0 : if (this != &aOther) {
1317 0 : Assign(aOther);
1318 : }
1319 0 : return *this;
1320 : }
1321 :
1322 : void
1323 132 : nsStyleSVGPaint::Assign(const nsStyleSVGPaint& aOther)
1324 : {
1325 132 : MOZ_ASSERT(aOther.mType != nsStyleSVGPaintType(0),
1326 : "shouldn't copy uninitialized nsStyleSVGPaint");
1327 :
1328 132 : switch (aOther.mType) {
1329 : case eStyleSVGPaintType_None:
1330 66 : SetNone();
1331 66 : break;
1332 : case eStyleSVGPaintType_Color:
1333 66 : SetColor(aOther.mPaint.mColor);
1334 66 : break;
1335 : case eStyleSVGPaintType_Server:
1336 0 : SetPaintServer(aOther.mPaint.mPaintServer,
1337 0 : aOther.mFallbackType,
1338 0 : aOther.mFallbackColor);
1339 0 : break;
1340 : case eStyleSVGPaintType_ContextFill:
1341 : case eStyleSVGPaintType_ContextStroke:
1342 0 : SetContextValue(aOther.mType,
1343 0 : aOther.mFallbackType,
1344 0 : aOther.mFallbackColor);
1345 0 : break;
1346 : }
1347 132 : }
1348 :
1349 : void
1350 67 : nsStyleSVGPaint::SetNone()
1351 : {
1352 67 : Reset();
1353 67 : mType = eStyleSVGPaintType_None;
1354 67 : }
1355 :
1356 : void
1357 22 : nsStyleSVGPaint::SetContextValue(nsStyleSVGPaintType aType,
1358 : nsStyleSVGFallbackType aFallbackType,
1359 : nscolor aFallbackColor)
1360 : {
1361 22 : MOZ_ASSERT(aType == eStyleSVGPaintType_ContextFill ||
1362 : aType == eStyleSVGPaintType_ContextStroke);
1363 22 : Reset();
1364 22 : mType = aType;
1365 22 : mFallbackType = aFallbackType;
1366 22 : mFallbackColor = aFallbackColor;
1367 22 : }
1368 :
1369 : void
1370 110 : nsStyleSVGPaint::SetColor(nscolor aColor)
1371 : {
1372 110 : Reset();
1373 110 : mType = eStyleSVGPaintType_Color;
1374 110 : mPaint.mColor = aColor;
1375 110 : }
1376 :
1377 : void
1378 0 : nsStyleSVGPaint::SetPaintServer(css::URLValue* aPaintServer,
1379 : nsStyleSVGFallbackType aFallbackType,
1380 : nscolor aFallbackColor)
1381 : {
1382 0 : MOZ_ASSERT(aPaintServer);
1383 0 : Reset();
1384 0 : mType = eStyleSVGPaintType_Server;
1385 0 : mPaint.mPaintServer = aPaintServer;
1386 0 : mPaint.mPaintServer->AddRef();
1387 0 : mFallbackType = aFallbackType;
1388 0 : mFallbackColor = aFallbackColor;
1389 0 : }
1390 :
1391 32 : bool nsStyleSVGPaint::operator==(const nsStyleSVGPaint& aOther) const
1392 : {
1393 32 : if (mType != aOther.mType) {
1394 0 : return false;
1395 : }
1396 32 : switch (mType) {
1397 : case eStyleSVGPaintType_Color:
1398 16 : return mPaint.mColor == aOther.mPaint.mColor;
1399 : case eStyleSVGPaintType_Server:
1400 0 : return DefinitelyEqualURIs(mPaint.mPaintServer,
1401 0 : aOther.mPaint.mPaintServer) &&
1402 0 : mFallbackType == aOther.mFallbackType &&
1403 0 : mFallbackColor == aOther.mFallbackColor;
1404 : case eStyleSVGPaintType_ContextFill:
1405 : case eStyleSVGPaintType_ContextStroke:
1406 0 : return mFallbackType == aOther.mFallbackType &&
1407 0 : mFallbackColor == aOther.mFallbackColor;
1408 : default:
1409 16 : MOZ_ASSERT(mType == eStyleSVGPaintType_None,
1410 : "Unexpected SVG paint type");
1411 16 : return true;
1412 : }
1413 : }
1414 :
1415 : // --------------------
1416 : // nsStylePosition
1417 : //
1418 26 : nsStylePosition::nsStylePosition(const nsPresContext* aContext)
1419 : : mWidth(eStyleUnit_Auto)
1420 : , mMinWidth(eStyleUnit_Auto)
1421 : , mMaxWidth(eStyleUnit_None)
1422 : , mHeight(eStyleUnit_Auto)
1423 : , mMinHeight(eStyleUnit_Auto)
1424 : , mMaxHeight(eStyleUnit_None)
1425 : , mFlexBasis(eStyleUnit_Auto)
1426 : , mGridAutoColumnsMin(eStyleUnit_Auto)
1427 : , mGridAutoColumnsMax(eStyleUnit_Auto)
1428 : , mGridAutoRowsMin(eStyleUnit_Auto)
1429 : , mGridAutoRowsMax(eStyleUnit_Auto)
1430 : , mGridAutoFlow(NS_STYLE_GRID_AUTO_FLOW_ROW)
1431 : , mBoxSizing(StyleBoxSizing::Content)
1432 : , mAlignContent(NS_STYLE_ALIGN_NORMAL)
1433 : , mAlignItems(NS_STYLE_ALIGN_NORMAL)
1434 : , mAlignSelf(NS_STYLE_ALIGN_AUTO)
1435 : , mJustifyContent(NS_STYLE_JUSTIFY_NORMAL)
1436 : , mJustifyItems(NS_STYLE_JUSTIFY_AUTO)
1437 : , mJustifySelf(NS_STYLE_JUSTIFY_AUTO)
1438 : , mFlexDirection(NS_STYLE_FLEX_DIRECTION_ROW)
1439 : , mFlexWrap(NS_STYLE_FLEX_WRAP_NOWRAP)
1440 : , mObjectFit(NS_STYLE_OBJECT_FIT_FILL)
1441 : , mOrder(NS_STYLE_ORDER_INITIAL)
1442 : , mFlexGrow(0.0f)
1443 : , mFlexShrink(1.0f)
1444 : , mZIndex(eStyleUnit_Auto)
1445 : , mGridColumnGap(nscoord(0), nsStyleCoord::CoordConstructor)
1446 26 : , mGridRowGap(nscoord(0), nsStyleCoord::CoordConstructor)
1447 : {
1448 26 : MOZ_COUNT_CTOR(nsStylePosition);
1449 :
1450 : // positioning values not inherited
1451 :
1452 26 : mObjectPosition.SetInitialPercentValues(0.5f);
1453 :
1454 52 : nsStyleCoord autoCoord(eStyleUnit_Auto);
1455 130 : NS_FOR_CSS_SIDES(side) {
1456 104 : mOffset.Set(side, autoCoord);
1457 : }
1458 :
1459 : // The initial value of grid-auto-columns and grid-auto-rows is 'auto',
1460 : // which computes to 'minmax(auto, auto)'.
1461 :
1462 : // Other members get their default constructors
1463 : // which initialize them to representations of their respective initial value.
1464 : // mGridTemplateAreas: nullptr for 'none'
1465 : // mGridTemplate{Rows,Columns}: false and empty arrays for 'none'
1466 : // mGrid{Column,Row}{Start,End}: false/0/empty values for 'auto'
1467 26 : }
1468 :
1469 282 : nsStylePosition::~nsStylePosition()
1470 : {
1471 141 : MOZ_COUNT_DTOR(nsStylePosition);
1472 141 : }
1473 :
1474 255 : nsStylePosition::nsStylePosition(const nsStylePosition& aSource)
1475 : : mObjectPosition(aSource.mObjectPosition)
1476 : , mOffset(aSource.mOffset)
1477 : , mWidth(aSource.mWidth)
1478 : , mMinWidth(aSource.mMinWidth)
1479 : , mMaxWidth(aSource.mMaxWidth)
1480 : , mHeight(aSource.mHeight)
1481 : , mMinHeight(aSource.mMinHeight)
1482 : , mMaxHeight(aSource.mMaxHeight)
1483 : , mFlexBasis(aSource.mFlexBasis)
1484 : , mGridAutoColumnsMin(aSource.mGridAutoColumnsMin)
1485 : , mGridAutoColumnsMax(aSource.mGridAutoColumnsMax)
1486 : , mGridAutoRowsMin(aSource.mGridAutoRowsMin)
1487 : , mGridAutoRowsMax(aSource.mGridAutoRowsMax)
1488 255 : , mGridAutoFlow(aSource.mGridAutoFlow)
1489 255 : , mBoxSizing(aSource.mBoxSizing)
1490 255 : , mAlignContent(aSource.mAlignContent)
1491 255 : , mAlignItems(aSource.mAlignItems)
1492 255 : , mAlignSelf(aSource.mAlignSelf)
1493 255 : , mJustifyContent(aSource.mJustifyContent)
1494 255 : , mJustifyItems(aSource.mJustifyItems)
1495 255 : , mJustifySelf(aSource.mJustifySelf)
1496 255 : , mFlexDirection(aSource.mFlexDirection)
1497 255 : , mFlexWrap(aSource.mFlexWrap)
1498 255 : , mObjectFit(aSource.mObjectFit)
1499 255 : , mOrder(aSource.mOrder)
1500 255 : , mFlexGrow(aSource.mFlexGrow)
1501 255 : , mFlexShrink(aSource.mFlexShrink)
1502 : , mZIndex(aSource.mZIndex)
1503 : , mGridTemplateColumns(aSource.mGridTemplateColumns)
1504 : , mGridTemplateRows(aSource.mGridTemplateRows)
1505 : , mGridTemplateAreas(aSource.mGridTemplateAreas)
1506 : , mGridColumnStart(aSource.mGridColumnStart)
1507 : , mGridColumnEnd(aSource.mGridColumnEnd)
1508 : , mGridRowStart(aSource.mGridRowStart)
1509 : , mGridRowEnd(aSource.mGridRowEnd)
1510 : , mGridColumnGap(aSource.mGridColumnGap)
1511 3825 : , mGridRowGap(aSource.mGridRowGap)
1512 : {
1513 255 : MOZ_COUNT_CTOR(nsStylePosition);
1514 255 : }
1515 :
1516 : static bool
1517 0 : IsAutonessEqual(const nsStyleSides& aSides1, const nsStyleSides& aSides2)
1518 : {
1519 0 : NS_FOR_CSS_SIDES(side) {
1520 0 : if ((aSides1.GetUnit(side) == eStyleUnit_Auto) !=
1521 0 : (aSides2.GetUnit(side) == eStyleUnit_Auto)) {
1522 0 : return false;
1523 : }
1524 : }
1525 0 : return true;
1526 : }
1527 :
1528 : nsChangeHint
1529 289 : nsStylePosition::CalcDifference(const nsStylePosition& aNewData,
1530 : const nsStyleVisibility* aOldStyleVisibility) const
1531 : {
1532 289 : nsChangeHint hint = nsChangeHint(0);
1533 :
1534 : // Changes to "z-index" require a repaint.
1535 289 : if (mZIndex != aNewData.mZIndex) {
1536 1 : hint |= nsChangeHint_RepaintFrame;
1537 : }
1538 :
1539 : // Changes to "object-fit" & "object-position" require a repaint. They
1540 : // may also require a reflow, if we have a nsSubDocumentFrame, so that we
1541 : // can adjust the size & position of the subdocument.
1542 578 : if (mObjectFit != aNewData.mObjectFit ||
1543 289 : mObjectPosition != aNewData.mObjectPosition) {
1544 : hint |= nsChangeHint_RepaintFrame |
1545 0 : nsChangeHint_NeedReflow;
1546 : }
1547 :
1548 289 : if (mOrder != aNewData.mOrder) {
1549 : // "order" impacts both layout order and stacking order, so we need both a
1550 : // reflow and a repaint when it changes. (Technically, we only need a
1551 : // reflow if we're in a multi-line flexbox (which we can't be sure about,
1552 : // since that's determined by styling on our parent) -- there, "order" can
1553 : // affect which flex line we end up on, & hence can affect our sizing by
1554 : // changing the group of flex items we're competing with for space.)
1555 : return hint |
1556 0 : nsChangeHint_RepaintFrame |
1557 0 : nsChangeHint_AllReflowHints;
1558 : }
1559 :
1560 289 : if (mBoxSizing != aNewData.mBoxSizing) {
1561 : // Can affect both widths and heights; just a bad scene.
1562 0 : return hint |
1563 0 : nsChangeHint_AllReflowHints;
1564 : }
1565 :
1566 : // Properties that apply to flex items:
1567 : // XXXdholbert These should probably be more targeted (bug 819536)
1568 867 : if (mAlignSelf != aNewData.mAlignSelf ||
1569 578 : mFlexBasis != aNewData.mFlexBasis ||
1570 867 : mFlexGrow != aNewData.mFlexGrow ||
1571 289 : mFlexShrink != aNewData.mFlexShrink) {
1572 0 : return hint |
1573 0 : nsChangeHint_AllReflowHints;
1574 : }
1575 :
1576 : // Properties that apply to flex containers:
1577 : // - flex-direction can swap a flex container between vertical & horizontal.
1578 : // - align-items can change the sizing of a flex container & the positioning
1579 : // of its children.
1580 : // - flex-wrap changes whether a flex container's children are wrapped, which
1581 : // impacts their sizing/positioning and hence impacts the container's size.
1582 578 : if (mAlignItems != aNewData.mAlignItems ||
1583 578 : mFlexDirection != aNewData.mFlexDirection ||
1584 289 : mFlexWrap != aNewData.mFlexWrap) {
1585 0 : return hint |
1586 0 : nsChangeHint_AllReflowHints;
1587 : }
1588 :
1589 : // Properties that apply to grid containers:
1590 : // FIXME: only for grid containers
1591 : // (ie. 'display: grid' or 'display: inline-grid')
1592 867 : if (mGridTemplateColumns != aNewData.mGridTemplateColumns ||
1593 578 : mGridTemplateRows != aNewData.mGridTemplateRows ||
1594 578 : mGridTemplateAreas != aNewData.mGridTemplateAreas ||
1595 578 : mGridAutoColumnsMin != aNewData.mGridAutoColumnsMin ||
1596 578 : mGridAutoColumnsMax != aNewData.mGridAutoColumnsMax ||
1597 578 : mGridAutoRowsMin != aNewData.mGridAutoRowsMin ||
1598 867 : mGridAutoRowsMax != aNewData.mGridAutoRowsMax ||
1599 289 : mGridAutoFlow != aNewData.mGridAutoFlow) {
1600 0 : return hint |
1601 0 : nsChangeHint_AllReflowHints;
1602 : }
1603 :
1604 : // Properties that apply to grid items:
1605 : // FIXME: only for grid items
1606 : // (ie. parent frame is 'display: grid' or 'display: inline-grid')
1607 867 : if (mGridColumnStart != aNewData.mGridColumnStart ||
1608 578 : mGridColumnEnd != aNewData.mGridColumnEnd ||
1609 578 : mGridRowStart != aNewData.mGridRowStart ||
1610 578 : mGridRowEnd != aNewData.mGridRowEnd ||
1611 867 : mGridColumnGap != aNewData.mGridColumnGap ||
1612 289 : mGridRowGap != aNewData.mGridRowGap) {
1613 0 : return hint |
1614 0 : nsChangeHint_AllReflowHints;
1615 : }
1616 :
1617 : // Changing 'justify-content/items/self' might affect the positioning,
1618 : // but it won't affect any sizing.
1619 578 : if (mJustifyContent != aNewData.mJustifyContent ||
1620 578 : mJustifyItems != aNewData.mJustifyItems ||
1621 289 : mJustifySelf != aNewData.mJustifySelf) {
1622 0 : hint |= nsChangeHint_NeedReflow;
1623 : }
1624 :
1625 : // 'align-content' doesn't apply to a single-line flexbox but we don't know
1626 : // if we're a flex container at this point so we can't optimize for that.
1627 289 : if (mAlignContent != aNewData.mAlignContent) {
1628 0 : hint |= nsChangeHint_NeedReflow;
1629 : }
1630 :
1631 578 : bool widthChanged = mWidth != aNewData.mWidth ||
1632 576 : mMinWidth != aNewData.mMinWidth ||
1633 576 : mMaxWidth != aNewData.mMaxWidth;
1634 578 : bool heightChanged = mHeight != aNewData.mHeight ||
1635 578 : mMinHeight != aNewData.mMinHeight ||
1636 578 : mMaxHeight != aNewData.mMaxHeight;
1637 :
1638 : // If aOldStyleVisibility is null, we don't need to bother with any of
1639 : // these tests, since we know that the element never had its
1640 : // nsStyleVisibility accessed, which means it couldn't have done
1641 : // layout.
1642 : // Note that we pass an nsStyleVisibility here because we don't want
1643 : // to cause a new struct to be computed during
1644 : // nsStyleContext::CalcStyleDifference, which can lead to incorrect
1645 : // style data.
1646 : // It doesn't matter whether we're looking at the old or new
1647 : // visibility struct, since a change between vertical and horizontal
1648 : // writing-mode will cause a reframe, and it's easier to pass the old.
1649 289 : if (aOldStyleVisibility) {
1650 289 : bool isVertical = WritingMode(aOldStyleVisibility).IsVertical();
1651 289 : if (isVertical ? widthChanged : heightChanged) {
1652 0 : hint |= nsChangeHint_ReflowHintsForBSizeChange;
1653 : }
1654 :
1655 289 : if (isVertical ? heightChanged : widthChanged) {
1656 2 : hint |= nsChangeHint_ReflowHintsForISizeChange;
1657 : }
1658 : } else {
1659 0 : if (widthChanged || heightChanged) {
1660 0 : hint |= nsChangeHint_NeutralChange;
1661 : }
1662 : }
1663 :
1664 : // If any of the offsets have changed, then return the respective hints
1665 : // so that we would hopefully be able to avoid reflowing.
1666 : // Note that it is possible that we'll need to reflow when processing
1667 : // restyles, but we don't have enough information to make a good decision
1668 : // right now.
1669 : // Don't try to handle changes between "auto" and non-auto efficiently;
1670 : // that's tricky to do and will hardly ever be able to avoid a reflow.
1671 289 : if (mOffset != aNewData.mOffset) {
1672 0 : if (IsAutonessEqual(mOffset, aNewData.mOffset)) {
1673 : hint |= nsChangeHint_RecomputePosition |
1674 0 : nsChangeHint_UpdateParentOverflow;
1675 : } else {
1676 0 : hint |= nsChangeHint_AllReflowHints;
1677 : }
1678 : }
1679 289 : return hint;
1680 : }
1681 :
1682 : /* static */ bool
1683 50 : nsStylePosition::WidthCoordDependsOnContainer(const nsStyleCoord &aCoord)
1684 : {
1685 100 : return aCoord.HasPercent() ||
1686 46 : (aCoord.GetUnit() == eStyleUnit_Enumerated &&
1687 0 : (aCoord.GetIntValue() == NS_STYLE_WIDTH_FIT_CONTENT ||
1688 50 : aCoord.GetIntValue() == NS_STYLE_WIDTH_AVAILABLE));
1689 : }
1690 :
1691 : uint8_t
1692 0 : nsStylePosition::UsedAlignSelf(nsStyleContext* aParent) const
1693 : {
1694 0 : if (mAlignSelf != NS_STYLE_ALIGN_AUTO) {
1695 0 : return mAlignSelf;
1696 : }
1697 0 : if (MOZ_LIKELY(aParent)) {
1698 0 : auto parentAlignItems = aParent->StylePosition()->mAlignItems;
1699 0 : MOZ_ASSERT(!(parentAlignItems & NS_STYLE_ALIGN_LEGACY),
1700 : "align-items can't have 'legacy'");
1701 0 : return parentAlignItems;
1702 : }
1703 0 : return NS_STYLE_ALIGN_NORMAL;
1704 : }
1705 :
1706 : uint8_t
1707 476 : nsStylePosition::ComputedJustifyItems(nsStyleContext* aParent) const
1708 : {
1709 476 : if (mJustifyItems != NS_STYLE_JUSTIFY_AUTO) {
1710 0 : return mJustifyItems;
1711 : }
1712 476 : if (MOZ_LIKELY(aParent)) {
1713 427 : auto inheritedJustifyItems = aParent->StylePosition()->ComputedJustifyItems(
1714 427 : aParent->GetParentAllowServo());
1715 : // "If the inherited value of justify-items includes the 'legacy' keyword,
1716 : // 'auto' computes to the inherited value." Otherwise, 'normal'.
1717 427 : if (inheritedJustifyItems & NS_STYLE_JUSTIFY_LEGACY) {
1718 0 : return inheritedJustifyItems;
1719 : }
1720 : }
1721 476 : return NS_STYLE_JUSTIFY_NORMAL;
1722 : }
1723 :
1724 : uint8_t
1725 0 : nsStylePosition::UsedJustifySelf(nsStyleContext* aParent) const
1726 : {
1727 0 : if (mJustifySelf != NS_STYLE_JUSTIFY_AUTO) {
1728 0 : return mJustifySelf;
1729 : }
1730 0 : if (MOZ_LIKELY(aParent)) {
1731 0 : auto inheritedJustifyItems = aParent->StylePosition()->ComputedJustifyItems(
1732 0 : aParent->GetParentAllowServo());
1733 0 : return inheritedJustifyItems & ~NS_STYLE_JUSTIFY_LEGACY;
1734 : }
1735 0 : return NS_STYLE_JUSTIFY_NORMAL;
1736 : }
1737 :
1738 : // --------------------
1739 : // nsStyleTable
1740 : //
1741 :
1742 0 : nsStyleTable::nsStyleTable(const nsPresContext* aContext)
1743 : : mLayoutStrategy(NS_STYLE_TABLE_LAYOUT_AUTO)
1744 0 : , mSpan(1)
1745 : {
1746 0 : MOZ_COUNT_CTOR(nsStyleTable);
1747 0 : }
1748 :
1749 0 : nsStyleTable::~nsStyleTable()
1750 : {
1751 0 : MOZ_COUNT_DTOR(nsStyleTable);
1752 0 : }
1753 :
1754 0 : nsStyleTable::nsStyleTable(const nsStyleTable& aSource)
1755 0 : : mLayoutStrategy(aSource.mLayoutStrategy)
1756 0 : , mSpan(aSource.mSpan)
1757 : {
1758 0 : MOZ_COUNT_CTOR(nsStyleTable);
1759 0 : }
1760 :
1761 : nsChangeHint
1762 0 : nsStyleTable::CalcDifference(const nsStyleTable& aNewData) const
1763 : {
1764 0 : if (mSpan != aNewData.mSpan ||
1765 0 : mLayoutStrategy != aNewData.mLayoutStrategy) {
1766 0 : return nsChangeHint_ReconstructFrame;
1767 : }
1768 0 : return nsChangeHint(0);
1769 : }
1770 :
1771 : // -----------------------
1772 : // nsStyleTableBorder
1773 :
1774 0 : nsStyleTableBorder::nsStyleTableBorder(const nsPresContext* aContext)
1775 : : mBorderSpacingCol(0)
1776 : , mBorderSpacingRow(0)
1777 : , mBorderCollapse(NS_STYLE_BORDER_SEPARATE)
1778 : , mCaptionSide(NS_STYLE_CAPTION_SIDE_TOP)
1779 0 : , mEmptyCells(NS_STYLE_TABLE_EMPTY_CELLS_SHOW)
1780 : {
1781 0 : MOZ_COUNT_CTOR(nsStyleTableBorder);
1782 0 : }
1783 :
1784 0 : nsStyleTableBorder::~nsStyleTableBorder()
1785 : {
1786 0 : MOZ_COUNT_DTOR(nsStyleTableBorder);
1787 0 : }
1788 :
1789 0 : nsStyleTableBorder::nsStyleTableBorder(const nsStyleTableBorder& aSource)
1790 0 : : mBorderSpacingCol(aSource.mBorderSpacingCol)
1791 0 : , mBorderSpacingRow(aSource.mBorderSpacingRow)
1792 0 : , mBorderCollapse(aSource.mBorderCollapse)
1793 0 : , mCaptionSide(aSource.mCaptionSide)
1794 0 : , mEmptyCells(aSource.mEmptyCells)
1795 : {
1796 0 : MOZ_COUNT_CTOR(nsStyleTableBorder);
1797 0 : }
1798 :
1799 : nsChangeHint
1800 0 : nsStyleTableBorder::CalcDifference(const nsStyleTableBorder& aNewData) const
1801 : {
1802 : // Border-collapse changes need a reframe, because we use a different frame
1803 : // class for table cells in the collapsed border model. This is used to
1804 : // conserve memory when using the separated border model (collapsed borders
1805 : // require extra state to be stored).
1806 0 : if (mBorderCollapse != aNewData.mBorderCollapse) {
1807 0 : return nsChangeHint_ReconstructFrame;
1808 : }
1809 :
1810 0 : if ((mCaptionSide == aNewData.mCaptionSide) &&
1811 0 : (mBorderSpacingCol == aNewData.mBorderSpacingCol) &&
1812 0 : (mBorderSpacingRow == aNewData.mBorderSpacingRow)) {
1813 0 : if (mEmptyCells == aNewData.mEmptyCells) {
1814 0 : return nsChangeHint(0);
1815 : }
1816 0 : return NS_STYLE_HINT_VISUAL;
1817 : } else {
1818 0 : return NS_STYLE_HINT_REFLOW;
1819 : }
1820 : }
1821 :
1822 : // --------------------
1823 : // nsStyleColor
1824 : //
1825 :
1826 35 : nsStyleColor::nsStyleColor(const nsPresContext* aContext)
1827 35 : : mColor(aContext->DefaultColor())
1828 : {
1829 35 : MOZ_COUNT_CTOR(nsStyleColor);
1830 35 : }
1831 :
1832 0 : nsStyleColor::nsStyleColor(const nsStyleColor& aSource)
1833 0 : : mColor(aSource.mColor)
1834 : {
1835 0 : MOZ_COUNT_CTOR(nsStyleColor);
1836 0 : }
1837 :
1838 : nsChangeHint
1839 3 : nsStyleColor::CalcDifference(const nsStyleColor& aNewData) const
1840 : {
1841 3 : if (mColor == aNewData.mColor) {
1842 3 : return nsChangeHint(0);
1843 : }
1844 0 : return nsChangeHint_RepaintFrame;
1845 : }
1846 :
1847 : // --------------------
1848 : // nsStyleGradient
1849 : //
1850 : bool
1851 8 : nsStyleGradient::operator==(const nsStyleGradient& aOther) const
1852 : {
1853 8 : MOZ_ASSERT(mSize == NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER ||
1854 : mShape != NS_STYLE_GRADIENT_SHAPE_LINEAR,
1855 : "incorrect combination of shape and size");
1856 8 : MOZ_ASSERT(aOther.mSize == NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER ||
1857 : aOther.mShape != NS_STYLE_GRADIENT_SHAPE_LINEAR,
1858 : "incorrect combination of shape and size");
1859 :
1860 24 : if (mShape != aOther.mShape ||
1861 16 : mSize != aOther.mSize ||
1862 16 : mRepeating != aOther.mRepeating ||
1863 16 : mLegacySyntax != aOther.mLegacySyntax ||
1864 16 : mMozLegacySyntax != aOther.mMozLegacySyntax ||
1865 16 : mBgPosX != aOther.mBgPosX ||
1866 16 : mBgPosY != aOther.mBgPosY ||
1867 16 : mAngle != aOther.mAngle ||
1868 24 : mRadiusX != aOther.mRadiusX ||
1869 8 : mRadiusY != aOther.mRadiusY) {
1870 0 : return false;
1871 : }
1872 :
1873 8 : if (mStops.Length() != aOther.mStops.Length()) {
1874 0 : return false;
1875 : }
1876 :
1877 32 : for (uint32_t i = 0; i < mStops.Length(); i++) {
1878 24 : const auto& stop1 = mStops[i];
1879 24 : const auto& stop2 = aOther.mStops[i];
1880 72 : if (stop1.mLocation != stop2.mLocation ||
1881 48 : stop1.mIsInterpolationHint != stop2.mIsInterpolationHint ||
1882 48 : (!stop1.mIsInterpolationHint && stop1.mColor != stop2.mColor)) {
1883 0 : return false;
1884 : }
1885 : }
1886 :
1887 8 : return true;
1888 : }
1889 :
1890 15 : nsStyleGradient::nsStyleGradient()
1891 : : mShape(NS_STYLE_GRADIENT_SHAPE_LINEAR)
1892 : , mSize(NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER)
1893 : , mRepeating(false)
1894 : , mLegacySyntax(false)
1895 15 : , mMozLegacySyntax(false)
1896 : {
1897 15 : }
1898 :
1899 : bool
1900 104 : nsStyleGradient::IsOpaque()
1901 : {
1902 104 : for (uint32_t i = 0; i < mStops.Length(); i++) {
1903 104 : if (NS_GET_A(mStops[i].mColor) < 255) {
1904 104 : return false;
1905 : }
1906 : }
1907 0 : return true;
1908 : }
1909 :
1910 : bool
1911 0 : nsStyleGradient::HasCalc()
1912 : {
1913 0 : for (uint32_t i = 0; i < mStops.Length(); i++) {
1914 0 : if (mStops[i].mLocation.IsCalcUnit()) {
1915 0 : return true;
1916 : }
1917 : }
1918 0 : return mBgPosX.IsCalcUnit() || mBgPosY.IsCalcUnit() || mAngle.IsCalcUnit() ||
1919 0 : mRadiusX.IsCalcUnit() || mRadiusY.IsCalcUnit();
1920 : }
1921 :
1922 :
1923 : // --------------------
1924 : // nsStyleImageRequest
1925 :
1926 : /**
1927 : * Runnable to release the nsStyleImageRequest's mRequestProxy,
1928 : * mImageValue and mImageTracker on the main thread, and to perform
1929 : * any necessary unlocking and untracking of the image.
1930 : */
1931 : class StyleImageRequestCleanupTask : public mozilla::Runnable
1932 : {
1933 : public:
1934 : typedef nsStyleImageRequest::Mode Mode;
1935 :
1936 106 : StyleImageRequestCleanupTask(Mode aModeFlags,
1937 : already_AddRefed<imgRequestProxy> aRequestProxy,
1938 : already_AddRefed<css::ImageValue> aImageValue,
1939 : already_AddRefed<ImageTracker> aImageTracker)
1940 106 : : mozilla::Runnable("StyleImageRequestCleanupTask")
1941 : , mModeFlags(aModeFlags)
1942 : , mRequestProxy(aRequestProxy)
1943 : , mImageValue(aImageValue)
1944 106 : , mImageTracker(aImageTracker)
1945 : {
1946 106 : }
1947 :
1948 106 : NS_IMETHOD Run() final
1949 : {
1950 106 : MOZ_ASSERT(!mRequestProxy || NS_IsMainThread(),
1951 : "If mRequestProxy is non-null, we need to run on main thread!");
1952 :
1953 106 : if (!mRequestProxy) {
1954 0 : return NS_OK;
1955 : }
1956 :
1957 106 : if (mModeFlags & Mode::Track) {
1958 14 : MOZ_ASSERT(mImageTracker);
1959 14 : mImageTracker->Remove(mRequestProxy);
1960 : } else {
1961 92 : mRequestProxy->UnlockImage();
1962 : }
1963 :
1964 106 : if (mModeFlags & Mode::Discard) {
1965 0 : mRequestProxy->RequestDiscard();
1966 : }
1967 :
1968 106 : return NS_OK;
1969 : }
1970 :
1971 : protected:
1972 212 : virtual ~StyleImageRequestCleanupTask()
1973 212 : {
1974 106 : MOZ_ASSERT(mImageValue->mRequests.Count() == 0 || NS_IsMainThread(),
1975 : "If mImageValue has any mRequests, we need to run on main "
1976 : "thread to release ImageValues!");
1977 106 : MOZ_ASSERT((!mRequestProxy && !mImageTracker) || NS_IsMainThread(),
1978 : "mRequestProxy and mImageTracker's destructor need to run "
1979 : "on the main thread!");
1980 318 : }
1981 :
1982 : private:
1983 : Mode mModeFlags;
1984 : // Since we always dispatch this runnable to the main thread, these will be
1985 : // released on the main thread when the runnable itself is released.
1986 : RefPtr<imgRequestProxy> mRequestProxy;
1987 : RefPtr<css::ImageValue> mImageValue;
1988 : RefPtr<ImageTracker> mImageTracker;
1989 : };
1990 :
1991 141 : nsStyleImageRequest::nsStyleImageRequest(Mode aModeFlags,
1992 : imgRequestProxy* aRequestProxy,
1993 : css::ImageValue* aImageValue,
1994 141 : ImageTracker* aImageTracker)
1995 : : mRequestProxy(aRequestProxy)
1996 : , mImageValue(aImageValue)
1997 : , mImageTracker(aImageTracker)
1998 : , mModeFlags(aModeFlags)
1999 141 : , mResolved(true)
2000 : {
2001 141 : MOZ_ASSERT(NS_IsMainThread());
2002 141 : MOZ_ASSERT(aImageValue);
2003 141 : MOZ_ASSERT(!!(aModeFlags & Mode::Track) == !!aImageTracker);
2004 :
2005 141 : if (mRequestProxy) {
2006 141 : MaybeTrackAndLock();
2007 : }
2008 141 : }
2009 :
2010 0 : nsStyleImageRequest::nsStyleImageRequest(
2011 : Mode aModeFlags,
2012 0 : mozilla::css::ImageValue* aImageValue)
2013 : : mImageValue(aImageValue)
2014 : , mModeFlags(aModeFlags)
2015 0 : , mResolved(false)
2016 : {
2017 0 : }
2018 :
2019 212 : nsStyleImageRequest::~nsStyleImageRequest()
2020 : {
2021 : // We may or may not be being destroyed on the main thread. To clean
2022 : // up, we must untrack and unlock the image (depending on mModeFlags),
2023 : // and release mRequestProxy and mImageValue, all on the main thread.
2024 : {
2025 : RefPtr<StyleImageRequestCleanupTask> task =
2026 : new StyleImageRequestCleanupTask(mModeFlags,
2027 212 : mRequestProxy.forget(),
2028 212 : mImageValue.forget(),
2029 530 : mImageTracker.forget());
2030 106 : if (NS_IsMainThread()) {
2031 106 : task->Run();
2032 : } else {
2033 0 : if (mDocGroup) {
2034 0 : mDocGroup->Dispatch("StyleImageRequestCleanupTask",
2035 0 : TaskCategory::Other, task.forget());
2036 : } else {
2037 : // if Resolve was not called at some point, mDocGroup is not set.
2038 0 : NS_DispatchToMainThread(task.forget());
2039 : }
2040 : }
2041 : }
2042 :
2043 106 : MOZ_ASSERT(!mRequestProxy);
2044 106 : MOZ_ASSERT(!mImageValue);
2045 106 : MOZ_ASSERT(!mImageTracker);
2046 106 : }
2047 :
2048 : bool
2049 0 : nsStyleImageRequest::Resolve(nsPresContext* aPresContext)
2050 : {
2051 0 : MOZ_ASSERT(NS_IsMainThread());
2052 0 : MOZ_ASSERT(!IsResolved(), "already resolved");
2053 0 : MOZ_ASSERT(aPresContext);
2054 :
2055 0 : mResolved = true;
2056 :
2057 0 : nsIDocument* doc = aPresContext->Document();
2058 0 : nsIURI* docURI = doc->GetDocumentURI();
2059 0 : if (GetImageValue()->HasRef()) {
2060 0 : bool isEqualExceptRef = false;
2061 0 : RefPtr<nsIURI> imageURI = GetImageURI();
2062 0 : imageURI->EqualsExceptRef(docURI, &isEqualExceptRef);
2063 0 : if (isEqualExceptRef) {
2064 : // Prevent loading an internal resource.
2065 0 : return true;
2066 : }
2067 : }
2068 :
2069 0 : mDocGroup = doc->GetDocGroup();
2070 :
2071 0 : mImageValue->Initialize(doc);
2072 :
2073 0 : nsCSSValue value;
2074 0 : value.SetImageValue(mImageValue);
2075 0 : mRequestProxy = value.GetPossiblyStaticImageValue(aPresContext->Document(),
2076 0 : aPresContext);
2077 :
2078 0 : if (!mRequestProxy) {
2079 : // The URL resolution or image load failed.
2080 0 : return false;
2081 : }
2082 :
2083 0 : if (mModeFlags & Mode::Track) {
2084 0 : mImageTracker = aPresContext->Document()->ImageTracker();
2085 : }
2086 :
2087 0 : MaybeTrackAndLock();
2088 0 : return true;
2089 : }
2090 :
2091 : void
2092 141 : nsStyleImageRequest::MaybeTrackAndLock()
2093 : {
2094 141 : MOZ_ASSERT(NS_IsMainThread());
2095 141 : MOZ_ASSERT(IsResolved());
2096 141 : MOZ_ASSERT(mRequestProxy);
2097 :
2098 141 : if (mModeFlags & Mode::Track) {
2099 24 : MOZ_ASSERT(mImageTracker);
2100 24 : mImageTracker->Add(mRequestProxy);
2101 : } else {
2102 117 : MOZ_ASSERT(!mImageTracker);
2103 117 : mRequestProxy->LockImage();
2104 : }
2105 141 : }
2106 :
2107 : bool
2108 94 : nsStyleImageRequest::DefinitelyEquals(const nsStyleImageRequest& aOther) const
2109 : {
2110 94 : return DefinitelyEqualURIs(mImageValue, aOther.mImageValue);
2111 : }
2112 :
2113 : // --------------------
2114 : // CachedBorderImageData
2115 : //
2116 : void
2117 0 : CachedBorderImageData::SetCachedSVGViewportSize(
2118 : const mozilla::Maybe<nsSize>& aSVGViewportSize)
2119 : {
2120 0 : mCachedSVGViewportSize = aSVGViewportSize;
2121 0 : }
2122 :
2123 : const mozilla::Maybe<nsSize>&
2124 0 : CachedBorderImageData::GetCachedSVGViewportSize()
2125 : {
2126 0 : return mCachedSVGViewportSize;
2127 : }
2128 :
2129 0 : struct PurgeCachedImagesTask : mozilla::Runnable
2130 : {
2131 0 : PurgeCachedImagesTask() : mozilla::Runnable("PurgeCachedImagesTask") {}
2132 0 : NS_IMETHOD Run() final
2133 : {
2134 0 : mSubImages.Clear();
2135 0 : return NS_OK;
2136 : }
2137 :
2138 : nsCOMArray<imgIContainer> mSubImages;
2139 : };
2140 :
2141 : void
2142 0 : CachedBorderImageData::PurgeCachedImages()
2143 : {
2144 0 : if (ServoStyleSet::IsInServoTraversal()) {
2145 0 : RefPtr<PurgeCachedImagesTask> task = new PurgeCachedImagesTask();
2146 0 : task->mSubImages.SwapElements(mSubImages);
2147 : // This will run the task immediately if we're already on the main thread,
2148 : // but that is fine.
2149 0 : NS_DispatchToMainThread(task.forget());
2150 : } else {
2151 0 : mSubImages.Clear();
2152 : }
2153 0 : }
2154 :
2155 : void
2156 0 : CachedBorderImageData::SetSubImage(uint8_t aIndex, imgIContainer* aSubImage)
2157 : {
2158 0 : mSubImages.ReplaceObjectAt(aSubImage, aIndex);
2159 0 : }
2160 :
2161 : imgIContainer*
2162 0 : CachedBorderImageData::GetSubImage(uint8_t aIndex)
2163 : {
2164 0 : imgIContainer* subImage = nullptr;
2165 0 : if (aIndex < mSubImages.Count())
2166 0 : subImage = mSubImages[aIndex];
2167 0 : return subImage;
2168 : }
2169 :
2170 : // --------------------
2171 : // nsStyleImage
2172 : //
2173 :
2174 546 : nsStyleImage::nsStyleImage()
2175 : : mType(eStyleImageType_Null)
2176 546 : , mCropRect(nullptr)
2177 : {
2178 546 : MOZ_COUNT_CTOR(nsStyleImage);
2179 546 : }
2180 :
2181 1358 : nsStyleImage::~nsStyleImage()
2182 : {
2183 679 : MOZ_COUNT_DTOR(nsStyleImage);
2184 679 : if (mType != eStyleImageType_Null) {
2185 22 : SetNull();
2186 : }
2187 679 : }
2188 :
2189 363 : nsStyleImage::nsStyleImage(const nsStyleImage& aOther)
2190 : : mType(eStyleImageType_Null)
2191 363 : , mCropRect(nullptr)
2192 : {
2193 : // We need our own copy constructor because we don't want
2194 : // to copy the reference count
2195 363 : MOZ_COUNT_CTOR(nsStyleImage);
2196 363 : DoCopy(aOther);
2197 363 : }
2198 :
2199 : nsStyleImage&
2200 77 : nsStyleImage::operator=(const nsStyleImage& aOther)
2201 : {
2202 77 : if (this != &aOther) {
2203 77 : DoCopy(aOther);
2204 : }
2205 :
2206 77 : return *this;
2207 : }
2208 :
2209 : void
2210 440 : nsStyleImage::DoCopy(const nsStyleImage& aOther)
2211 : {
2212 440 : SetNull();
2213 :
2214 440 : if (aOther.mType == eStyleImageType_Image) {
2215 0 : SetImageRequest(do_AddRef(aOther.mImage));
2216 440 : } else if (aOther.mType == eStyleImageType_Gradient) {
2217 0 : SetGradientData(aOther.mGradient);
2218 440 : } else if (aOther.mType == eStyleImageType_Element) {
2219 0 : SetElementId(do_AddRef(aOther.mElementId));
2220 440 : } else if (aOther.mType == eStyleImageType_URL) {
2221 0 : SetURLValue(do_AddRef(aOther.mURLValue));
2222 : }
2223 :
2224 880 : UniquePtr<nsStyleSides> cropRectCopy;
2225 440 : if (aOther.mCropRect) {
2226 0 : cropRectCopy = MakeUnique<nsStyleSides>(*aOther.mCropRect.get());
2227 : }
2228 440 : SetCropRect(Move(cropRectCopy));
2229 440 : }
2230 :
2231 : void
2232 862 : nsStyleImage::SetNull()
2233 : {
2234 862 : if (mType == eStyleImageType_Gradient) {
2235 8 : mGradient->Release();
2236 854 : } else if (mType == eStyleImageType_Image) {
2237 14 : NS_RELEASE(mImage);
2238 840 : } else if (mType == eStyleImageType_Element) {
2239 0 : NS_RELEASE(mElementId);
2240 840 : } else if (mType == eStyleImageType_URL) {
2241 0 : NS_RELEASE(mURLValue);
2242 : }
2243 :
2244 862 : mType = eStyleImageType_Null;
2245 862 : mCropRect = nullptr;
2246 862 : }
2247 :
2248 : void
2249 24 : nsStyleImage::SetImageRequest(already_AddRefed<nsStyleImageRequest> aImage)
2250 : {
2251 48 : RefPtr<nsStyleImageRequest> image = aImage;
2252 :
2253 24 : if (mType != eStyleImageType_Null) {
2254 0 : SetNull();
2255 : }
2256 :
2257 24 : if (image) {
2258 24 : mImage = image.forget().take();
2259 24 : mType = eStyleImageType_Image;
2260 : }
2261 24 : if (mCachedBIData) {
2262 0 : mCachedBIData->PurgeCachedImages();
2263 : }
2264 24 : }
2265 :
2266 : void
2267 15 : nsStyleImage::SetGradientData(nsStyleGradient* aGradient)
2268 : {
2269 15 : if (aGradient) {
2270 15 : aGradient->AddRef();
2271 : }
2272 :
2273 15 : if (mType != eStyleImageType_Null) {
2274 0 : SetNull();
2275 : }
2276 :
2277 15 : if (aGradient) {
2278 15 : mGradient = aGradient;
2279 15 : mType = eStyleImageType_Gradient;
2280 : }
2281 15 : }
2282 :
2283 : void
2284 0 : nsStyleImage::SetElementId(already_AddRefed<nsIAtom> aElementId)
2285 : {
2286 0 : if (mType != eStyleImageType_Null) {
2287 0 : SetNull();
2288 : }
2289 :
2290 0 : if (nsCOMPtr<nsIAtom> atom = aElementId) {
2291 0 : mElementId = atom.forget().take();
2292 0 : mType = eStyleImageType_Element;
2293 : }
2294 0 : }
2295 :
2296 : void
2297 442 : nsStyleImage::SetCropRect(UniquePtr<nsStyleSides> aCropRect)
2298 : {
2299 442 : mCropRect = Move(aCropRect);
2300 442 : }
2301 :
2302 : void
2303 1 : nsStyleImage::SetURLValue(already_AddRefed<URLValue> aValue)
2304 : {
2305 2 : RefPtr<URLValue> value = aValue;
2306 :
2307 1 : if (mType != eStyleImageType_Null) {
2308 0 : SetNull();
2309 : }
2310 :
2311 1 : if (value) {
2312 1 : mURLValue = value.forget().take();
2313 1 : mType = eStyleImageType_URL;
2314 : }
2315 1 : }
2316 :
2317 : static int32_t
2318 208 : ConvertToPixelCoord(const nsStyleCoord& aCoord, int32_t aPercentScale)
2319 : {
2320 : double pixelValue;
2321 208 : switch (aCoord.GetUnit()) {
2322 : case eStyleUnit_Percent:
2323 0 : pixelValue = aCoord.GetPercentValue() * aPercentScale;
2324 0 : break;
2325 : case eStyleUnit_Factor:
2326 208 : pixelValue = aCoord.GetFactorValue();
2327 208 : break;
2328 : default:
2329 0 : NS_NOTREACHED("unexpected unit for image crop rect");
2330 0 : return 0;
2331 : }
2332 208 : MOZ_ASSERT(pixelValue >= 0, "we ensured non-negative while parsing");
2333 208 : pixelValue = std::min(pixelValue, double(INT32_MAX)); // avoid overflow
2334 208 : return NS_lround(pixelValue);
2335 : }
2336 :
2337 : already_AddRefed<nsIURI>
2338 0 : nsStyleImageRequest::GetImageURI() const
2339 : {
2340 0 : nsCOMPtr<nsIURI> uri;
2341 :
2342 0 : if (mRequestProxy) {
2343 0 : mRequestProxy->GetURI(getter_AddRefs(uri));
2344 0 : if (uri) {
2345 0 : return uri.forget();
2346 : }
2347 : }
2348 :
2349 : // If we had some problem resolving the mRequestProxy, use the URL stored
2350 : // in the mImageValue.
2351 0 : if (!mImageValue) {
2352 0 : return nullptr;
2353 : }
2354 :
2355 0 : uri = mImageValue->GetURI();
2356 0 : return uri.forget();
2357 : }
2358 :
2359 : bool
2360 52 : nsStyleImage::ComputeActualCropRect(nsIntRect& aActualCropRect,
2361 : bool* aIsEntireImage) const
2362 : {
2363 52 : MOZ_ASSERT(mType == eStyleImageType_Image,
2364 : "This function is designed to be used only when mType"
2365 : "is eStyleImageType_Image.");
2366 :
2367 52 : imgRequestProxy* req = GetImageData();
2368 52 : if (!req) {
2369 0 : return false;
2370 : }
2371 :
2372 104 : nsCOMPtr<imgIContainer> imageContainer;
2373 52 : req->GetImage(getter_AddRefs(imageContainer));
2374 52 : if (!imageContainer) {
2375 0 : return false;
2376 : }
2377 :
2378 52 : nsIntSize imageSize;
2379 52 : imageContainer->GetWidth(&imageSize.width);
2380 52 : imageContainer->GetHeight(&imageSize.height);
2381 52 : if (imageSize.width <= 0 || imageSize.height <= 0) {
2382 0 : return false;
2383 : }
2384 :
2385 52 : int32_t left = ConvertToPixelCoord(mCropRect->GetLeft(), imageSize.width);
2386 52 : int32_t top = ConvertToPixelCoord(mCropRect->GetTop(), imageSize.height);
2387 52 : int32_t right = ConvertToPixelCoord(mCropRect->GetRight(), imageSize.width);
2388 52 : int32_t bottom = ConvertToPixelCoord(mCropRect->GetBottom(), imageSize.height);
2389 :
2390 : // IntersectRect() returns an empty rect if we get negative width or height
2391 52 : nsIntRect cropRect(left, top, right - left, bottom - top);
2392 52 : nsIntRect imageRect(nsIntPoint(0, 0), imageSize);
2393 52 : aActualCropRect.IntersectRect(imageRect, cropRect);
2394 :
2395 52 : if (aIsEntireImage) {
2396 52 : *aIsEntireImage = aActualCropRect.IsEqualInterior(imageRect);
2397 : }
2398 52 : return true;
2399 : }
2400 :
2401 : bool
2402 9 : nsStyleImage::StartDecoding() const
2403 : {
2404 9 : if (mType == eStyleImageType_Image) {
2405 9 : imgRequestProxy* req = GetImageData();
2406 9 : if (!req) {
2407 0 : return false;
2408 : }
2409 9 : return req->StartDecodingWithResult(imgIContainer::FLAG_ASYNC_NOTIFY);
2410 : }
2411 : // null image types always return false from IsComplete, so we do the same here.
2412 0 : return mType != eStyleImageType_Null ? true : false;
2413 : }
2414 :
2415 : bool
2416 433 : nsStyleImage::IsOpaque() const
2417 : {
2418 433 : if (!IsComplete()) {
2419 155 : return false;
2420 : }
2421 :
2422 278 : if (mType == eStyleImageType_Gradient) {
2423 104 : return mGradient->IsOpaque();
2424 : }
2425 :
2426 174 : if (mType == eStyleImageType_Element || mType == eStyleImageType_URL) {
2427 0 : return false;
2428 : }
2429 :
2430 174 : MOZ_ASSERT(mType == eStyleImageType_Image, "unexpected image type");
2431 174 : MOZ_ASSERT(GetImageData(), "should've returned earlier above");
2432 :
2433 348 : nsCOMPtr<imgIContainer> imageContainer;
2434 174 : GetImageData()->GetImage(getter_AddRefs(imageContainer));
2435 174 : MOZ_ASSERT(imageContainer, "IsComplete() said image container is ready");
2436 :
2437 : // Check if the crop region of the image is opaque.
2438 174 : if (imageContainer->WillDrawOpaqueNow()) {
2439 0 : if (!mCropRect) {
2440 0 : return true;
2441 : }
2442 :
2443 : // Must make sure if mCropRect contains at least a pixel.
2444 : // XXX Is this optimization worth it? Maybe I should just return false.
2445 0 : nsIntRect actualCropRect;
2446 0 : return ComputeActualCropRect(actualCropRect) && !actualCropRect.IsEmpty();
2447 : }
2448 :
2449 174 : return false;
2450 : }
2451 :
2452 : bool
2453 888 : nsStyleImage::IsComplete() const
2454 : {
2455 888 : switch (mType) {
2456 : case eStyleImageType_Null:
2457 149 : return false;
2458 : case eStyleImageType_Gradient:
2459 : case eStyleImageType_Element:
2460 : case eStyleImageType_URL:
2461 235 : return true;
2462 : case eStyleImageType_Image: {
2463 504 : imgRequestProxy* req = GetImageData();
2464 504 : if (!req) {
2465 0 : return false;
2466 : }
2467 504 : uint32_t status = imgIRequest::STATUS_ERROR;
2468 1008 : return NS_SUCCEEDED(req->GetImageStatus(&status)) &&
2469 1008 : (status & imgIRequest::STATUS_SIZE_AVAILABLE) &&
2470 1008 : (status & imgIRequest::STATUS_FRAME_COMPLETE);
2471 : }
2472 : default:
2473 0 : NS_NOTREACHED("unexpected image type");
2474 0 : return false;
2475 : }
2476 : }
2477 :
2478 : bool
2479 185 : nsStyleImage::IsLoaded() const
2480 : {
2481 185 : switch (mType) {
2482 : case eStyleImageType_Null:
2483 158 : return false;
2484 : case eStyleImageType_Gradient:
2485 : case eStyleImageType_Element:
2486 : case eStyleImageType_URL:
2487 27 : return true;
2488 : case eStyleImageType_Image: {
2489 0 : imgRequestProxy* req = GetImageData();
2490 0 : if (!req) {
2491 0 : return false;
2492 : }
2493 0 : uint32_t status = imgIRequest::STATUS_ERROR;
2494 0 : return NS_SUCCEEDED(req->GetImageStatus(&status)) &&
2495 0 : !(status & imgIRequest::STATUS_ERROR) &&
2496 0 : (status & imgIRequest::STATUS_LOAD_COMPLETE);
2497 : }
2498 : default:
2499 0 : NS_NOTREACHED("unexpected image type");
2500 0 : return false;
2501 : }
2502 : }
2503 :
2504 : static inline bool
2505 935 : EqualRects(const UniquePtr<nsStyleSides>& aRect1, const UniquePtr<nsStyleSides>& aRect2)
2506 : {
2507 1871 : return aRect1 == aRect2 || /* handles null== null, and optimize */
2508 937 : (aRect1 && aRect2 && *aRect1 == *aRect2);
2509 : }
2510 :
2511 : bool
2512 936 : nsStyleImage::operator==(const nsStyleImage& aOther) const
2513 : {
2514 936 : if (mType != aOther.mType) {
2515 1 : return false;
2516 : }
2517 :
2518 935 : if (!EqualRects(mCropRect, aOther.mCropRect)) {
2519 0 : return false;
2520 : }
2521 :
2522 935 : if (mType == eStyleImageType_Image) {
2523 13 : return DefinitelyEqualImages(mImage, aOther.mImage);
2524 : }
2525 :
2526 922 : if (mType == eStyleImageType_Gradient) {
2527 8 : return *mGradient == *aOther.mGradient;
2528 : }
2529 :
2530 914 : if (mType == eStyleImageType_Element) {
2531 0 : return mElementId == aOther.mElementId;
2532 : }
2533 :
2534 914 : if (mType == eStyleImageType_URL) {
2535 0 : return DefinitelyEqualURIs(mURLValue, aOther.mURLValue);
2536 : }
2537 :
2538 914 : return true;
2539 : }
2540 :
2541 : void
2542 0 : nsStyleImage::PurgeCacheForViewportChange(
2543 : const mozilla::Maybe<nsSize>& aSVGViewportSize,
2544 : const bool aHasIntrinsicRatio) const
2545 : {
2546 0 : EnsureCachedBIData();
2547 :
2548 : // If we're redrawing with a different viewport-size than we used for our
2549 : // cached subimages, then we can't trust that our subimages are valid;
2550 : // any percent sizes/positions in our SVG doc may be different now. Purge!
2551 : // (We don't have to purge if the SVG document has an intrinsic ratio,
2552 : // though, because the actual size of elements in SVG documant's coordinate
2553 : // axis are fixed in this case.)
2554 0 : if (aSVGViewportSize != mCachedBIData->GetCachedSVGViewportSize() &&
2555 0 : !aHasIntrinsicRatio) {
2556 0 : mCachedBIData->PurgeCachedImages();
2557 0 : mCachedBIData->SetCachedSVGViewportSize(aSVGViewportSize);
2558 : }
2559 0 : }
2560 :
2561 : already_AddRefed<nsIURI>
2562 0 : nsStyleImage::GetImageURI() const
2563 : {
2564 0 : if (mType != eStyleImageType_Image) {
2565 0 : return nullptr;
2566 : }
2567 :
2568 0 : nsCOMPtr<nsIURI> uri = mImage->GetImageURI();
2569 0 : return uri.forget();
2570 : }
2571 :
2572 : css::URLValueData*
2573 1219 : nsStyleImage::GetURLValue() const
2574 : {
2575 1219 : if (mType == eStyleImageType_Image) {
2576 32 : return mImage->GetImageValue();
2577 1187 : } else if (mType == eStyleImageType_URL) {
2578 0 : return mURLValue;
2579 : }
2580 :
2581 1187 : return nullptr;
2582 : }
2583 :
2584 : // --------------------
2585 : // nsStyleImageLayers
2586 : //
2587 :
2588 : const nsCSSPropertyID nsStyleImageLayers::kBackgroundLayerTable[] = {
2589 : eCSSProperty_background, // shorthand
2590 : eCSSProperty_background_color, // color
2591 : eCSSProperty_background_image, // image
2592 : eCSSProperty_background_repeat, // repeat
2593 : eCSSProperty_background_position_x, // positionX
2594 : eCSSProperty_background_position_y, // positionY
2595 : eCSSProperty_background_clip, // clip
2596 : eCSSProperty_background_origin, // origin
2597 : eCSSProperty_background_size, // size
2598 : eCSSProperty_background_attachment, // attachment
2599 : eCSSProperty_UNKNOWN, // maskMode
2600 : eCSSProperty_UNKNOWN // composite
2601 : };
2602 :
2603 : #ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
2604 : const nsCSSPropertyID nsStyleImageLayers::kMaskLayerTable[] = {
2605 : eCSSProperty_mask, // shorthand
2606 : eCSSProperty_UNKNOWN, // color
2607 : eCSSProperty_mask_image, // image
2608 : eCSSProperty_mask_repeat, // repeat
2609 : eCSSProperty_mask_position_x, // positionX
2610 : eCSSProperty_mask_position_y, // positionY
2611 : eCSSProperty_mask_clip, // clip
2612 : eCSSProperty_mask_origin, // origin
2613 : eCSSProperty_mask_size, // size
2614 : eCSSProperty_UNKNOWN, // attachment
2615 : eCSSProperty_mask_mode, // maskMode
2616 : eCSSProperty_mask_composite // composite
2617 : };
2618 : #endif
2619 :
2620 201 : nsStyleImageLayers::nsStyleImageLayers(nsStyleImageLayers::LayerType aType)
2621 : : mAttachmentCount(1)
2622 : , mClipCount(1)
2623 : , mOriginCount(1)
2624 : , mRepeatCount(1)
2625 : , mPositionXCount(1)
2626 : , mPositionYCount(1)
2627 : , mImageCount(1)
2628 : , mSizeCount(1)
2629 : , mMaskModeCount(1)
2630 : , mBlendModeCount(1)
2631 : , mCompositeCount(1)
2632 201 : , mLayers(nsStyleAutoArray<Layer>::WITH_SINGLE_INITIAL_ELEMENT)
2633 : {
2634 201 : MOZ_COUNT_CTOR(nsStyleImageLayers);
2635 :
2636 : // Ensure first layer is initialized as specified layer type
2637 201 : mLayers[0].Initialize(aType);
2638 201 : }
2639 :
2640 77 : nsStyleImageLayers::nsStyleImageLayers(const nsStyleImageLayers &aSource)
2641 77 : : mAttachmentCount(aSource.mAttachmentCount)
2642 77 : , mClipCount(aSource.mClipCount)
2643 77 : , mOriginCount(aSource.mOriginCount)
2644 77 : , mRepeatCount(aSource.mRepeatCount)
2645 77 : , mPositionXCount(aSource.mPositionXCount)
2646 77 : , mPositionYCount(aSource.mPositionYCount)
2647 77 : , mImageCount(aSource.mImageCount)
2648 77 : , mSizeCount(aSource.mSizeCount)
2649 77 : , mMaskModeCount(aSource.mMaskModeCount)
2650 77 : , mBlendModeCount(aSource.mBlendModeCount)
2651 77 : , mCompositeCount(aSource.mCompositeCount)
2652 847 : , mLayers(aSource.mLayers) // deep copy
2653 : {
2654 77 : MOZ_COUNT_CTOR(nsStyleImageLayers);
2655 : // If the deep copy of mLayers failed, truncate the counts.
2656 77 : uint32_t count = mLayers.Length();
2657 77 : if (count != aSource.mLayers.Length()) {
2658 0 : NS_WARNING("truncating counts due to out-of-memory");
2659 0 : mAttachmentCount = std::max(mAttachmentCount, count);
2660 0 : mClipCount = std::max(mClipCount, count);
2661 0 : mOriginCount = std::max(mOriginCount, count);
2662 0 : mRepeatCount = std::max(mRepeatCount, count);
2663 0 : mPositionXCount = std::max(mPositionXCount, count);
2664 0 : mPositionYCount = std::max(mPositionYCount, count);
2665 0 : mImageCount = std::max(mImageCount, count);
2666 0 : mSizeCount = std::max(mSizeCount, count);
2667 0 : mMaskModeCount = std::max(mMaskModeCount, count);
2668 0 : mBlendModeCount = std::max(mBlendModeCount, count);
2669 0 : mCompositeCount = std::max(mCompositeCount, count);
2670 : }
2671 77 : }
2672 :
2673 : nsChangeHint
2674 596 : nsStyleImageLayers::CalcDifference(const nsStyleImageLayers& aNewLayers,
2675 : nsStyleImageLayers::LayerType aType) const
2676 : {
2677 596 : nsChangeHint hint = nsChangeHint(0);
2678 :
2679 : const nsStyleImageLayers& moreLayers =
2680 596 : mImageCount > aNewLayers.mImageCount ?
2681 596 : *this : aNewLayers;
2682 : const nsStyleImageLayers& lessLayers =
2683 596 : mImageCount > aNewLayers.mImageCount ?
2684 596 : aNewLayers : *this;
2685 :
2686 1202 : NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, moreLayers) {
2687 606 : if (i < lessLayers.mImageCount) {
2688 : nsChangeHint layerDifference =
2689 606 : moreLayers.mLayers[i].CalcDifference(lessLayers.mLayers[i]);
2690 606 : hint |= layerDifference;
2691 610 : if (layerDifference &&
2692 8 : ((moreLayers.mLayers[i].mImage.GetType() == eStyleImageType_Element) ||
2693 4 : (lessLayers.mLayers[i].mImage.GetType() == eStyleImageType_Element))) {
2694 0 : hint |= nsChangeHint_UpdateEffects | nsChangeHint_RepaintFrame;
2695 : }
2696 : } else {
2697 0 : hint |= nsChangeHint_RepaintFrame;
2698 0 : if (moreLayers.mLayers[i].mImage.GetType() == eStyleImageType_Element) {
2699 0 : hint |= nsChangeHint_UpdateEffects | nsChangeHint_RepaintFrame;
2700 : }
2701 : }
2702 : }
2703 :
2704 890 : if (aType == nsStyleImageLayers::LayerType::Mask &&
2705 294 : mImageCount != aNewLayers.mImageCount) {
2706 0 : hint |= nsChangeHint_UpdateEffects;
2707 : }
2708 :
2709 596 : if (hint) {
2710 4 : return hint;
2711 : }
2712 :
2713 1184 : if (mAttachmentCount != aNewLayers.mAttachmentCount ||
2714 1184 : mBlendModeCount != aNewLayers.mBlendModeCount ||
2715 1184 : mClipCount != aNewLayers.mClipCount ||
2716 1184 : mCompositeCount != aNewLayers.mCompositeCount ||
2717 1184 : mMaskModeCount != aNewLayers.mMaskModeCount ||
2718 1184 : mOriginCount != aNewLayers.mOriginCount ||
2719 1184 : mRepeatCount != aNewLayers.mRepeatCount ||
2720 1184 : mPositionXCount != aNewLayers.mPositionXCount ||
2721 1184 : mPositionYCount != aNewLayers.mPositionYCount ||
2722 592 : mSizeCount != aNewLayers.mSizeCount) {
2723 0 : hint |= nsChangeHint_NeutralChange;
2724 : }
2725 :
2726 592 : return hint;
2727 : }
2728 :
2729 : nsStyleImageLayers&
2730 0 : nsStyleImageLayers::operator=(const nsStyleImageLayers& aOther)
2731 : {
2732 0 : mAttachmentCount = aOther.mAttachmentCount;
2733 0 : mClipCount = aOther.mClipCount;
2734 0 : mOriginCount = aOther.mOriginCount;
2735 0 : mRepeatCount = aOther.mRepeatCount;
2736 0 : mPositionXCount = aOther.mPositionXCount;
2737 0 : mPositionYCount = aOther.mPositionYCount;
2738 0 : mImageCount = aOther.mImageCount;
2739 0 : mSizeCount = aOther.mSizeCount;
2740 0 : mMaskModeCount = aOther.mMaskModeCount;
2741 0 : mBlendModeCount = aOther.mBlendModeCount;
2742 0 : mCompositeCount = aOther.mCompositeCount;
2743 0 : mLayers = aOther.mLayers;
2744 :
2745 0 : uint32_t count = mLayers.Length();
2746 0 : if (count != aOther.mLayers.Length()) {
2747 0 : NS_WARNING("truncating counts due to out-of-memory");
2748 0 : mAttachmentCount = std::max(mAttachmentCount, count);
2749 0 : mClipCount = std::max(mClipCount, count);
2750 0 : mOriginCount = std::max(mOriginCount, count);
2751 0 : mRepeatCount = std::max(mRepeatCount, count);
2752 0 : mPositionXCount = std::max(mPositionXCount, count);
2753 0 : mPositionYCount = std::max(mPositionYCount, count);
2754 0 : mImageCount = std::max(mImageCount, count);
2755 0 : mSizeCount = std::max(mSizeCount, count);
2756 0 : mMaskModeCount = std::max(mMaskModeCount, count);
2757 0 : mBlendModeCount = std::max(mBlendModeCount, count);
2758 0 : mCompositeCount = std::max(mCompositeCount, count);
2759 : }
2760 :
2761 0 : return *this;
2762 : }
2763 :
2764 : nsStyleImageLayers&
2765 0 : nsStyleImageLayers::operator=(nsStyleImageLayers&& aOther)
2766 : {
2767 0 : mAttachmentCount = aOther.mAttachmentCount;
2768 0 : mClipCount = aOther.mClipCount;
2769 0 : mOriginCount = aOther.mOriginCount;
2770 0 : mRepeatCount = aOther.mRepeatCount;
2771 0 : mPositionXCount = aOther.mPositionXCount;
2772 0 : mPositionYCount = aOther.mPositionYCount;
2773 0 : mImageCount = aOther.mImageCount;
2774 0 : mSizeCount = aOther.mSizeCount;
2775 0 : mMaskModeCount = aOther.mMaskModeCount;
2776 0 : mBlendModeCount = aOther.mBlendModeCount;
2777 0 : mCompositeCount = aOther.mCompositeCount;
2778 0 : mLayers = Move(aOther.mLayers);
2779 :
2780 0 : uint32_t count = mLayers.Length();
2781 0 : if (count != aOther.mLayers.Length()) {
2782 0 : NS_WARNING("truncating counts due to out-of-memory");
2783 0 : mAttachmentCount = std::max(mAttachmentCount, count);
2784 0 : mClipCount = std::max(mClipCount, count);
2785 0 : mOriginCount = std::max(mOriginCount, count);
2786 0 : mRepeatCount = std::max(mRepeatCount, count);
2787 0 : mPositionXCount = std::max(mPositionXCount, count);
2788 0 : mPositionYCount = std::max(mPositionYCount, count);
2789 0 : mImageCount = std::max(mImageCount, count);
2790 0 : mSizeCount = std::max(mSizeCount, count);
2791 0 : mMaskModeCount = std::max(mMaskModeCount, count);
2792 0 : mBlendModeCount = std::max(mBlendModeCount, count);
2793 0 : mCompositeCount = std::max(mCompositeCount, count);
2794 : }
2795 :
2796 0 : return *this;
2797 : }
2798 :
2799 0 : bool nsStyleImageLayers::operator==(const nsStyleImageLayers& aOther) const
2800 : {
2801 0 : if (mAttachmentCount != aOther.mAttachmentCount ||
2802 0 : mClipCount != aOther.mClipCount ||
2803 0 : mOriginCount != aOther.mOriginCount ||
2804 0 : mRepeatCount != aOther.mRepeatCount ||
2805 0 : mPositionXCount != aOther.mPositionXCount ||
2806 0 : mPositionYCount != aOther.mPositionYCount ||
2807 0 : mImageCount != aOther.mImageCount ||
2808 0 : mSizeCount != aOther.mSizeCount ||
2809 0 : mMaskModeCount != aOther.mMaskModeCount ||
2810 0 : mBlendModeCount != aOther.mBlendModeCount) {
2811 0 : return false;
2812 : }
2813 :
2814 0 : if (mLayers.Length() != aOther.mLayers.Length()) {
2815 0 : return false;
2816 : }
2817 :
2818 0 : for (uint32_t i = 0; i < mLayers.Length(); i++) {
2819 0 : if (mLayers[i].mPosition != aOther.mLayers[i].mPosition ||
2820 0 : !DefinitelyEqualURIs(mLayers[i].mImage.GetURLValue(),
2821 0 : aOther.mLayers[i].mImage.GetURLValue()) ||
2822 0 : mLayers[i].mImage != aOther.mLayers[i].mImage ||
2823 0 : mLayers[i].mSize != aOther.mLayers[i].mSize ||
2824 0 : mLayers[i].mClip != aOther.mLayers[i].mClip ||
2825 0 : mLayers[i].mOrigin != aOther.mLayers[i].mOrigin ||
2826 0 : mLayers[i].mAttachment != aOther.mLayers[i].mAttachment ||
2827 0 : mLayers[i].mBlendMode != aOther.mLayers[i].mBlendMode ||
2828 0 : mLayers[i].mComposite != aOther.mLayers[i].mComposite ||
2829 0 : mLayers[i].mMaskMode != aOther.mLayers[i].mMaskMode ||
2830 0 : mLayers[i].mRepeat != aOther.mLayers[i].mRepeat) {
2831 0 : return false;
2832 : }
2833 : }
2834 :
2835 0 : return true;
2836 : }
2837 :
2838 : bool
2839 0 : nsStyleImageLayers::IsInitialPositionForLayerType(Position aPosition, LayerType aType)
2840 : {
2841 0 : if (aPosition.mXPosition.mPercent == 0.0f &&
2842 0 : aPosition.mXPosition.mLength == 0 &&
2843 0 : aPosition.mXPosition.mHasPercent &&
2844 0 : aPosition.mYPosition.mPercent == 0.0f &&
2845 0 : aPosition.mYPosition.mLength == 0 &&
2846 0 : aPosition.mYPosition.mHasPercent) {
2847 0 : return true;
2848 : }
2849 :
2850 0 : return false;
2851 : }
2852 :
2853 : void
2854 227 : Position::SetInitialPercentValues(float aPercentVal)
2855 : {
2856 227 : mXPosition.mPercent = aPercentVal;
2857 227 : mXPosition.mLength = 0;
2858 227 : mXPosition.mHasPercent = true;
2859 227 : mYPosition.mPercent = aPercentVal;
2860 227 : mYPosition.mLength = 0;
2861 227 : mYPosition.mHasPercent = true;
2862 227 : }
2863 :
2864 : void
2865 94 : Position::SetInitialZeroValues()
2866 : {
2867 94 : mXPosition.mPercent = 0;
2868 94 : mXPosition.mLength = 0;
2869 94 : mXPosition.mHasPercent = false;
2870 94 : mYPosition.mPercent = 0;
2871 94 : mYPosition.mLength = 0;
2872 94 : mYPosition.mHasPercent = false;
2873 94 : }
2874 :
2875 : bool
2876 1 : nsStyleImageLayers::Size::DependsOnPositioningAreaSize(const nsStyleImage& aImage) const
2877 : {
2878 1 : MOZ_ASSERT(aImage.GetType() != eStyleImageType_Null,
2879 : "caller should have handled this");
2880 :
2881 : // If either dimension contains a non-zero percentage, rendering for that
2882 : // dimension straightforwardly depends on frame size.
2883 2 : if ((mWidthType == eLengthPercentage && mWidth.mPercent != 0.0f) ||
2884 1 : (mHeightType == eLengthPercentage && mHeight.mPercent != 0.0f)) {
2885 0 : return true;
2886 : }
2887 :
2888 : // So too for contain and cover.
2889 1 : if (mWidthType == eContain || mWidthType == eCover) {
2890 0 : return true;
2891 : }
2892 :
2893 : // If both dimensions are fixed lengths, there's no dependency.
2894 1 : if (mWidthType == eLengthPercentage && mHeightType == eLengthPercentage) {
2895 0 : return false;
2896 : }
2897 :
2898 1 : MOZ_ASSERT((mWidthType == eLengthPercentage && mHeightType == eAuto) ||
2899 : (mWidthType == eAuto && mHeightType == eLengthPercentage) ||
2900 : (mWidthType == eAuto && mHeightType == eAuto),
2901 : "logic error");
2902 :
2903 1 : nsStyleImageType type = aImage.GetType();
2904 :
2905 : // Gradient rendering depends on frame size when auto is involved because
2906 : // gradients have no intrinsic ratio or dimensions, and therefore the relevant
2907 : // dimension is "treat[ed] as 100%".
2908 1 : if (type == eStyleImageType_Gradient) {
2909 1 : return true;
2910 : }
2911 :
2912 : // XXX Element rendering for auto or fixed length doesn't depend on frame size
2913 : // according to the spec. However, we don't implement the spec yet, so
2914 : // for now we bail and say element() plus auto affects ultimate size.
2915 0 : if (type == eStyleImageType_Element) {
2916 0 : return true;
2917 : }
2918 :
2919 0 : if (type == eStyleImageType_Image) {
2920 0 : nsCOMPtr<imgIContainer> imgContainer;
2921 0 : if (imgRequestProxy* req = aImage.GetImageData()) {
2922 0 : req->GetImage(getter_AddRefs(imgContainer));
2923 : }
2924 0 : if (imgContainer) {
2925 0 : CSSIntSize imageSize;
2926 0 : nsSize imageRatio;
2927 : bool hasWidth, hasHeight;
2928 0 : nsLayoutUtils::ComputeSizeForDrawing(imgContainer, imageSize, imageRatio,
2929 0 : hasWidth, hasHeight);
2930 :
2931 : // If the image has a fixed width and height, rendering never depends on
2932 : // the frame size.
2933 0 : if (hasWidth && hasHeight) {
2934 0 : return false;
2935 : }
2936 :
2937 : // If the image has an intrinsic ratio, rendering will depend on frame
2938 : // size when background-size is all auto.
2939 0 : if (imageRatio != nsSize(0, 0)) {
2940 0 : return mWidthType == mHeightType;
2941 : }
2942 :
2943 : // Otherwise, rendering depends on frame size when the image dimensions
2944 : // and background-size don't complement each other.
2945 0 : return !(hasWidth && mHeightType == eLengthPercentage) &&
2946 0 : !(hasHeight && mWidthType == eLengthPercentage);
2947 : }
2948 : } else {
2949 0 : NS_NOTREACHED("missed an enum value");
2950 : }
2951 :
2952 : // Passed the gauntlet: no dependency.
2953 0 : return false;
2954 : }
2955 :
2956 : void
2957 520 : nsStyleImageLayers::Size::SetInitialValues()
2958 : {
2959 520 : mWidthType = mHeightType = eAuto;
2960 520 : }
2961 :
2962 : bool
2963 603 : nsStyleImageLayers::Size::operator==(const Size& aOther) const
2964 : {
2965 603 : MOZ_ASSERT(mWidthType < eDimensionType_COUNT,
2966 : "bad mWidthType for this");
2967 603 : MOZ_ASSERT(mHeightType < eDimensionType_COUNT,
2968 : "bad mHeightType for this");
2969 603 : MOZ_ASSERT(aOther.mWidthType < eDimensionType_COUNT,
2970 : "bad mWidthType for aOther");
2971 603 : MOZ_ASSERT(aOther.mHeightType < eDimensionType_COUNT,
2972 : "bad mHeightType for aOther");
2973 :
2974 1206 : return mWidthType == aOther.mWidthType &&
2975 1206 : mHeightType == aOther.mHeightType &&
2976 2418 : (mWidthType != eLengthPercentage || mWidth == aOther.mWidth) &&
2977 1222 : (mHeightType != eLengthPercentage || mHeight == aOther.mHeight);
2978 : }
2979 :
2980 292 : nsStyleImageLayers::Layer::Layer()
2981 : : mClip(StyleGeometryBox::BorderBox)
2982 : , mAttachment(NS_STYLE_IMAGELAYER_ATTACHMENT_SCROLL)
2983 : , mBlendMode(NS_STYLE_BLEND_NORMAL)
2984 : , mComposite(NS_STYLE_MASK_COMPOSITE_ADD)
2985 292 : , mMaskMode(NS_STYLE_MASK_MODE_MATCH_SOURCE)
2986 : {
2987 292 : mImage.SetNull();
2988 292 : mSize.SetInitialValues();
2989 292 : }
2990 :
2991 131 : nsStyleImageLayers::Layer::~Layer()
2992 : {
2993 131 : }
2994 :
2995 : void
2996 201 : nsStyleImageLayers::Layer::Initialize(nsStyleImageLayers::LayerType aType)
2997 : {
2998 201 : mRepeat.SetInitialValues();
2999 :
3000 201 : mPosition.SetInitialPercentValues(0.0f);
3001 :
3002 201 : if (aType == LayerType::Background) {
3003 175 : mOrigin = StyleGeometryBox::PaddingBox;
3004 : } else {
3005 26 : MOZ_ASSERT(aType == LayerType::Mask, "unsupported layer type.");
3006 26 : mOrigin = StyleGeometryBox::BorderBox;
3007 : }
3008 201 : }
3009 :
3010 : bool
3011 1 : nsStyleImageLayers::Layer::RenderingMightDependOnPositioningAreaSizeChange() const
3012 : {
3013 : // Do we even have an image?
3014 1 : if (mImage.IsEmpty()) {
3015 0 : return false;
3016 : }
3017 :
3018 2 : return mPosition.DependsOnPositioningAreaSize() ||
3019 1 : mSize.DependsOnPositioningAreaSize(mImage) ||
3020 1 : mRepeat.DependsOnPositioningAreaSize();
3021 : }
3022 :
3023 : bool
3024 0 : nsStyleImageLayers::Layer::operator==(const Layer& aOther) const
3025 : {
3026 0 : return mAttachment == aOther.mAttachment &&
3027 0 : mClip == aOther.mClip &&
3028 0 : mOrigin == aOther.mOrigin &&
3029 0 : mRepeat == aOther.mRepeat &&
3030 0 : mBlendMode == aOther.mBlendMode &&
3031 0 : mPosition == aOther.mPosition &&
3032 0 : mSize == aOther.mSize &&
3033 0 : mImage == aOther.mImage &&
3034 0 : mMaskMode == aOther.mMaskMode &&
3035 0 : mComposite == aOther.mComposite;
3036 : }
3037 :
3038 : nsChangeHint
3039 606 : nsStyleImageLayers::Layer::CalcDifference(const nsStyleImageLayers::Layer& aNewLayer) const
3040 : {
3041 606 : nsChangeHint hint = nsChangeHint(0);
3042 606 : if (!DefinitelyEqualURIs(mImage.GetURLValue(),
3043 : aNewLayer.mImage.GetURLValue())) {
3044 2 : hint |= nsChangeHint_RepaintFrame | nsChangeHint_UpdateEffects;
3045 :
3046 : // If mImage links to an SVG mask, the URL in mImage must have a fragment.
3047 : // Not vice versa.
3048 : // Here are examples of URI contains a fragment, two of them link to an
3049 : // SVG mask:
3050 : // mask:url(a.svg#maskID); // The fragment of this URI is an ID of a mask
3051 : // // element in a.svg.
3052 : // mask:url(#localMaskID); // The fragment of this URI is an ID of a mask
3053 : // // element in local document.
3054 : // mask:url(b.svg#viewBoxID); // The fragment of this URI is an ID of a
3055 : // // viewbox defined in b.svg.
3056 : // That is, if the URL in mImage has a fragment, it may link to an SVG
3057 : // mask; If not, it "must" not link to an SVG mask.
3058 2 : bool maybeSVGMask = false;
3059 2 : if (mImage.GetURLValue()) {
3060 0 : maybeSVGMask = mImage.GetURLValue()->MightHaveRef();
3061 : }
3062 :
3063 2 : if (!maybeSVGMask && aNewLayer.mImage.GetURLValue()) {
3064 2 : maybeSVGMask = aNewLayer.mImage.GetURLValue()->MightHaveRef();
3065 : }
3066 :
3067 : // Return nsChangeHint_UpdateOverflow if either URI might link to an SVG
3068 : // mask.
3069 2 : if (maybeSVGMask) {
3070 : // Mask changes require that we update the PreEffectsBBoxProperty,
3071 : // which is done during overflow computation.
3072 0 : hint |= nsChangeHint_UpdateOverflow;
3073 : }
3074 1812 : } else if (mAttachment != aNewLayer.mAttachment ||
3075 1207 : mClip != aNewLayer.mClip ||
3076 1206 : mOrigin != aNewLayer.mOrigin ||
3077 1206 : mRepeat != aNewLayer.mRepeat ||
3078 1206 : mBlendMode != aNewLayer.mBlendMode ||
3079 1206 : mSize != aNewLayer.mSize ||
3080 1205 : mImage != aNewLayer.mImage ||
3081 1808 : mMaskMode != aNewLayer.mMaskMode ||
3082 602 : mComposite != aNewLayer.mComposite) {
3083 2 : hint |= nsChangeHint_RepaintFrame;
3084 : }
3085 :
3086 606 : if (mPosition != aNewLayer.mPosition) {
3087 0 : hint |= nsChangeHint_UpdateBackgroundPosition;
3088 : }
3089 :
3090 606 : return hint;
3091 : }
3092 :
3093 : // --------------------
3094 : // nsStyleBackground
3095 : //
3096 :
3097 175 : nsStyleBackground::nsStyleBackground(const nsPresContext* aContext)
3098 : : mImage(nsStyleImageLayers::LayerType::Background)
3099 175 : , mBackgroundColor(StyleComplexColor::FromColor(NS_RGBA(0, 0, 0, 0)))
3100 : {
3101 175 : MOZ_COUNT_CTOR(nsStyleBackground);
3102 175 : }
3103 :
3104 73 : nsStyleBackground::nsStyleBackground(const nsStyleBackground& aSource)
3105 : : mImage(aSource.mImage)
3106 73 : , mBackgroundColor(aSource.mBackgroundColor)
3107 : {
3108 73 : MOZ_COUNT_CTOR(nsStyleBackground);
3109 73 : }
3110 :
3111 238 : nsStyleBackground::~nsStyleBackground()
3112 : {
3113 119 : MOZ_COUNT_DTOR(nsStyleBackground);
3114 119 : }
3115 :
3116 : void
3117 69 : nsStyleBackground::Destroy(nsPresContext* aContext)
3118 : {
3119 69 : this->~nsStyleBackground();
3120 : aContext->PresShell()->
3121 69 : FreeByObjectID(eArenaObjectID_nsStyleBackground, this);
3122 69 : }
3123 :
3124 : void
3125 0 : nsStyleBackground::FinishStyle(nsPresContext* aPresContext)
3126 : {
3127 0 : MOZ_ASSERT(NS_IsMainThread());
3128 0 : MOZ_ASSERT(aPresContext->StyleSet()->IsServo());
3129 :
3130 0 : mImage.ResolveImages(aPresContext);
3131 0 : }
3132 :
3133 : nsChangeHint
3134 302 : nsStyleBackground::CalcDifference(const nsStyleBackground& aNewData) const
3135 : {
3136 302 : nsChangeHint hint = nsChangeHint(0);
3137 302 : if (mBackgroundColor != aNewData.mBackgroundColor) {
3138 2 : hint |= nsChangeHint_RepaintFrame;
3139 : }
3140 :
3141 : hint |= mImage.CalcDifference(aNewData.mImage,
3142 302 : nsStyleImageLayers::LayerType::Background);
3143 :
3144 302 : return hint;
3145 : }
3146 :
3147 : bool
3148 0 : nsStyleBackground::HasFixedBackground(nsIFrame* aFrame) const
3149 : {
3150 0 : NS_FOR_VISIBLE_IMAGE_LAYERS_BACK_TO_FRONT(i, mImage) {
3151 0 : const nsStyleImageLayers::Layer &layer = mImage.mLayers[i];
3152 0 : if (layer.mAttachment == NS_STYLE_IMAGELAYER_ATTACHMENT_FIXED &&
3153 0 : !layer.mImage.IsEmpty() &&
3154 0 : !nsLayoutUtils::IsTransformed(aFrame)) {
3155 0 : return true;
3156 : }
3157 : }
3158 0 : return false;
3159 : }
3160 :
3161 : nscolor
3162 49 : nsStyleBackground::BackgroundColor(const nsIFrame* aFrame) const
3163 : {
3164 49 : return BackgroundColor(aFrame->StyleContext());
3165 : }
3166 :
3167 : nscolor
3168 2575 : nsStyleBackground::BackgroundColor(nsStyleContext* aContext) const
3169 : {
3170 : // In majority of cases, background-color should just be a numeric color.
3171 : // In that case, we can skip resolving StyleColor().
3172 2575 : return mBackgroundColor.IsNumericColor()
3173 2575 : ? mBackgroundColor.mColor
3174 2575 : : aContext->StyleColor()->CalcComplexColor(mBackgroundColor);
3175 : }
3176 :
3177 : bool
3178 2894 : nsStyleBackground::IsTransparent(const nsIFrame* aFrame) const
3179 : {
3180 2894 : return IsTransparent(aFrame->StyleContext());
3181 : }
3182 :
3183 : bool
3184 2894 : nsStyleBackground::IsTransparent(nsStyleContext* aContext) const
3185 : {
3186 5492 : return BottomLayer().mImage.IsEmpty() &&
3187 5420 : mImage.mImageCount == 1 &&
3188 5420 : NS_GET_A(BackgroundColor(aContext)) == 0;
3189 : }
3190 :
3191 : void
3192 1823 : nsTimingFunction::AssignFromKeyword(int32_t aTimingFunctionType)
3193 : {
3194 1823 : switch (aTimingFunctionType) {
3195 : case NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_START:
3196 0 : mType = Type::StepStart;
3197 0 : mStepsOrFrames = 1;
3198 0 : return;
3199 : default:
3200 0 : MOZ_FALLTHROUGH_ASSERT("aTimingFunctionType must be a keyword value");
3201 : case NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END:
3202 0 : mType = Type::StepEnd;
3203 0 : mStepsOrFrames = 1;
3204 0 : return;
3205 : case NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE:
3206 : case NS_STYLE_TRANSITION_TIMING_FUNCTION_LINEAR:
3207 : case NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE_IN:
3208 : case NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE_OUT:
3209 : case NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE_IN_OUT:
3210 1823 : mType = static_cast<Type>(aTimingFunctionType);
3211 1823 : break;
3212 : }
3213 :
3214 : static_assert(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE == 0 &&
3215 : NS_STYLE_TRANSITION_TIMING_FUNCTION_LINEAR == 1 &&
3216 : NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE_IN == 2 &&
3217 : NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE_OUT == 3 &&
3218 : NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE_IN_OUT == 4,
3219 : "transition timing function constants not as expected");
3220 :
3221 : static const float timingFunctionValues[5][4] = {
3222 : { 0.25f, 0.10f, 0.25f, 1.00f }, // ease
3223 : { 0.00f, 0.00f, 1.00f, 1.00f }, // linear
3224 : { 0.42f, 0.00f, 1.00f, 1.00f }, // ease-in
3225 : { 0.00f, 0.00f, 0.58f, 1.00f }, // ease-out
3226 : { 0.42f, 0.00f, 0.58f, 1.00f } // ease-in-out
3227 : };
3228 :
3229 1823 : MOZ_ASSERT(0 <= aTimingFunctionType && aTimingFunctionType < 5,
3230 : "keyword out of range");
3231 1823 : mFunc.mX1 = timingFunctionValues[aTimingFunctionType][0];
3232 1823 : mFunc.mY1 = timingFunctionValues[aTimingFunctionType][1];
3233 1823 : mFunc.mX2 = timingFunctionValues[aTimingFunctionType][2];
3234 1823 : mFunc.mY2 = timingFunctionValues[aTimingFunctionType][3];
3235 : }
3236 :
3237 0 : StyleTransition::StyleTransition(const StyleTransition& aCopy)
3238 : : mTimingFunction(aCopy.mTimingFunction)
3239 0 : , mDuration(aCopy.mDuration)
3240 0 : , mDelay(aCopy.mDelay)
3241 0 : , mProperty(aCopy.mProperty)
3242 0 : , mUnknownProperty(aCopy.mUnknownProperty)
3243 : {
3244 0 : }
3245 :
3246 : void
3247 94 : StyleTransition::SetInitialValues()
3248 : {
3249 94 : mTimingFunction = nsTimingFunction(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE);
3250 94 : mDuration = 0.0;
3251 94 : mDelay = 0.0;
3252 94 : mProperty = eCSSPropertyExtra_all_properties;
3253 94 : }
3254 :
3255 : void
3256 0 : StyleTransition::SetUnknownProperty(nsCSSPropertyID aProperty,
3257 : const nsAString& aPropertyString)
3258 : {
3259 0 : MOZ_ASSERT(nsCSSProps::LookupProperty(aPropertyString,
3260 : CSSEnabledState::eForAllContent) ==
3261 : aProperty,
3262 : "property and property string should match");
3263 0 : nsCOMPtr<nsIAtom> temp = NS_Atomize(aPropertyString);
3264 0 : SetUnknownProperty(aProperty, temp);
3265 0 : }
3266 :
3267 : void
3268 0 : StyleTransition::SetUnknownProperty(nsCSSPropertyID aProperty,
3269 : nsIAtom* aPropertyString)
3270 : {
3271 0 : MOZ_ASSERT(aProperty == eCSSProperty_UNKNOWN ||
3272 : aProperty == eCSSPropertyExtra_variable,
3273 : "should be either unknown or custom property");
3274 0 : mProperty = aProperty;
3275 0 : mUnknownProperty = aPropertyString;
3276 0 : }
3277 :
3278 : bool
3279 368 : StyleTransition::operator==(const StyleTransition& aOther) const
3280 : {
3281 736 : return mTimingFunction == aOther.mTimingFunction &&
3282 736 : mDuration == aOther.mDuration &&
3283 736 : mDelay == aOther.mDelay &&
3284 1468 : mProperty == aOther.mProperty &&
3285 366 : (mProperty != eCSSProperty_UNKNOWN ||
3286 368 : mUnknownProperty == aOther.mUnknownProperty);
3287 : }
3288 :
3289 0 : StyleAnimation::StyleAnimation(const StyleAnimation& aCopy)
3290 : : mTimingFunction(aCopy.mTimingFunction)
3291 0 : , mDuration(aCopy.mDuration)
3292 0 : , mDelay(aCopy.mDelay)
3293 : , mName(aCopy.mName)
3294 0 : , mDirection(aCopy.mDirection)
3295 0 : , mFillMode(aCopy.mFillMode)
3296 0 : , mPlayState(aCopy.mPlayState)
3297 0 : , mIterationCount(aCopy.mIterationCount)
3298 : {
3299 0 : }
3300 :
3301 : void
3302 94 : StyleAnimation::SetInitialValues()
3303 : {
3304 94 : mTimingFunction = nsTimingFunction(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE);
3305 94 : mDuration = 0.0;
3306 94 : mDelay = 0.0;
3307 94 : mName = EmptyString();
3308 94 : mDirection = dom::PlaybackDirection::Normal;
3309 94 : mFillMode = dom::FillMode::None;
3310 94 : mPlayState = NS_STYLE_ANIMATION_PLAY_STATE_RUNNING;
3311 94 : mIterationCount = 1.0f;
3312 94 : }
3313 :
3314 : bool
3315 343 : StyleAnimation::operator==(const StyleAnimation& aOther) const
3316 : {
3317 684 : return mTimingFunction == aOther.mTimingFunction &&
3318 682 : mDuration == aOther.mDuration &&
3319 682 : mDelay == aOther.mDelay &&
3320 682 : mName == aOther.mName &&
3321 682 : mDirection == aOther.mDirection &&
3322 682 : mFillMode == aOther.mFillMode &&
3323 1025 : mPlayState == aOther.mPlayState &&
3324 684 : mIterationCount == aOther.mIterationCount;
3325 : }
3326 :
3327 : // --------------------
3328 : // nsStyleDisplay
3329 : //
3330 94 : nsStyleDisplay::nsStyleDisplay(const nsPresContext* aContext)
3331 : : mDisplay(StyleDisplay::Inline)
3332 : , mOriginalDisplay(StyleDisplay::Inline)
3333 : , mContain(NS_STYLE_CONTAIN_NONE)
3334 : , mAppearance(NS_THEME_NONE)
3335 : , mPosition(NS_STYLE_POSITION_STATIC)
3336 : , mFloat(StyleFloat::None)
3337 : , mOriginalFloat(StyleFloat::None)
3338 : , mBreakType(StyleClear::None)
3339 : , mBreakInside(NS_STYLE_PAGE_BREAK_AUTO)
3340 : , mBreakBefore(false)
3341 : , mBreakAfter(false)
3342 : , mOverflowX(NS_STYLE_OVERFLOW_VISIBLE)
3343 : , mOverflowY(NS_STYLE_OVERFLOW_VISIBLE)
3344 : , mOverflowClipBox(NS_STYLE_OVERFLOW_CLIP_BOX_PADDING_BOX)
3345 : , mResize(NS_STYLE_RESIZE_NONE)
3346 : , mOrient(StyleOrient::Inline)
3347 : , mIsolation(NS_STYLE_ISOLATION_AUTO)
3348 : , mTopLayer(NS_STYLE_TOP_LAYER_NONE)
3349 : , mWillChangeBitField(0)
3350 : , mTouchAction(NS_STYLE_TOUCH_ACTION_AUTO)
3351 : , mScrollBehavior(NS_STYLE_SCROLL_BEHAVIOR_AUTO)
3352 : , mScrollSnapTypeX(NS_STYLE_SCROLL_SNAP_TYPE_NONE)
3353 : , mScrollSnapTypeY(NS_STYLE_SCROLL_SNAP_TYPE_NONE)
3354 : , mScrollSnapPointsX(eStyleUnit_None)
3355 : , mScrollSnapPointsY(eStyleUnit_None)
3356 : , mBackfaceVisibility(NS_STYLE_BACKFACE_VISIBILITY_VISIBLE)
3357 : , mTransformStyle(NS_STYLE_TRANSFORM_STYLE_FLAT)
3358 : , mTransformBox(StyleGeometryBox::BorderBox)
3359 : , mSpecifiedTransform(nullptr)
3360 : , mTransformOrigin{ {0.5f, eStyleUnit_Percent}, // Transform is centered on origin
3361 : {0.5f, eStyleUnit_Percent},
3362 : {0, nsStyleCoord::CoordConstructor} }
3363 : , mChildPerspective(eStyleUnit_None)
3364 : , mPerspectiveOrigin{ {0.5f, eStyleUnit_Percent},
3365 : {0.5f, eStyleUnit_Percent} }
3366 : , mVerticalAlign(NS_STYLE_VERTICAL_ALIGN_BASELINE, eStyleUnit_Enumerated)
3367 : , mTransitions(nsStyleAutoArray<StyleTransition>::WITH_SINGLE_INITIAL_ELEMENT)
3368 : , mTransitionTimingFunctionCount(1)
3369 : , mTransitionDurationCount(1)
3370 : , mTransitionDelayCount(1)
3371 : , mTransitionPropertyCount(1)
3372 : , mAnimations(nsStyleAutoArray<StyleAnimation>::WITH_SINGLE_INITIAL_ELEMENT)
3373 : , mAnimationTimingFunctionCount(1)
3374 : , mAnimationDurationCount(1)
3375 : , mAnimationDelayCount(1)
3376 : , mAnimationNameCount(1)
3377 : , mAnimationDirectionCount(1)
3378 : , mAnimationFillModeCount(1)
3379 : , mAnimationPlayStateCount(1)
3380 94 : , mAnimationIterationCountCount(1)
3381 : {
3382 94 : MOZ_COUNT_CTOR(nsStyleDisplay);
3383 :
3384 : // Initial value for mScrollSnapDestination is "0px 0px"
3385 94 : mScrollSnapDestination.SetInitialZeroValues();
3386 :
3387 94 : mTransitions[0].SetInitialValues();
3388 94 : mAnimations[0].SetInitialValues();
3389 94 : }
3390 :
3391 677 : nsStyleDisplay::nsStyleDisplay(const nsStyleDisplay& aSource)
3392 : : mBinding(aSource.mBinding)
3393 677 : , mDisplay(aSource.mDisplay)
3394 677 : , mOriginalDisplay(aSource.mOriginalDisplay)
3395 677 : , mContain(aSource.mContain)
3396 677 : , mAppearance(aSource.mAppearance)
3397 677 : , mPosition(aSource.mPosition)
3398 677 : , mFloat(aSource.mFloat)
3399 677 : , mOriginalFloat(aSource.mOriginalFloat)
3400 677 : , mBreakType(aSource.mBreakType)
3401 677 : , mBreakInside(aSource.mBreakInside)
3402 677 : , mBreakBefore(aSource.mBreakBefore)
3403 677 : , mBreakAfter(aSource.mBreakAfter)
3404 677 : , mOverflowX(aSource.mOverflowX)
3405 677 : , mOverflowY(aSource.mOverflowY)
3406 677 : , mOverflowClipBox(aSource.mOverflowClipBox)
3407 677 : , mResize(aSource.mResize)
3408 677 : , mOrient(aSource.mOrient)
3409 677 : , mIsolation(aSource.mIsolation)
3410 677 : , mTopLayer(aSource.mTopLayer)
3411 677 : , mWillChangeBitField(aSource.mWillChangeBitField)
3412 : , mWillChange(aSource.mWillChange)
3413 677 : , mTouchAction(aSource.mTouchAction)
3414 677 : , mScrollBehavior(aSource.mScrollBehavior)
3415 677 : , mScrollSnapTypeX(aSource.mScrollSnapTypeX)
3416 677 : , mScrollSnapTypeY(aSource.mScrollSnapTypeY)
3417 : , mScrollSnapPointsX(aSource.mScrollSnapPointsX)
3418 : , mScrollSnapPointsY(aSource.mScrollSnapPointsY)
3419 : , mScrollSnapDestination(aSource.mScrollSnapDestination)
3420 : , mScrollSnapCoordinate(aSource.mScrollSnapCoordinate)
3421 677 : , mBackfaceVisibility(aSource.mBackfaceVisibility)
3422 677 : , mTransformStyle(aSource.mTransformStyle)
3423 677 : , mTransformBox(aSource.mTransformBox)
3424 : , mSpecifiedTransform(aSource.mSpecifiedTransform)
3425 : , mTransformOrigin{ aSource.mTransformOrigin[0],
3426 : aSource.mTransformOrigin[1],
3427 : aSource.mTransformOrigin[2] }
3428 : , mChildPerspective(aSource.mChildPerspective)
3429 : , mPerspectiveOrigin{ aSource.mPerspectiveOrigin[0],
3430 : aSource.mPerspectiveOrigin[1] }
3431 : , mVerticalAlign(aSource.mVerticalAlign)
3432 : , mTransitions(aSource.mTransitions)
3433 677 : , mTransitionTimingFunctionCount(aSource.mTransitionTimingFunctionCount)
3434 677 : , mTransitionDurationCount(aSource.mTransitionDurationCount)
3435 677 : , mTransitionDelayCount(aSource.mTransitionDelayCount)
3436 677 : , mTransitionPropertyCount(aSource.mTransitionPropertyCount)
3437 : , mAnimations(aSource.mAnimations)
3438 677 : , mAnimationTimingFunctionCount(aSource.mAnimationTimingFunctionCount)
3439 677 : , mAnimationDurationCount(aSource.mAnimationDurationCount)
3440 677 : , mAnimationDelayCount(aSource.mAnimationDelayCount)
3441 677 : , mAnimationNameCount(aSource.mAnimationNameCount)
3442 677 : , mAnimationDirectionCount(aSource.mAnimationDirectionCount)
3443 677 : , mAnimationFillModeCount(aSource.mAnimationFillModeCount)
3444 677 : , mAnimationPlayStateCount(aSource.mAnimationPlayStateCount)
3445 677 : , mAnimationIterationCountCount(aSource.mAnimationIterationCountCount)
3446 26403 : , mShapeOutside(aSource.mShapeOutside)
3447 : {
3448 677 : MOZ_COUNT_CTOR(nsStyleDisplay);
3449 677 : }
3450 :
3451 808 : nsStyleDisplay::~nsStyleDisplay()
3452 : {
3453 : // We don't allow releasing nsCSSValues with refcounted data in the Servo
3454 : // traversal, since the refcounts aren't threadsafe. Since Servo may trigger
3455 : // the deallocation of style structs during styling, we need to handle it
3456 : // here.
3457 404 : if (mSpecifiedTransform && ServoStyleSet::IsInServoTraversal()) {
3458 : // The default behavior of NS_ReleaseOnMainThread is to only proxy the
3459 : // release if we're not already on the main thread. This is a nice
3460 : // optimization for the cases we happen to be doing a sequential traversal
3461 : // (i.e. a single-core machine), but it trips our assertions which check
3462 : // whether we're in a Servo traversal, parallel or not. So we
3463 : // unconditionally proxy in debug builds.
3464 : bool alwaysProxy =
3465 : #ifdef DEBUG
3466 0 : true;
3467 : #else
3468 : false;
3469 : #endif
3470 0 : NS_ReleaseOnMainThread(
3471 : "nsStyleDisplay::mSpecifiedTransform",
3472 0 : mSpecifiedTransform.forget(), alwaysProxy);
3473 : }
3474 :
3475 404 : MOZ_COUNT_DTOR(nsStyleDisplay);
3476 404 : }
3477 :
3478 : nsChangeHint
3479 358 : nsStyleDisplay::CalcDifference(const nsStyleDisplay& aNewData) const
3480 : {
3481 358 : nsChangeHint hint = nsChangeHint(0);
3482 :
3483 716 : if (!DefinitelyEqualURIsAndPrincipal(mBinding.ForceGet(), aNewData.mBinding.ForceGet())
3484 353 : || mPosition != aNewData.mPosition
3485 350 : || mDisplay != aNewData.mDisplay
3486 348 : || mContain != aNewData.mContain
3487 348 : || (mFloat == StyleFloat::None) != (aNewData.mFloat == StyleFloat::None)
3488 348 : || mScrollBehavior != aNewData.mScrollBehavior
3489 348 : || mScrollSnapTypeX != aNewData.mScrollSnapTypeX
3490 348 : || mScrollSnapTypeY != aNewData.mScrollSnapTypeY
3491 348 : || mScrollSnapPointsX != aNewData.mScrollSnapPointsX
3492 348 : || mScrollSnapPointsY != aNewData.mScrollSnapPointsY
3493 348 : || mScrollSnapDestination != aNewData.mScrollSnapDestination
3494 348 : || mTopLayer != aNewData.mTopLayer
3495 706 : || mResize != aNewData.mResize) {
3496 10 : hint |= nsChangeHint_ReconstructFrame;
3497 : }
3498 :
3499 358 : if (mOverflowX != aNewData.mOverflowX
3500 358 : || mOverflowY != aNewData.mOverflowY) {
3501 0 : hint |= nsChangeHint_CSSOverflowChange;
3502 : }
3503 :
3504 : /* Note: When mScrollBehavior, mScrollSnapTypeX, mScrollSnapTypeY,
3505 : * mScrollSnapPointsX, mScrollSnapPointsY, or mScrollSnapDestination are
3506 : * changed, nsChangeHint_NeutralChange is not sufficient to enter
3507 : * nsCSSFrameConstructor::PropagateScrollToViewport. By using the same hint
3508 : * as used when the overflow css property changes,
3509 : * nsChangeHint_ReconstructFrame, PropagateScrollToViewport will be called.
3510 : *
3511 : * The scroll-behavior css property is not expected to change often (the
3512 : * CSSOM-View DOM methods are likely to be used in those cases); however,
3513 : * if this does become common perhaps a faster-path might be worth while.
3514 : */
3515 :
3516 358 : if ((mAppearance == NS_THEME_TEXTFIELD &&
3517 358 : aNewData.mAppearance != NS_THEME_TEXTFIELD) ||
3518 716 : (mAppearance != NS_THEME_TEXTFIELD &&
3519 358 : aNewData.mAppearance == NS_THEME_TEXTFIELD)) {
3520 : // This is for <input type=number> where we allow authors to specify a
3521 : // |-moz-appearance:textfield| to get a control without a spinner. (The
3522 : // spinner is present for |-moz-appearance:number-input| but also other
3523 : // values such as 'none'.) We need to reframe since we want to use
3524 : // nsTextControlFrame instead of nsNumberControlFrame if the author
3525 : // specifies 'textfield'.
3526 0 : return nsChangeHint_ReconstructFrame;
3527 : }
3528 :
3529 358 : if (mFloat != aNewData.mFloat) {
3530 : // Changing which side we float on doesn't affect descendants directly
3531 : hint |= nsChangeHint_AllReflowHints &
3532 : ~(nsChangeHint_ClearDescendantIntrinsics |
3533 0 : nsChangeHint_NeedDirtyReflow);
3534 : }
3535 :
3536 358 : if (mVerticalAlign != aNewData.mVerticalAlign) {
3537 : // XXX Can this just be AllReflowHints + RepaintFrame, and be included in
3538 : // the block below?
3539 0 : hint |= NS_STYLE_HINT_REFLOW;
3540 : }
3541 :
3542 : // XXX the following is conservative, for now: changing float breaking shouldn't
3543 : // necessarily require a repaint, reflow should suffice.
3544 358 : if (mBreakType != aNewData.mBreakType
3545 358 : || mBreakInside != aNewData.mBreakInside
3546 358 : || mBreakBefore != aNewData.mBreakBefore
3547 358 : || mBreakAfter != aNewData.mBreakAfter
3548 358 : || mAppearance != aNewData.mAppearance
3549 357 : || mOrient != aNewData.mOrient
3550 357 : || mOverflowClipBox != aNewData.mOverflowClipBox) {
3551 : hint |= nsChangeHint_AllReflowHints |
3552 1 : nsChangeHint_RepaintFrame;
3553 : }
3554 :
3555 358 : if (mIsolation != aNewData.mIsolation) {
3556 0 : hint |= nsChangeHint_RepaintFrame;
3557 : }
3558 :
3559 : /* If we've added or removed the transform property, we need to reconstruct the frame to add
3560 : * or remove the view object, and also to handle abs-pos and fixed-pos containers.
3561 : */
3562 358 : if (HasTransformStyle() != aNewData.HasTransformStyle()) {
3563 : // We do not need to apply nsChangeHint_UpdateTransformLayer since
3564 : // nsChangeHint_RepaintFrame will forcibly invalidate the frame area and
3565 : // ensure layers are rebuilt (or removed).
3566 : hint |= nsChangeHint_UpdateContainingBlock |
3567 : nsChangeHint_AddOrRemoveTransform |
3568 : nsChangeHint_UpdateOverflow |
3569 2 : nsChangeHint_RepaintFrame;
3570 : } else {
3571 : /* Otherwise, if we've kept the property lying around and we already had a
3572 : * transform, we need to see whether or not we've changed the transform.
3573 : * If so, we need to recompute its overflow rect (which probably changed
3574 : * if the transform changed) and to redraw within the bounds of that new
3575 : * overflow rect.
3576 : *
3577 : * If the property isn't present in either style struct, we still do the
3578 : * comparisons but turn all the resulting change hints into
3579 : * nsChangeHint_NeutralChange.
3580 : */
3581 356 : nsChangeHint transformHint = nsChangeHint(0);
3582 :
3583 712 : if (!mSpecifiedTransform != !aNewData.mSpecifiedTransform ||
3584 8 : (mSpecifiedTransform &&
3585 364 : *mSpecifiedTransform != *aNewData.mSpecifiedTransform)) {
3586 0 : transformHint |= nsChangeHint_UpdateTransformLayer;
3587 :
3588 0 : if (mSpecifiedTransform &&
3589 0 : aNewData.mSpecifiedTransform) {
3590 0 : transformHint |= nsChangeHint_UpdatePostTransformOverflow;
3591 : } else {
3592 0 : transformHint |= nsChangeHint_UpdateOverflow;
3593 : }
3594 : }
3595 :
3596 : const nsChangeHint kUpdateOverflowAndRepaintHint =
3597 356 : nsChangeHint_UpdateOverflow | nsChangeHint_RepaintFrame;
3598 1424 : for (uint8_t index = 0; index < 3; ++index) {
3599 1068 : if (mTransformOrigin[index] != aNewData.mTransformOrigin[index]) {
3600 : transformHint |= nsChangeHint_UpdateTransformLayer |
3601 0 : nsChangeHint_UpdatePostTransformOverflow;
3602 0 : break;
3603 : }
3604 : }
3605 :
3606 1068 : for (uint8_t index = 0; index < 2; ++index) {
3607 712 : if (mPerspectiveOrigin[index] != aNewData.mPerspectiveOrigin[index]) {
3608 0 : transformHint |= kUpdateOverflowAndRepaintHint;
3609 0 : break;
3610 : }
3611 : }
3612 :
3613 356 : if (HasPerspectiveStyle() != aNewData.HasPerspectiveStyle()) {
3614 : // A change from/to being a containing block for position:fixed.
3615 0 : hint |= nsChangeHint_UpdateContainingBlock;
3616 : }
3617 :
3618 1068 : if (mChildPerspective != aNewData.mChildPerspective ||
3619 712 : mTransformStyle != aNewData.mTransformStyle ||
3620 356 : mTransformBox != aNewData.mTransformBox) {
3621 0 : transformHint |= kUpdateOverflowAndRepaintHint;
3622 : }
3623 :
3624 356 : if (mBackfaceVisibility != aNewData.mBackfaceVisibility) {
3625 0 : transformHint |= nsChangeHint_RepaintFrame;
3626 : }
3627 :
3628 356 : if (transformHint) {
3629 0 : if (HasTransformStyle()) {
3630 0 : hint |= transformHint;
3631 : } else {
3632 0 : hint |= nsChangeHint_NeutralChange;
3633 : }
3634 : }
3635 : }
3636 :
3637 : // Note that the HasTransformStyle() != aNewData.HasTransformStyle()
3638 : // test above handles relevant changes in the
3639 : // NS_STYLE_WILL_CHANGE_TRANSFORM bit, which in turn handles frame
3640 : // reconstruction for changes in the containing block of
3641 : // fixed-positioned elements.
3642 : uint8_t willChangeBitsChanged =
3643 358 : mWillChangeBitField ^ aNewData.mWillChangeBitField;
3644 358 : if (willChangeBitsChanged & (NS_STYLE_WILL_CHANGE_STACKING_CONTEXT |
3645 : NS_STYLE_WILL_CHANGE_SCROLL |
3646 : NS_STYLE_WILL_CHANGE_OPACITY)) {
3647 0 : hint |= nsChangeHint_RepaintFrame;
3648 : }
3649 :
3650 358 : if (willChangeBitsChanged & NS_STYLE_WILL_CHANGE_FIXPOS_CB) {
3651 0 : hint |= nsChangeHint_UpdateContainingBlock;
3652 : }
3653 :
3654 : // If touch-action is changed, we need to regenerate the event regions on
3655 : // the layers and send it over to the compositor for APZ to handle.
3656 358 : if (mTouchAction != aNewData.mTouchAction) {
3657 0 : hint |= nsChangeHint_RepaintFrame;
3658 : }
3659 :
3660 : // Note: Our current behavior for handling changes to the
3661 : // transition-duration, transition-delay, and transition-timing-function
3662 : // properties is to do nothing. In other words, the transition
3663 : // property that matters is what it is when the transition begins, and
3664 : // we don't stop a transition later because the transition property
3665 : // changed.
3666 : // We do handle changes to transition-property, but we don't need to
3667 : // bother with anything here, since the transition manager is notified
3668 : // of any style context change anyway.
3669 :
3670 : // Note: Likewise, for animation-*, the animation manager gets
3671 : // notified about every new style context constructed, and it uses
3672 : // that opportunity to handle dynamic changes appropriately.
3673 :
3674 : // But we still need to return nsChangeHint_NeutralChange for these
3675 : // properties, since some data did change in the style struct.
3676 :
3677 707 : if (!hint &&
3678 690 : (mOriginalDisplay != aNewData.mOriginalDisplay ||
3679 690 : mOriginalFloat != aNewData.mOriginalFloat ||
3680 688 : mTransitions != aNewData.mTransitions ||
3681 343 : mTransitionTimingFunctionCount !=
3682 686 : aNewData.mTransitionTimingFunctionCount ||
3683 686 : mTransitionDurationCount != aNewData.mTransitionDurationCount ||
3684 686 : mTransitionDelayCount != aNewData.mTransitionDelayCount ||
3685 686 : mTransitionPropertyCount != aNewData.mTransitionPropertyCount ||
3686 684 : mAnimations != aNewData.mAnimations ||
3687 682 : mAnimationTimingFunctionCount != aNewData.mAnimationTimingFunctionCount ||
3688 682 : mAnimationDurationCount != aNewData.mAnimationDurationCount ||
3689 682 : mAnimationDelayCount != aNewData.mAnimationDelayCount ||
3690 682 : mAnimationNameCount != aNewData.mAnimationNameCount ||
3691 682 : mAnimationDirectionCount != aNewData.mAnimationDirectionCount ||
3692 682 : mAnimationFillModeCount != aNewData.mAnimationFillModeCount ||
3693 682 : mAnimationPlayStateCount != aNewData.mAnimationPlayStateCount ||
3694 682 : mAnimationIterationCountCount != aNewData.mAnimationIterationCountCount ||
3695 682 : mScrollSnapCoordinate != aNewData.mScrollSnapCoordinate ||
3696 341 : !mShapeOutside.DefinitelyEquals(aNewData.mShapeOutside))) {
3697 4 : hint |= nsChangeHint_NeutralChange;
3698 : }
3699 :
3700 358 : return hint;
3701 : }
3702 :
3703 : // --------------------
3704 : // nsStyleVisibility
3705 : //
3706 :
3707 129 : nsStyleVisibility::nsStyleVisibility(const nsPresContext* aContext)
3708 129 : : mDirection(aContext->GetBidi() == IBMBIDI_TEXTDIRECTION_RTL
3709 : ? NS_STYLE_DIRECTION_RTL
3710 : : NS_STYLE_DIRECTION_LTR)
3711 : , mVisible(NS_STYLE_VISIBILITY_VISIBLE)
3712 : , mImageRendering(NS_STYLE_IMAGE_RENDERING_AUTO)
3713 : , mWritingMode(NS_STYLE_WRITING_MODE_HORIZONTAL_TB)
3714 : , mTextOrientation(NS_STYLE_TEXT_ORIENTATION_MIXED)
3715 258 : , mColorAdjust(NS_STYLE_COLOR_ADJUST_ECONOMY)
3716 : {
3717 129 : MOZ_COUNT_CTOR(nsStyleVisibility);
3718 129 : }
3719 :
3720 142 : nsStyleVisibility::nsStyleVisibility(const nsStyleVisibility& aSource)
3721 : : mImageOrientation(aSource.mImageOrientation)
3722 142 : , mDirection(aSource.mDirection)
3723 142 : , mVisible(aSource.mVisible)
3724 142 : , mImageRendering(aSource.mImageRendering)
3725 142 : , mWritingMode(aSource.mWritingMode)
3726 142 : , mTextOrientation(aSource.mTextOrientation)
3727 852 : , mColorAdjust(aSource.mColorAdjust)
3728 : {
3729 142 : MOZ_COUNT_CTOR(nsStyleVisibility);
3730 142 : }
3731 :
3732 : nsChangeHint
3733 217 : nsStyleVisibility::CalcDifference(const nsStyleVisibility& aNewData) const
3734 : {
3735 217 : nsChangeHint hint = nsChangeHint(0);
3736 :
3737 217 : if (mDirection != aNewData.mDirection || mWritingMode != aNewData.mWritingMode) {
3738 : // It's important that a change in mWritingMode results in frame
3739 : // reconstruction, because it may affect intrinsic size (see
3740 : // nsSubDocumentFrame::GetIntrinsicISize/BSize).
3741 : // Also, the used writing-mode value is now a field on nsIFrame and some
3742 : // classes (e.g. table rows/cells) copy their value from an ancestor.
3743 0 : hint |= nsChangeHint_ReconstructFrame;
3744 : } else {
3745 217 : if ((mImageOrientation != aNewData.mImageOrientation)) {
3746 : hint |= nsChangeHint_AllReflowHints |
3747 0 : nsChangeHint_RepaintFrame;
3748 : }
3749 217 : if (mVisible != aNewData.mVisible) {
3750 62 : if ((NS_STYLE_VISIBILITY_COLLAPSE == mVisible) ||
3751 14 : (NS_STYLE_VISIBILITY_COLLAPSE == aNewData.mVisible)) {
3752 48 : hint |= NS_STYLE_HINT_REFLOW;
3753 : } else {
3754 0 : hint |= NS_STYLE_HINT_VISUAL;
3755 : }
3756 : }
3757 217 : if (mTextOrientation != aNewData.mTextOrientation) {
3758 0 : hint |= NS_STYLE_HINT_REFLOW;
3759 : }
3760 217 : if (mImageRendering != aNewData.mImageRendering) {
3761 0 : hint |= nsChangeHint_RepaintFrame;
3762 : }
3763 217 : if (mColorAdjust != aNewData.mColorAdjust) {
3764 : // color-adjust only affects media where dynamic changes can't happen.
3765 0 : hint |= nsChangeHint_NeutralChange;
3766 : }
3767 : }
3768 217 : return hint;
3769 : }
3770 :
3771 8 : nsStyleContentData::~nsStyleContentData()
3772 : {
3773 4 : MOZ_COUNT_DTOR(nsStyleContentData);
3774 :
3775 4 : if (mType == eStyleContentType_Image) {
3776 : NS_ReleaseOnMainThread(
3777 0 : "nsStyleContentData::mContent.mImage", dont_AddRef(mContent.mImage));
3778 0 : mContent.mImage = nullptr;
3779 8 : } else if (mType == eStyleContentType_Counter ||
3780 4 : mType == eStyleContentType_Counters) {
3781 0 : mContent.mCounters->Release();
3782 4 : } else if (mContent.mString) {
3783 4 : free(mContent.mString);
3784 : }
3785 4 : }
3786 :
3787 0 : nsStyleContentData::nsStyleContentData(const nsStyleContentData& aOther)
3788 0 : : mType(aOther.mType)
3789 : {
3790 0 : MOZ_COUNT_CTOR(nsStyleContentData);
3791 0 : if (mType == eStyleContentType_Image) {
3792 0 : mContent.mImage = aOther.mContent.mImage;
3793 0 : mContent.mImage->AddRef();
3794 0 : } else if (mType == eStyleContentType_Counter ||
3795 0 : mType == eStyleContentType_Counters) {
3796 0 : mContent.mCounters = aOther.mContent.mCounters;
3797 0 : mContent.mCounters->AddRef();
3798 0 : } else if (aOther.mContent.mString) {
3799 0 : mContent.mString = NS_strdup(aOther.mContent.mString);
3800 : } else {
3801 0 : mContent.mString = nullptr;
3802 : }
3803 0 : }
3804 :
3805 : bool
3806 0 : nsStyleContentData::
3807 : CounterFunction::operator==(const CounterFunction& aOther) const
3808 : {
3809 0 : return mIdent == aOther.mIdent &&
3810 0 : mSeparator == aOther.mSeparator &&
3811 0 : mCounterStyle == aOther.mCounterStyle;
3812 : }
3813 :
3814 : nsStyleContentData&
3815 0 : nsStyleContentData::operator=(const nsStyleContentData& aOther)
3816 : {
3817 0 : if (this == &aOther) {
3818 0 : return *this;
3819 : }
3820 0 : this->~nsStyleContentData();
3821 0 : new (this) nsStyleContentData(aOther);
3822 :
3823 0 : return *this;
3824 : }
3825 :
3826 : bool
3827 6 : nsStyleContentData::operator==(const nsStyleContentData& aOther) const
3828 : {
3829 6 : if (mType != aOther.mType) {
3830 0 : return false;
3831 : }
3832 6 : if (mType == eStyleContentType_Image) {
3833 0 : return DefinitelyEqualImages(mContent.mImage, aOther.mContent.mImage);
3834 : }
3835 12 : if (mType == eStyleContentType_Counter ||
3836 6 : mType == eStyleContentType_Counters) {
3837 0 : return *mContent.mCounters == *aOther.mContent.mCounters;
3838 : }
3839 6 : return safe_strcmp(mContent.mString, aOther.mContent.mString) == 0;
3840 : }
3841 :
3842 : void
3843 0 : nsStyleContentData::Resolve(nsPresContext* aPresContext)
3844 : {
3845 0 : switch (mType) {
3846 : case eStyleContentType_Image:
3847 0 : if (!mContent.mImage->IsResolved()) {
3848 0 : mContent.mImage->Resolve(aPresContext);
3849 : }
3850 0 : break;
3851 : case eStyleContentType_Counter:
3852 : case eStyleContentType_Counters: {
3853 0 : mContent.mCounters->
3854 0 : mCounterStyle.Resolve(aPresContext->CounterStyleManager());
3855 0 : break;
3856 : }
3857 : default:
3858 0 : break;
3859 : }
3860 0 : }
3861 :
3862 :
3863 : //-----------------------
3864 : // nsStyleContent
3865 : //
3866 :
3867 26 : nsStyleContent::nsStyleContent(const nsPresContext* aContext)
3868 : {
3869 26 : MOZ_COUNT_CTOR(nsStyleContent);
3870 26 : }
3871 :
3872 12 : nsStyleContent::~nsStyleContent()
3873 : {
3874 6 : MOZ_COUNT_DTOR(nsStyleContent);
3875 6 : }
3876 :
3877 : void
3878 6 : nsStyleContent::Destroy(nsPresContext* aContext)
3879 : {
3880 6 : this->~nsStyleContent();
3881 6 : aContext->PresShell()->FreeByObjectID(eArenaObjectID_nsStyleContent, this);
3882 6 : }
3883 :
3884 : void
3885 0 : nsStyleContent::FinishStyle(nsPresContext* aPresContext)
3886 : {
3887 0 : for (nsStyleContentData& data : mContents) {
3888 0 : data.Resolve(aPresContext);
3889 : }
3890 0 : }
3891 :
3892 8 : nsStyleContent::nsStyleContent(const nsStyleContent& aSource)
3893 : : mContents(aSource.mContents)
3894 : , mIncrements(aSource.mIncrements)
3895 8 : , mResets(aSource.mResets)
3896 : {
3897 8 : MOZ_COUNT_CTOR(nsStyleContent);
3898 8 : }
3899 :
3900 : nsChangeHint
3901 284 : nsStyleContent::CalcDifference(const nsStyleContent& aNewData) const
3902 : {
3903 : // In ElementRestyler::Restyle we assume that if there's no existing
3904 : // ::before or ::after and we don't have to restyle children of the
3905 : // node then we can't end up with a ::before or ::after due to the
3906 : // restyle of the node itself. That's not quite true, but the only
3907 : // exception to the above is when the 'content' property of the node
3908 : // changes and the pseudo-element inherits the changed value. Since
3909 : // the code here triggers a frame change on the node in that case,
3910 : // the optimization in ElementRestyler::Restyle is ok. But if we ever
3911 : // change this code to not reconstruct frames on changes to the
3912 : // 'content' property, then we will need to revisit the optimization
3913 : // in ElementRestyler::Restyle.
3914 :
3915 : // Unfortunately we need to reframe even if the content lengths are the same;
3916 : // a simple reflow will not pick up different text or different image URLs,
3917 : // since we set all that up in the CSSFrameConstructor
3918 : //
3919 : // Also note that we also rely on this to return ReconstructFrame when
3920 : // content changes to ensure that nsCounterUseNode wouldn't reference
3921 : // to stale counter stylex.
3922 852 : if (mContents != aNewData.mContents ||
3923 568 : mIncrements != aNewData.mIncrements ||
3924 284 : mResets != aNewData.mResets) {
3925 0 : return nsChangeHint_ReconstructFrame;
3926 : }
3927 :
3928 284 : return nsChangeHint(0);
3929 : }
3930 :
3931 : // --------------------
3932 : // nsStyleTextReset
3933 : //
3934 :
3935 26 : nsStyleTextReset::nsStyleTextReset(const nsPresContext* aContext)
3936 : : mTextDecorationLine(NS_STYLE_TEXT_DECORATION_LINE_NONE)
3937 : , mTextDecorationStyle(NS_STYLE_TEXT_DECORATION_STYLE_SOLID)
3938 : , mUnicodeBidi(NS_STYLE_UNICODE_BIDI_NORMAL)
3939 : , mInitialLetterSink(0)
3940 : , mInitialLetterSize(0.0f)
3941 26 : , mTextDecorationColor(StyleComplexColor::CurrentColor())
3942 : {
3943 26 : MOZ_COUNT_CTOR(nsStyleTextReset);
3944 26 : }
3945 :
3946 95 : nsStyleTextReset::nsStyleTextReset(const nsStyleTextReset& aSource)
3947 : {
3948 95 : MOZ_COUNT_CTOR(nsStyleTextReset);
3949 95 : *this = aSource;
3950 95 : }
3951 :
3952 136 : nsStyleTextReset::~nsStyleTextReset()
3953 : {
3954 68 : MOZ_COUNT_DTOR(nsStyleTextReset);
3955 68 : }
3956 :
3957 : nsChangeHint
3958 323 : nsStyleTextReset::CalcDifference(const nsStyleTextReset& aNewData) const
3959 : {
3960 646 : if (mUnicodeBidi != aNewData.mUnicodeBidi ||
3961 646 : mInitialLetterSink != aNewData.mInitialLetterSink ||
3962 323 : mInitialLetterSize != aNewData.mInitialLetterSize) {
3963 0 : return NS_STYLE_HINT_REFLOW;
3964 : }
3965 :
3966 646 : if (mTextDecorationLine != aNewData.mTextDecorationLine ||
3967 323 : mTextDecorationStyle != aNewData.mTextDecorationStyle) {
3968 : // Changes to our text-decoration line can impact our overflow area &
3969 : // also our descendants' overflow areas (particularly for text-frame
3970 : // descendants). So, we update those areas & trigger a repaint.
3971 : return nsChangeHint_RepaintFrame |
3972 0 : nsChangeHint_UpdateSubtreeOverflow |
3973 0 : nsChangeHint_SchedulePaint;
3974 : }
3975 :
3976 : // Repaint for decoration color changes
3977 323 : if (mTextDecorationColor != aNewData.mTextDecorationColor) {
3978 0 : return nsChangeHint_RepaintFrame;
3979 : }
3980 :
3981 323 : if (mTextOverflow != aNewData.mTextOverflow) {
3982 0 : return nsChangeHint_RepaintFrame;
3983 : }
3984 :
3985 323 : return nsChangeHint(0);
3986 : }
3987 :
3988 : // Returns true if the given shadow-arrays are equal.
3989 : static bool
3990 372 : AreShadowArraysEqual(nsCSSShadowArray* lhs,
3991 : nsCSSShadowArray* rhs)
3992 : {
3993 372 : if (lhs == rhs) {
3994 369 : return true;
3995 : }
3996 :
3997 3 : if (!lhs || !rhs || lhs->Length() != rhs->Length()) {
3998 0 : return false;
3999 : }
4000 :
4001 6 : for (uint32_t i = 0; i < lhs->Length(); ++i) {
4002 3 : if (*lhs->ShadowAt(i) != *rhs->ShadowAt(i)) {
4003 0 : return false;
4004 : }
4005 : }
4006 3 : return true;
4007 : }
4008 :
4009 : // --------------------
4010 : // nsStyleText
4011 : //
4012 :
4013 55 : nsStyleText::nsStyleText(const nsPresContext* aContext)
4014 : : mTextAlign(NS_STYLE_TEXT_ALIGN_START)
4015 : , mTextAlignLast(NS_STYLE_TEXT_ALIGN_AUTO)
4016 : , mTextAlignTrue(false)
4017 : , mTextAlignLastTrue(false)
4018 : , mTextJustify(StyleTextJustify::Auto)
4019 : , mTextTransform(NS_STYLE_TEXT_TRANSFORM_NONE)
4020 : , mWhiteSpace(StyleWhiteSpace::Normal)
4021 : , mWordBreak(NS_STYLE_WORDBREAK_NORMAL)
4022 : , mOverflowWrap(NS_STYLE_OVERFLOWWRAP_NORMAL)
4023 : , mHyphens(StyleHyphens::Manual)
4024 : , mRubyAlign(NS_STYLE_RUBY_ALIGN_SPACE_AROUND)
4025 : , mRubyPosition(NS_STYLE_RUBY_POSITION_OVER)
4026 : , mTextSizeAdjust(NS_STYLE_TEXT_SIZE_ADJUST_AUTO)
4027 : , mTextCombineUpright(NS_STYLE_TEXT_COMBINE_UPRIGHT_NONE)
4028 55 : , mControlCharacterVisibility(nsCSSParser::ControlCharVisibilityDefault())
4029 : , mTextEmphasisStyle(NS_STYLE_TEXT_EMPHASIS_STYLE_NONE)
4030 : , mTextRendering(NS_STYLE_TEXT_RENDERING_AUTO)
4031 : , mTextEmphasisColor(StyleComplexColor::CurrentColor())
4032 : , mWebkitTextFillColor(StyleComplexColor::CurrentColor())
4033 : , mWebkitTextStrokeColor(StyleComplexColor::CurrentColor())
4034 : , mTabSize(float(NS_STYLE_TABSIZE_INITIAL), eStyleUnit_Factor)
4035 : , mWordSpacing(0, nsStyleCoord::CoordConstructor)
4036 : , mLetterSpacing(eStyleUnit_Normal)
4037 : , mLineHeight(eStyleUnit_Normal)
4038 : , mTextIndent(0, nsStyleCoord::CoordConstructor)
4039 : , mWebkitTextStrokeWidth(0)
4040 110 : , mTextShadow(nullptr)
4041 : {
4042 55 : MOZ_COUNT_CTOR(nsStyleText);
4043 110 : nsCOMPtr<nsIAtom> language = aContext->GetContentLanguage();
4044 55 : mTextEmphasisPosition = language &&
4045 55 : nsStyleUtil::MatchesLanguagePrefix(language, u"zh") ?
4046 : NS_STYLE_TEXT_EMPHASIS_POSITION_DEFAULT_ZH :
4047 55 : NS_STYLE_TEXT_EMPHASIS_POSITION_DEFAULT;
4048 55 : }
4049 :
4050 46 : nsStyleText::nsStyleText(const nsStyleText& aSource)
4051 46 : : mTextAlign(aSource.mTextAlign)
4052 46 : , mTextAlignLast(aSource.mTextAlignLast)
4053 : , mTextAlignTrue(false)
4054 : , mTextAlignLastTrue(false)
4055 46 : , mTextJustify(aSource.mTextJustify)
4056 46 : , mTextTransform(aSource.mTextTransform)
4057 46 : , mWhiteSpace(aSource.mWhiteSpace)
4058 46 : , mWordBreak(aSource.mWordBreak)
4059 46 : , mOverflowWrap(aSource.mOverflowWrap)
4060 46 : , mHyphens(aSource.mHyphens)
4061 46 : , mRubyAlign(aSource.mRubyAlign)
4062 46 : , mRubyPosition(aSource.mRubyPosition)
4063 46 : , mTextSizeAdjust(aSource.mTextSizeAdjust)
4064 46 : , mTextCombineUpright(aSource.mTextCombineUpright)
4065 46 : , mControlCharacterVisibility(aSource.mControlCharacterVisibility)
4066 46 : , mTextEmphasisPosition(aSource.mTextEmphasisPosition)
4067 46 : , mTextEmphasisStyle(aSource.mTextEmphasisStyle)
4068 46 : , mTextRendering(aSource.mTextRendering)
4069 : , mTextEmphasisColor(aSource.mTextEmphasisColor)
4070 : , mWebkitTextFillColor(aSource.mWebkitTextFillColor)
4071 : , mWebkitTextStrokeColor(aSource.mWebkitTextStrokeColor)
4072 : , mTabSize(aSource.mTabSize)
4073 : , mWordSpacing(aSource.mWordSpacing)
4074 : , mLetterSpacing(aSource.mLetterSpacing)
4075 : , mLineHeight(aSource.mLineHeight)
4076 : , mTextIndent(aSource.mTextIndent)
4077 46 : , mWebkitTextStrokeWidth(aSource.mWebkitTextStrokeWidth)
4078 : , mTextShadow(aSource.mTextShadow)
4079 782 : , mTextEmphasisStyleString(aSource.mTextEmphasisStyleString)
4080 : {
4081 46 : MOZ_COUNT_CTOR(nsStyleText);
4082 46 : }
4083 :
4084 72 : nsStyleText::~nsStyleText()
4085 : {
4086 36 : MOZ_COUNT_DTOR(nsStyleText);
4087 36 : }
4088 :
4089 : nsChangeHint
4090 77 : nsStyleText::CalcDifference(const nsStyleText& aNewData) const
4091 : {
4092 154 : if (WhiteSpaceOrNewlineIsSignificant() !=
4093 77 : aNewData.WhiteSpaceOrNewlineIsSignificant()) {
4094 : // This may require construction of suppressed text frames
4095 0 : return nsChangeHint_ReconstructFrame;
4096 : }
4097 :
4098 154 : if (mTextCombineUpright != aNewData.mTextCombineUpright ||
4099 77 : mControlCharacterVisibility != aNewData.mControlCharacterVisibility) {
4100 0 : return nsChangeHint_ReconstructFrame;
4101 : }
4102 :
4103 231 : if ((mTextAlign != aNewData.mTextAlign) ||
4104 154 : (mTextAlignLast != aNewData.mTextAlignLast) ||
4105 154 : (mTextAlignTrue != aNewData.mTextAlignTrue) ||
4106 154 : (mTextAlignLastTrue != aNewData.mTextAlignLastTrue) ||
4107 154 : (mTextTransform != aNewData.mTextTransform) ||
4108 154 : (mWhiteSpace != aNewData.mWhiteSpace) ||
4109 154 : (mWordBreak != aNewData.mWordBreak) ||
4110 154 : (mOverflowWrap != aNewData.mOverflowWrap) ||
4111 154 : (mHyphens != aNewData.mHyphens) ||
4112 154 : (mRubyAlign != aNewData.mRubyAlign) ||
4113 154 : (mRubyPosition != aNewData.mRubyPosition) ||
4114 154 : (mTextSizeAdjust != aNewData.mTextSizeAdjust) ||
4115 154 : (mLetterSpacing != aNewData.mLetterSpacing) ||
4116 154 : (mLineHeight != aNewData.mLineHeight) ||
4117 154 : (mTextIndent != aNewData.mTextIndent) ||
4118 154 : (mTextJustify != aNewData.mTextJustify) ||
4119 231 : (mWordSpacing != aNewData.mWordSpacing) ||
4120 77 : (mTabSize != aNewData.mTabSize)) {
4121 0 : return NS_STYLE_HINT_REFLOW;
4122 : }
4123 :
4124 154 : if (HasTextEmphasis() != aNewData.HasTextEmphasis() ||
4125 77 : (HasTextEmphasis() &&
4126 0 : mTextEmphasisPosition != aNewData.mTextEmphasisPosition)) {
4127 : // Text emphasis position change could affect line height calculation.
4128 0 : return nsChangeHint_AllReflowHints |
4129 0 : nsChangeHint_RepaintFrame;
4130 : }
4131 :
4132 77 : nsChangeHint hint = nsChangeHint(0);
4133 :
4134 : // text-rendering changes require a reflow since they change SVG
4135 : // frames' rects.
4136 77 : if (mTextRendering != aNewData.mTextRendering) {
4137 : hint |= nsChangeHint_NeedReflow |
4138 : nsChangeHint_NeedDirtyReflow | // XXX remove me: bug 876085
4139 0 : nsChangeHint_RepaintFrame;
4140 : }
4141 :
4142 231 : if (!AreShadowArraysEqual(mTextShadow, aNewData.mTextShadow) ||
4143 154 : mTextEmphasisStyle != aNewData.mTextEmphasisStyle ||
4144 231 : mTextEmphasisStyleString != aNewData.mTextEmphasisStyleString ||
4145 77 : mWebkitTextStrokeWidth != aNewData.mWebkitTextStrokeWidth) {
4146 : hint |= nsChangeHint_UpdateSubtreeOverflow |
4147 : nsChangeHint_SchedulePaint |
4148 0 : nsChangeHint_RepaintFrame;
4149 :
4150 : // We don't add any other hints below.
4151 0 : return hint;
4152 : }
4153 :
4154 231 : if (mTextEmphasisColor != aNewData.mTextEmphasisColor ||
4155 154 : mWebkitTextFillColor != aNewData.mWebkitTextFillColor ||
4156 77 : mWebkitTextStrokeColor != aNewData.mWebkitTextStrokeColor) {
4157 : hint |= nsChangeHint_SchedulePaint |
4158 0 : nsChangeHint_RepaintFrame;
4159 : }
4160 :
4161 77 : if (hint) {
4162 0 : return hint;
4163 : }
4164 :
4165 77 : if (mTextEmphasisPosition != aNewData.mTextEmphasisPosition) {
4166 0 : return nsChangeHint_NeutralChange;
4167 : }
4168 :
4169 77 : return nsChangeHint(0);
4170 : }
4171 :
4172 : LogicalSide
4173 0 : nsStyleText::TextEmphasisSide(WritingMode aWM) const
4174 : {
4175 0 : MOZ_ASSERT(
4176 : (!(mTextEmphasisPosition & NS_STYLE_TEXT_EMPHASIS_POSITION_LEFT) !=
4177 : !(mTextEmphasisPosition & NS_STYLE_TEXT_EMPHASIS_POSITION_RIGHT)) &&
4178 : (!(mTextEmphasisPosition & NS_STYLE_TEXT_EMPHASIS_POSITION_OVER) !=
4179 : !(mTextEmphasisPosition & NS_STYLE_TEXT_EMPHASIS_POSITION_UNDER)));
4180 0 : mozilla::Side side = aWM.IsVertical() ?
4181 0 : (mTextEmphasisPosition & NS_STYLE_TEXT_EMPHASIS_POSITION_LEFT
4182 0 : ? eSideLeft : eSideRight) :
4183 0 : (mTextEmphasisPosition & NS_STYLE_TEXT_EMPHASIS_POSITION_OVER
4184 0 : ? eSideTop : eSideBottom);
4185 0 : LogicalSide result = aWM.LogicalSideForPhysicalSide(side);
4186 0 : MOZ_ASSERT(IsBlock(result));
4187 0 : return result;
4188 : }
4189 :
4190 : //-----------------------
4191 : // nsStyleUserInterface
4192 : //
4193 :
4194 0 : nsCursorImage::nsCursorImage()
4195 : : mHaveHotspot(false)
4196 : , mHotspotX(0.0f)
4197 0 : , mHotspotY(0.0f)
4198 : {
4199 0 : }
4200 :
4201 0 : nsCursorImage::nsCursorImage(const nsCursorImage& aOther)
4202 0 : : mHaveHotspot(aOther.mHaveHotspot)
4203 0 : , mHotspotX(aOther.mHotspotX)
4204 0 : , mHotspotY(aOther.mHotspotY)
4205 0 : , mImage(aOther.mImage)
4206 : {
4207 0 : }
4208 :
4209 : nsCursorImage&
4210 0 : nsCursorImage::operator=(const nsCursorImage& aOther)
4211 : {
4212 0 : if (this != &aOther) {
4213 0 : mHaveHotspot = aOther.mHaveHotspot;
4214 0 : mHotspotX = aOther.mHotspotX;
4215 0 : mHotspotY = aOther.mHotspotY;
4216 0 : mImage = aOther.mImage;
4217 : }
4218 :
4219 0 : return *this;
4220 : }
4221 :
4222 : bool
4223 0 : nsCursorImage::operator==(const nsCursorImage& aOther) const
4224 : {
4225 0 : NS_ASSERTION(mHaveHotspot ||
4226 : (mHotspotX == 0 && mHotspotY == 0),
4227 : "expected mHotspot{X,Y} to be 0 when mHaveHotspot is false");
4228 0 : NS_ASSERTION(aOther.mHaveHotspot ||
4229 : (aOther.mHotspotX == 0 && aOther.mHotspotY == 0),
4230 : "expected mHotspot{X,Y} to be 0 when mHaveHotspot is false");
4231 0 : return mHaveHotspot == aOther.mHaveHotspot &&
4232 0 : mHotspotX == aOther.mHotspotX &&
4233 0 : mHotspotY == aOther.mHotspotY &&
4234 0 : DefinitelyEqualImages(mImage, aOther.mImage);
4235 : }
4236 :
4237 187 : nsStyleUserInterface::nsStyleUserInterface(const nsPresContext* aContext)
4238 : : mUserInput(StyleUserInput::Auto)
4239 : , mUserModify(StyleUserModify::ReadOnly)
4240 : , mUserFocus(StyleUserFocus::None)
4241 : , mPointerEvents(NS_STYLE_POINTER_EVENTS_AUTO)
4242 : , mCursor(NS_STYLE_CURSOR_AUTO)
4243 187 : , mCaretColor(StyleComplexColor::Auto())
4244 : {
4245 187 : MOZ_COUNT_CTOR(nsStyleUserInterface);
4246 187 : }
4247 :
4248 1490 : nsStyleUserInterface::nsStyleUserInterface(const nsStyleUserInterface& aSource)
4249 1490 : : mUserInput(aSource.mUserInput)
4250 1490 : , mUserModify(aSource.mUserModify)
4251 1490 : , mUserFocus(aSource.mUserFocus)
4252 1490 : , mPointerEvents(aSource.mPointerEvents)
4253 1490 : , mCursor(aSource.mCursor)
4254 : , mCursorImages(aSource.mCursorImages)
4255 7450 : , mCaretColor(aSource.mCaretColor)
4256 : {
4257 1490 : MOZ_COUNT_CTOR(nsStyleUserInterface);
4258 1490 : }
4259 :
4260 2614 : nsStyleUserInterface::~nsStyleUserInterface()
4261 : {
4262 1307 : MOZ_COUNT_DTOR(nsStyleUserInterface);
4263 1307 : }
4264 :
4265 : void
4266 0 : nsStyleUserInterface::FinishStyle(nsPresContext* aPresContext)
4267 : {
4268 0 : MOZ_ASSERT(NS_IsMainThread());
4269 0 : MOZ_ASSERT(aPresContext->StyleSet()->IsServo());
4270 :
4271 0 : for (nsCursorImage& cursor : mCursorImages) {
4272 0 : if (cursor.mImage && !cursor.mImage->IsResolved()) {
4273 0 : cursor.mImage->Resolve(aPresContext);
4274 : }
4275 : }
4276 0 : }
4277 :
4278 : nsChangeHint
4279 655 : nsStyleUserInterface::CalcDifference(const nsStyleUserInterface& aNewData) const
4280 : {
4281 655 : nsChangeHint hint = nsChangeHint(0);
4282 655 : if (mCursor != aNewData.mCursor) {
4283 0 : hint |= nsChangeHint_UpdateCursor;
4284 : }
4285 :
4286 : // We could do better. But it wouldn't be worth it, URL-specified cursors are
4287 : // rare.
4288 655 : if (mCursorImages != aNewData.mCursorImages) {
4289 0 : hint |= nsChangeHint_UpdateCursor;
4290 : }
4291 :
4292 655 : if (mPointerEvents != aNewData.mPointerEvents) {
4293 : // SVGGeometryFrame's mRect depends on stroke _and_ on the value
4294 : // of pointer-events. See SVGGeometryFrame::ReflowSVG's use of
4295 : // GetHitTestFlags. (Only a reflow, no visual change.)
4296 : hint |= nsChangeHint_NeedReflow |
4297 14 : nsChangeHint_NeedDirtyReflow; // XXX remove me: bug 876085
4298 : }
4299 :
4300 655 : if (mUserModify != aNewData.mUserModify) {
4301 0 : hint |= NS_STYLE_HINT_VISUAL;
4302 : }
4303 :
4304 655 : if (mUserInput != aNewData.mUserInput) {
4305 0 : if (StyleUserInput::None == mUserInput ||
4306 0 : StyleUserInput::None == aNewData.mUserInput) {
4307 0 : hint |= nsChangeHint_ReconstructFrame;
4308 : } else {
4309 0 : hint |= nsChangeHint_NeutralChange;
4310 : }
4311 : }
4312 :
4313 655 : if (mUserFocus != aNewData.mUserFocus) {
4314 2 : hint |= nsChangeHint_NeutralChange;
4315 : }
4316 :
4317 655 : if (mCaretColor != aNewData.mCaretColor) {
4318 0 : hint |= nsChangeHint_RepaintFrame;
4319 : }
4320 :
4321 655 : return hint;
4322 : }
4323 :
4324 : //-----------------------
4325 : // nsStyleUIReset
4326 : //
4327 :
4328 3 : nsStyleUIReset::nsStyleUIReset(const nsPresContext* aContext)
4329 : : mUserSelect(StyleUserSelect::Auto)
4330 : , mForceBrokenImageIcon(0)
4331 : , mIMEMode(NS_STYLE_IME_MODE_AUTO)
4332 : , mWindowDragging(StyleWindowDragging::Default)
4333 : , mWindowShadow(NS_STYLE_WINDOW_SHADOW_DEFAULT)
4334 : , mWindowOpacity(1.0)
4335 : , mSpecifiedWindowTransform(nullptr)
4336 : , mWindowTransformOrigin{ {0.5f, eStyleUnit_Percent}, // Transform is centered on origin
4337 3 : {0.5f, eStyleUnit_Percent} }
4338 : {
4339 3 : MOZ_COUNT_CTOR(nsStyleUIReset);
4340 3 : }
4341 :
4342 6 : nsStyleUIReset::nsStyleUIReset(const nsStyleUIReset& aSource)
4343 6 : : mUserSelect(aSource.mUserSelect)
4344 6 : , mForceBrokenImageIcon(aSource.mForceBrokenImageIcon)
4345 6 : , mIMEMode(aSource.mIMEMode)
4346 6 : , mWindowDragging(aSource.mWindowDragging)
4347 6 : , mWindowShadow(aSource.mWindowShadow)
4348 6 : , mWindowOpacity(aSource.mWindowOpacity)
4349 : , mSpecifiedWindowTransform(aSource.mSpecifiedWindowTransform)
4350 : , mWindowTransformOrigin{ aSource.mWindowTransformOrigin[0],
4351 36 : aSource.mWindowTransformOrigin[1] }
4352 : {
4353 6 : MOZ_COUNT_CTOR(nsStyleUIReset);
4354 6 : }
4355 :
4356 2 : nsStyleUIReset::~nsStyleUIReset()
4357 : {
4358 1 : MOZ_COUNT_DTOR(nsStyleUIReset);
4359 :
4360 : // See the nsStyleDisplay destructor for why we're doing this.
4361 1 : if (mSpecifiedWindowTransform && ServoStyleSet::IsInServoTraversal()) {
4362 : bool alwaysProxy =
4363 : #ifdef DEBUG
4364 0 : true;
4365 : #else
4366 : false;
4367 : #endif
4368 0 : NS_ReleaseOnMainThread(
4369 : "nsStyleUIReset::mSpecifiedWindowTransform",
4370 0 : mSpecifiedWindowTransform.forget(), alwaysProxy);
4371 : }
4372 1 : }
4373 :
4374 : nsChangeHint
4375 13 : nsStyleUIReset::CalcDifference(const nsStyleUIReset& aNewData) const
4376 : {
4377 13 : nsChangeHint hint = nsChangeHint(0);
4378 :
4379 13 : if (mForceBrokenImageIcon != aNewData.mForceBrokenImageIcon) {
4380 0 : hint |= nsChangeHint_ReconstructFrame;
4381 : }
4382 13 : if (mWindowShadow != aNewData.mWindowShadow) {
4383 : // We really need just an nsChangeHint_SyncFrameView, except
4384 : // on an ancestor of the frame, so we get that by doing a
4385 : // reflow.
4386 0 : hint |= NS_STYLE_HINT_REFLOW;
4387 : }
4388 13 : if (mUserSelect != aNewData.mUserSelect) {
4389 0 : hint |= NS_STYLE_HINT_VISUAL;
4390 : }
4391 :
4392 13 : if (mWindowDragging != aNewData.mWindowDragging) {
4393 0 : hint |= nsChangeHint_SchedulePaint;
4394 : }
4395 :
4396 39 : if (mWindowOpacity != aNewData.mWindowOpacity ||
4397 26 : !mSpecifiedWindowTransform != !aNewData.mSpecifiedWindowTransform ||
4398 0 : (mSpecifiedWindowTransform &&
4399 13 : *mSpecifiedWindowTransform != *aNewData.mSpecifiedWindowTransform)) {
4400 0 : hint |= nsChangeHint_UpdateWidgetProperties;
4401 : } else {
4402 39 : for (uint8_t index = 0; index < 2; ++index) {
4403 26 : if (mWindowTransformOrigin[index] !=
4404 26 : aNewData.mWindowTransformOrigin[index]) {
4405 0 : hint |= nsChangeHint_UpdateWidgetProperties;
4406 0 : break;
4407 : }
4408 : }
4409 : }
4410 :
4411 26 : if (!hint &&
4412 13 : mIMEMode != aNewData.mIMEMode) {
4413 0 : hint |= nsChangeHint_NeutralChange;
4414 : }
4415 :
4416 13 : return hint;
4417 : }
4418 :
4419 : //-----------------------
4420 : // nsStyleVariables
4421 : //
4422 :
4423 0 : nsStyleVariables::nsStyleVariables()
4424 : {
4425 0 : MOZ_COUNT_CTOR(nsStyleVariables);
4426 0 : }
4427 :
4428 15 : nsStyleVariables::nsStyleVariables(const nsPresContext* aContext)
4429 : {
4430 15 : MOZ_COUNT_CTOR(nsStyleVariables);
4431 15 : }
4432 :
4433 0 : nsStyleVariables::nsStyleVariables(const nsStyleVariables& aSource)
4434 0 : : mVariables(aSource.mVariables)
4435 : {
4436 0 : MOZ_COUNT_CTOR(nsStyleVariables);
4437 0 : }
4438 :
4439 24 : nsStyleVariables::~nsStyleVariables()
4440 : {
4441 12 : MOZ_COUNT_DTOR(nsStyleVariables);
4442 12 : }
4443 :
4444 : nsChangeHint
4445 0 : nsStyleVariables::CalcDifference(const nsStyleVariables& aNewData) const
4446 : {
4447 0 : return nsChangeHint(0);
4448 : }
4449 :
4450 : //-----------------------
4451 : // nsStyleEffects
4452 : //
4453 :
4454 26 : nsStyleEffects::nsStyleEffects(const nsPresContext* aContext)
4455 : : mBoxShadow(nullptr)
4456 : , mClip(0, 0, 0, 0)
4457 : , mOpacity(1.0f)
4458 : , mClipFlags(NS_STYLE_CLIP_AUTO)
4459 26 : , mMixBlendMode(NS_STYLE_BLEND_NORMAL)
4460 : {
4461 26 : MOZ_COUNT_CTOR(nsStyleEffects);
4462 26 : }
4463 :
4464 61 : nsStyleEffects::nsStyleEffects(const nsStyleEffects& aSource)
4465 : : mFilters(aSource.mFilters)
4466 : , mBoxShadow(aSource.mBoxShadow)
4467 : , mClip(aSource.mClip)
4468 61 : , mOpacity(aSource.mOpacity)
4469 61 : , mClipFlags(aSource.mClipFlags)
4470 183 : , mMixBlendMode(aSource.mMixBlendMode)
4471 : {
4472 61 : MOZ_COUNT_CTOR(nsStyleEffects);
4473 61 : }
4474 :
4475 78 : nsStyleEffects::~nsStyleEffects()
4476 : {
4477 39 : MOZ_COUNT_DTOR(nsStyleEffects);
4478 39 : }
4479 :
4480 : nsChangeHint
4481 295 : nsStyleEffects::CalcDifference(const nsStyleEffects& aNewData) const
4482 : {
4483 295 : nsChangeHint hint = nsChangeHint(0);
4484 :
4485 295 : if (!AreShadowArraysEqual(mBoxShadow, aNewData.mBoxShadow)) {
4486 : // Update overflow regions & trigger DLBI to be sure it's noticed.
4487 : // Also request a repaint, since it's possible that only the color
4488 : // of the shadow is changing (and UpdateOverflow/SchedulePaint won't
4489 : // repaint for that, since they won't know what needs invalidating.)
4490 : hint |= nsChangeHint_UpdateOverflow |
4491 : nsChangeHint_SchedulePaint |
4492 0 : nsChangeHint_RepaintFrame;
4493 : }
4494 :
4495 295 : if (mClipFlags != aNewData.mClipFlags) {
4496 : hint |= nsChangeHint_AllReflowHints |
4497 0 : nsChangeHint_RepaintFrame;
4498 : }
4499 :
4500 295 : if (!mClip.IsEqualInterior(aNewData.mClip)) {
4501 : // If the clip has changed, we just need to update overflow areas. DLBI
4502 : // will handle the invalidation.
4503 : hint |= nsChangeHint_UpdateOverflow |
4504 0 : nsChangeHint_SchedulePaint;
4505 : }
4506 :
4507 295 : if (mOpacity != aNewData.mOpacity) {
4508 : // If we're going from the optimized >=0.99 opacity value to 1.0 or back, then
4509 : // repaint the frame because DLBI will not catch the invalidation. Otherwise,
4510 : // just update the opacity layer.
4511 46 : if ((mOpacity >= 0.99f && mOpacity < 1.0f && aNewData.mOpacity == 1.0f) ||
4512 31 : (aNewData.mOpacity >= 0.99f && aNewData.mOpacity < 1.0f && mOpacity == 1.0f)) {
4513 0 : hint |= nsChangeHint_RepaintFrame;
4514 : } else {
4515 23 : hint |= nsChangeHint_UpdateOpacityLayer;
4516 23 : if ((mOpacity == 1.0f) != (aNewData.mOpacity == 1.0f)) {
4517 21 : hint |= nsChangeHint_UpdateUsesOpacity;
4518 : }
4519 : }
4520 : }
4521 :
4522 295 : if (HasFilters() != aNewData.HasFilters()) {
4523 : // A change from/to being a containing block for position:fixed.
4524 0 : hint |= nsChangeHint_UpdateContainingBlock;
4525 : }
4526 :
4527 295 : if (mFilters != aNewData.mFilters) {
4528 : hint |= nsChangeHint_UpdateEffects |
4529 : nsChangeHint_RepaintFrame |
4530 0 : nsChangeHint_UpdateOverflow;
4531 : }
4532 :
4533 295 : if (mMixBlendMode != aNewData.mMixBlendMode) {
4534 0 : hint |= nsChangeHint_RepaintFrame;
4535 : }
4536 :
4537 567 : if (!hint &&
4538 272 : !mClip.IsEqualEdges(aNewData.mClip)) {
4539 0 : hint |= nsChangeHint_NeutralChange;
4540 : }
4541 :
4542 295 : return hint;
4543 : }
|