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