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