|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 /* |
|
7 * structs that contain the data provided by nsStyleContext, the |
|
8 * internal API for computed style data for an element |
|
9 */ |
|
10 |
|
11 #include "nsStyleStruct.h" |
|
12 #include "nsStyleStructInlines.h" |
|
13 #include "nsStyleConsts.h" |
|
14 #include "nsThemeConstants.h" |
|
15 #include "nsString.h" |
|
16 #include "nsPresContext.h" |
|
17 #include "nsIWidget.h" |
|
18 #include "nsCRTGlue.h" |
|
19 #include "nsCSSProps.h" |
|
20 |
|
21 #include "nsCOMPtr.h" |
|
22 |
|
23 #include "nsBidiUtils.h" |
|
24 #include "nsLayoutUtils.h" |
|
25 |
|
26 #include "imgIRequest.h" |
|
27 #include "imgIContainer.h" |
|
28 |
|
29 #include "mozilla/Likely.h" |
|
30 #include "nsIURI.h" |
|
31 #include "nsIDocument.h" |
|
32 #include <algorithm> |
|
33 |
|
34 static_assert((((1 << nsStyleStructID_Length) - 1) & |
|
35 ~(NS_STYLE_INHERIT_MASK)) == 0, |
|
36 "Not enough bits in NS_STYLE_INHERIT_MASK"); |
|
37 |
|
38 inline bool IsFixedUnit(const nsStyleCoord& aCoord, bool aEnumOK) |
|
39 { |
|
40 return aCoord.ConvertsToLength() || |
|
41 (aEnumOK && aCoord.GetUnit() == eStyleUnit_Enumerated); |
|
42 } |
|
43 |
|
44 static bool EqualURIs(nsIURI *aURI1, nsIURI *aURI2) |
|
45 { |
|
46 bool eq; |
|
47 return aURI1 == aURI2 || // handle null==null, and optimize |
|
48 (aURI1 && aURI2 && |
|
49 NS_SUCCEEDED(aURI1->Equals(aURI2, &eq)) && // not equal on fail |
|
50 eq); |
|
51 } |
|
52 |
|
53 static bool EqualURIs(mozilla::css::URLValue *aURI1, mozilla::css::URLValue *aURI2) |
|
54 { |
|
55 return aURI1 == aURI2 || // handle null==null, and optimize |
|
56 (aURI1 && aURI2 && aURI1->URIEquals(*aURI2)); |
|
57 } |
|
58 |
|
59 static bool EqualImages(imgIRequest *aImage1, imgIRequest* aImage2) |
|
60 { |
|
61 if (aImage1 == aImage2) { |
|
62 return true; |
|
63 } |
|
64 |
|
65 if (!aImage1 || !aImage2) { |
|
66 return false; |
|
67 } |
|
68 |
|
69 nsCOMPtr<nsIURI> uri1, uri2; |
|
70 aImage1->GetURI(getter_AddRefs(uri1)); |
|
71 aImage2->GetURI(getter_AddRefs(uri2)); |
|
72 return EqualURIs(uri1, uri2); |
|
73 } |
|
74 |
|
75 // A nullsafe wrapper for strcmp. We depend on null-safety. |
|
76 static int safe_strcmp(const char16_t* a, const char16_t* b) |
|
77 { |
|
78 if (!a || !b) { |
|
79 return (int)(a - b); |
|
80 } |
|
81 return NS_strcmp(a, b); |
|
82 } |
|
83 |
|
84 static nsChangeHint CalcShadowDifference(nsCSSShadowArray* lhs, |
|
85 nsCSSShadowArray* rhs); |
|
86 |
|
87 // -------------------- |
|
88 // nsStyleFont |
|
89 // |
|
90 nsStyleFont::nsStyleFont(const nsFont& aFont, nsPresContext *aPresContext) |
|
91 : mFont(aFont) |
|
92 , mGenericID(kGenericFont_NONE) |
|
93 , mExplicitLanguage(false) |
|
94 { |
|
95 MOZ_COUNT_CTOR(nsStyleFont); |
|
96 Init(aPresContext); |
|
97 } |
|
98 |
|
99 nsStyleFont::nsStyleFont(const nsStyleFont& aSrc) |
|
100 : mFont(aSrc.mFont) |
|
101 , mSize(aSrc.mSize) |
|
102 , mGenericID(aSrc.mGenericID) |
|
103 , mScriptLevel(aSrc.mScriptLevel) |
|
104 , mMathVariant(aSrc.mMathVariant) |
|
105 , mMathDisplay(aSrc.mMathDisplay) |
|
106 , mExplicitLanguage(aSrc.mExplicitLanguage) |
|
107 , mAllowZoom(aSrc.mAllowZoom) |
|
108 , mScriptUnconstrainedSize(aSrc.mScriptUnconstrainedSize) |
|
109 , mScriptMinSize(aSrc.mScriptMinSize) |
|
110 , mScriptSizeMultiplier(aSrc.mScriptSizeMultiplier) |
|
111 , mLanguage(aSrc.mLanguage) |
|
112 { |
|
113 MOZ_COUNT_CTOR(nsStyleFont); |
|
114 } |
|
115 |
|
116 nsStyleFont::nsStyleFont(nsPresContext* aPresContext) |
|
117 // passing nullptr to GetDefaultFont make it use the doc language |
|
118 : mFont(*(aPresContext->GetDefaultFont(kPresContext_DefaultVariableFont_ID, |
|
119 nullptr))) |
|
120 , mGenericID(kGenericFont_NONE) |
|
121 , mExplicitLanguage(false) |
|
122 { |
|
123 MOZ_COUNT_CTOR(nsStyleFont); |
|
124 Init(aPresContext); |
|
125 } |
|
126 |
|
127 void |
|
128 nsStyleFont::Init(nsPresContext* aPresContext) |
|
129 { |
|
130 mSize = mFont.size = nsStyleFont::ZoomText(aPresContext, mFont.size); |
|
131 mScriptUnconstrainedSize = mSize; |
|
132 mScriptMinSize = aPresContext->CSSTwipsToAppUnits( |
|
133 NS_POINTS_TO_TWIPS(NS_MATHML_DEFAULT_SCRIPT_MIN_SIZE_PT)); |
|
134 mScriptLevel = 0; |
|
135 mScriptSizeMultiplier = NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER; |
|
136 mMathVariant = NS_MATHML_MATHVARIANT_NONE; |
|
137 mMathDisplay = NS_MATHML_DISPLAYSTYLE_INLINE; |
|
138 mAllowZoom = true; |
|
139 |
|
140 nsAutoString language; |
|
141 aPresContext->Document()->GetContentLanguage(language); |
|
142 language.StripWhitespace(); |
|
143 |
|
144 // Content-Language may be a comma-separated list of language codes, |
|
145 // in which case the HTML5 spec says to treat it as unknown |
|
146 if (!language.IsEmpty() && |
|
147 language.FindChar(char16_t(',')) == kNotFound) { |
|
148 mLanguage = do_GetAtom(language); |
|
149 // NOTE: This does *not* count as an explicit language; in other |
|
150 // words, it doesn't trigger language-specific hyphenation. |
|
151 } else { |
|
152 // we didn't find a (usable) Content-Language, so we fall back |
|
153 // to whatever the presContext guessed from the charset |
|
154 mLanguage = aPresContext->GetLanguageFromCharset(); |
|
155 } |
|
156 } |
|
157 |
|
158 void* |
|
159 nsStyleFont::operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW { |
|
160 void* result = aContext->AllocateFromShell(sz); |
|
161 if (result) |
|
162 memset(result, 0, sz); |
|
163 return result; |
|
164 } |
|
165 |
|
166 void |
|
167 nsStyleFont::Destroy(nsPresContext* aContext) { |
|
168 this->~nsStyleFont(); |
|
169 aContext->FreeToShell(sizeof(nsStyleFont), this); |
|
170 } |
|
171 |
|
172 void |
|
173 nsStyleFont::EnableZoom(nsPresContext* aContext, bool aEnable) |
|
174 { |
|
175 if (mAllowZoom == aEnable) { |
|
176 return; |
|
177 } |
|
178 mAllowZoom = aEnable; |
|
179 if (mAllowZoom) { |
|
180 mSize = nsStyleFont::ZoomText(aContext, mSize); |
|
181 mFont.size = nsStyleFont::ZoomText(aContext, mFont.size); |
|
182 mScriptUnconstrainedSize = |
|
183 nsStyleFont::ZoomText(aContext, mScriptUnconstrainedSize); |
|
184 } else { |
|
185 mSize = nsStyleFont::UnZoomText(aContext, mSize); |
|
186 mFont.size = nsStyleFont::UnZoomText(aContext, mFont.size); |
|
187 mScriptUnconstrainedSize = |
|
188 nsStyleFont::UnZoomText(aContext, mScriptUnconstrainedSize); |
|
189 } |
|
190 } |
|
191 |
|
192 nsChangeHint nsStyleFont::CalcDifference(const nsStyleFont& aOther) const |
|
193 { |
|
194 MOZ_ASSERT(mAllowZoom == aOther.mAllowZoom, |
|
195 "expected mAllowZoom to be the same on both nsStyleFonts"); |
|
196 if (mSize != aOther.mSize || |
|
197 mLanguage != aOther.mLanguage || |
|
198 mExplicitLanguage != aOther.mExplicitLanguage || |
|
199 mMathVariant != aOther.mMathVariant || |
|
200 mMathDisplay != aOther.mMathDisplay) { |
|
201 return NS_STYLE_HINT_REFLOW; |
|
202 } |
|
203 return CalcFontDifference(mFont, aOther.mFont); |
|
204 } |
|
205 |
|
206 /* static */ nscoord |
|
207 nsStyleFont::ZoomText(nsPresContext *aPresContext, nscoord aSize) |
|
208 { |
|
209 return nscoord(float(aSize) * aPresContext->TextZoom()); |
|
210 } |
|
211 |
|
212 /* static */ nscoord |
|
213 nsStyleFont::UnZoomText(nsPresContext *aPresContext, nscoord aSize) |
|
214 { |
|
215 return nscoord(float(aSize) / aPresContext->TextZoom()); |
|
216 } |
|
217 |
|
218 nsChangeHint nsStyleFont::CalcFontDifference(const nsFont& aFont1, const nsFont& aFont2) |
|
219 { |
|
220 if ((aFont1.size == aFont2.size) && |
|
221 (aFont1.sizeAdjust == aFont2.sizeAdjust) && |
|
222 (aFont1.style == aFont2.style) && |
|
223 (aFont1.variant == aFont2.variant) && |
|
224 (aFont1.weight == aFont2.weight) && |
|
225 (aFont1.stretch == aFont2.stretch) && |
|
226 (aFont1.smoothing == aFont2.smoothing) && |
|
227 (aFont1.name == aFont2.name) && |
|
228 (aFont1.kerning == aFont2.kerning) && |
|
229 (aFont1.synthesis == aFont2.synthesis) && |
|
230 (aFont1.variantAlternates == aFont2.variantAlternates) && |
|
231 (aFont1.alternateValues == aFont2.alternateValues) && |
|
232 (aFont1.featureValueLookup == aFont2.featureValueLookup) && |
|
233 (aFont1.variantCaps == aFont2.variantCaps) && |
|
234 (aFont1.variantEastAsian == aFont2.variantEastAsian) && |
|
235 (aFont1.variantLigatures == aFont2.variantLigatures) && |
|
236 (aFont1.variantNumeric == aFont2.variantNumeric) && |
|
237 (aFont1.variantPosition == aFont2.variantPosition) && |
|
238 (aFont1.fontFeatureSettings == aFont2.fontFeatureSettings) && |
|
239 (aFont1.languageOverride == aFont2.languageOverride) && |
|
240 (aFont1.systemFont == aFont2.systemFont)) { |
|
241 if ((aFont1.decorations == aFont2.decorations)) { |
|
242 return NS_STYLE_HINT_NONE; |
|
243 } |
|
244 return NS_STYLE_HINT_VISUAL; |
|
245 } |
|
246 return NS_STYLE_HINT_REFLOW; |
|
247 } |
|
248 |
|
249 static bool IsFixedData(const nsStyleSides& aSides, bool aEnumOK) |
|
250 { |
|
251 NS_FOR_CSS_SIDES(side) { |
|
252 if (!IsFixedUnit(aSides.Get(side), aEnumOK)) |
|
253 return false; |
|
254 } |
|
255 return true; |
|
256 } |
|
257 |
|
258 static nscoord CalcCoord(const nsStyleCoord& aCoord, |
|
259 const nscoord* aEnumTable, |
|
260 int32_t aNumEnums) |
|
261 { |
|
262 if (aCoord.GetUnit() == eStyleUnit_Enumerated) { |
|
263 NS_ABORT_IF_FALSE(aEnumTable, "must have enum table"); |
|
264 int32_t value = aCoord.GetIntValue(); |
|
265 if (0 <= value && value < aNumEnums) { |
|
266 return aEnumTable[aCoord.GetIntValue()]; |
|
267 } |
|
268 NS_NOTREACHED("unexpected enum value"); |
|
269 return 0; |
|
270 } |
|
271 NS_ABORT_IF_FALSE(aCoord.ConvertsToLength(), "unexpected unit"); |
|
272 return nsRuleNode::ComputeCoordPercentCalc(aCoord, 0); |
|
273 } |
|
274 |
|
275 nsStyleMargin::nsStyleMargin() { |
|
276 MOZ_COUNT_CTOR(nsStyleMargin); |
|
277 nsStyleCoord zero(0, nsStyleCoord::CoordConstructor); |
|
278 NS_FOR_CSS_SIDES(side) { |
|
279 mMargin.Set(side, zero); |
|
280 } |
|
281 mHasCachedMargin = false; |
|
282 } |
|
283 |
|
284 nsStyleMargin::nsStyleMargin(const nsStyleMargin& aSrc) { |
|
285 MOZ_COUNT_CTOR(nsStyleMargin); |
|
286 mMargin = aSrc.mMargin; |
|
287 mHasCachedMargin = false; |
|
288 } |
|
289 |
|
290 void* |
|
291 nsStyleMargin::operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW { |
|
292 void* result = aContext->AllocateFromShell(sz); |
|
293 if (result) |
|
294 memset(result, 0, sz); |
|
295 return result; |
|
296 } |
|
297 |
|
298 void |
|
299 nsStyleMargin::Destroy(nsPresContext* aContext) { |
|
300 this->~nsStyleMargin(); |
|
301 aContext->FreeToShell(sizeof(nsStyleMargin), this); |
|
302 } |
|
303 |
|
304 |
|
305 void nsStyleMargin::RecalcData() |
|
306 { |
|
307 if (IsFixedData(mMargin, false)) { |
|
308 NS_FOR_CSS_SIDES(side) { |
|
309 mCachedMargin.Side(side) = CalcCoord(mMargin.Get(side), nullptr, 0); |
|
310 } |
|
311 mHasCachedMargin = true; |
|
312 } |
|
313 else |
|
314 mHasCachedMargin = false; |
|
315 } |
|
316 |
|
317 nsChangeHint nsStyleMargin::CalcDifference(const nsStyleMargin& aOther) const |
|
318 { |
|
319 if (mMargin == aOther.mMargin) { |
|
320 return NS_STYLE_HINT_NONE; |
|
321 } |
|
322 // Margin differences can't affect descendant intrinsic sizes and |
|
323 // don't need to force children to reflow. |
|
324 return NS_CombineHint(nsChangeHint_NeedReflow, |
|
325 nsChangeHint_ClearAncestorIntrinsics); |
|
326 } |
|
327 |
|
328 nsStylePadding::nsStylePadding() { |
|
329 MOZ_COUNT_CTOR(nsStylePadding); |
|
330 nsStyleCoord zero(0, nsStyleCoord::CoordConstructor); |
|
331 NS_FOR_CSS_SIDES(side) { |
|
332 mPadding.Set(side, zero); |
|
333 } |
|
334 mHasCachedPadding = false; |
|
335 } |
|
336 |
|
337 nsStylePadding::nsStylePadding(const nsStylePadding& aSrc) { |
|
338 MOZ_COUNT_CTOR(nsStylePadding); |
|
339 mPadding = aSrc.mPadding; |
|
340 mHasCachedPadding = false; |
|
341 } |
|
342 |
|
343 void* |
|
344 nsStylePadding::operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW { |
|
345 void* result = aContext->AllocateFromShell(sz); |
|
346 if (result) |
|
347 memset(result, 0, sz); |
|
348 return result; |
|
349 } |
|
350 |
|
351 void |
|
352 nsStylePadding::Destroy(nsPresContext* aContext) { |
|
353 this->~nsStylePadding(); |
|
354 aContext->FreeToShell(sizeof(nsStylePadding), this); |
|
355 } |
|
356 |
|
357 void nsStylePadding::RecalcData() |
|
358 { |
|
359 if (IsFixedData(mPadding, false)) { |
|
360 NS_FOR_CSS_SIDES(side) { |
|
361 // Clamp negative calc() to 0. |
|
362 mCachedPadding.Side(side) = |
|
363 std::max(CalcCoord(mPadding.Get(side), nullptr, 0), 0); |
|
364 } |
|
365 mHasCachedPadding = true; |
|
366 } |
|
367 else |
|
368 mHasCachedPadding = false; |
|
369 } |
|
370 |
|
371 nsChangeHint nsStylePadding::CalcDifference(const nsStylePadding& aOther) const |
|
372 { |
|
373 if (mPadding == aOther.mPadding) { |
|
374 return NS_STYLE_HINT_NONE; |
|
375 } |
|
376 // Padding differences can't affect descendant intrinsic sizes, but do need |
|
377 // to force children to reflow so that we can reposition them, since their |
|
378 // offsets are from our frame bounds but our content rect's position within |
|
379 // those bounds is moving. |
|
380 return NS_SubtractHint(NS_STYLE_HINT_REFLOW, |
|
381 nsChangeHint_ClearDescendantIntrinsics); |
|
382 } |
|
383 |
|
384 nsStyleBorder::nsStyleBorder(nsPresContext* aPresContext) |
|
385 : mBorderColors(nullptr), |
|
386 mBoxShadow(nullptr), |
|
387 mBorderImageFill(NS_STYLE_BORDER_IMAGE_SLICE_NOFILL), |
|
388 mBorderImageRepeatH(NS_STYLE_BORDER_IMAGE_REPEAT_STRETCH), |
|
389 mBorderImageRepeatV(NS_STYLE_BORDER_IMAGE_REPEAT_STRETCH), |
|
390 mFloatEdge(NS_STYLE_FLOAT_EDGE_CONTENT), |
|
391 mComputedBorder(0, 0, 0, 0) |
|
392 { |
|
393 MOZ_COUNT_CTOR(nsStyleBorder); |
|
394 |
|
395 NS_FOR_CSS_HALF_CORNERS (corner) { |
|
396 mBorderRadius.Set(corner, nsStyleCoord(0, nsStyleCoord::CoordConstructor)); |
|
397 } |
|
398 |
|
399 nscoord medium = |
|
400 (aPresContext->GetBorderWidthTable())[NS_STYLE_BORDER_WIDTH_MEDIUM]; |
|
401 NS_FOR_CSS_SIDES(side) { |
|
402 mBorderImageSlice.Set(side, nsStyleCoord(1.0f, eStyleUnit_Percent)); |
|
403 mBorderImageWidth.Set(side, nsStyleCoord(1.0f, eStyleUnit_Factor)); |
|
404 mBorderImageOutset.Set(side, nsStyleCoord(0.0f, eStyleUnit_Factor)); |
|
405 |
|
406 mBorder.Side(side) = medium; |
|
407 mBorderStyle[side] = NS_STYLE_BORDER_STYLE_NONE | BORDER_COLOR_FOREGROUND; |
|
408 mBorderColor[side] = NS_RGB(0, 0, 0); |
|
409 } |
|
410 |
|
411 mTwipsPerPixel = aPresContext->DevPixelsToAppUnits(1); |
|
412 } |
|
413 |
|
414 nsBorderColors::~nsBorderColors() |
|
415 { |
|
416 NS_CSS_DELETE_LIST_MEMBER(nsBorderColors, this, mNext); |
|
417 } |
|
418 |
|
419 nsBorderColors* |
|
420 nsBorderColors::Clone(bool aDeep) const |
|
421 { |
|
422 nsBorderColors* result = new nsBorderColors(mColor); |
|
423 if (MOZ_UNLIKELY(!result)) |
|
424 return result; |
|
425 if (aDeep) |
|
426 NS_CSS_CLONE_LIST_MEMBER(nsBorderColors, this, mNext, result, (false)); |
|
427 return result; |
|
428 } |
|
429 |
|
430 nsStyleBorder::nsStyleBorder(const nsStyleBorder& aSrc) |
|
431 : mBorderColors(nullptr), |
|
432 mBoxShadow(aSrc.mBoxShadow), |
|
433 mBorderRadius(aSrc.mBorderRadius), |
|
434 mBorderImageSource(aSrc.mBorderImageSource), |
|
435 mBorderImageSlice(aSrc.mBorderImageSlice), |
|
436 mBorderImageWidth(aSrc.mBorderImageWidth), |
|
437 mBorderImageOutset(aSrc.mBorderImageOutset), |
|
438 mBorderImageFill(aSrc.mBorderImageFill), |
|
439 mBorderImageRepeatH(aSrc.mBorderImageRepeatH), |
|
440 mBorderImageRepeatV(aSrc.mBorderImageRepeatV), |
|
441 mFloatEdge(aSrc.mFloatEdge), |
|
442 mComputedBorder(aSrc.mComputedBorder), |
|
443 mBorder(aSrc.mBorder), |
|
444 mTwipsPerPixel(aSrc.mTwipsPerPixel) |
|
445 { |
|
446 MOZ_COUNT_CTOR(nsStyleBorder); |
|
447 if (aSrc.mBorderColors) { |
|
448 EnsureBorderColors(); |
|
449 for (int32_t i = 0; i < 4; i++) |
|
450 if (aSrc.mBorderColors[i]) |
|
451 mBorderColors[i] = aSrc.mBorderColors[i]->Clone(); |
|
452 else |
|
453 mBorderColors[i] = nullptr; |
|
454 } |
|
455 |
|
456 NS_FOR_CSS_SIDES(side) { |
|
457 mBorderStyle[side] = aSrc.mBorderStyle[side]; |
|
458 mBorderColor[side] = aSrc.mBorderColor[side]; |
|
459 } |
|
460 } |
|
461 |
|
462 nsStyleBorder::~nsStyleBorder() |
|
463 { |
|
464 MOZ_COUNT_DTOR(nsStyleBorder); |
|
465 if (mBorderColors) { |
|
466 for (int32_t i = 0; i < 4; i++) |
|
467 delete mBorderColors[i]; |
|
468 delete [] mBorderColors; |
|
469 } |
|
470 } |
|
471 |
|
472 void* |
|
473 nsStyleBorder::operator new(size_t sz, nsPresContext* aContext) CPP_THROW_NEW { |
|
474 void* result = aContext->AllocateFromShell(sz); |
|
475 if (result) |
|
476 memset(result, 0, sz); |
|
477 return result; |
|
478 } |
|
479 |
|
480 nsMargin |
|
481 nsStyleBorder::GetImageOutset() const |
|
482 { |
|
483 // We don't check whether there is a border-image (which is OK since |
|
484 // the initial values yields 0 outset) so that we don't have to |
|
485 // reflow to update overflow areas when an image loads. |
|
486 nsMargin outset; |
|
487 NS_FOR_CSS_SIDES(s) { |
|
488 nsStyleCoord coord = mBorderImageOutset.Get(s); |
|
489 nscoord value; |
|
490 switch (coord.GetUnit()) { |
|
491 case eStyleUnit_Coord: |
|
492 value = coord.GetCoordValue(); |
|
493 break; |
|
494 case eStyleUnit_Factor: |
|
495 value = coord.GetFactorValue() * mComputedBorder.Side(s); |
|
496 break; |
|
497 default: |
|
498 NS_NOTREACHED("unexpected CSS unit for image outset"); |
|
499 value = 0; |
|
500 break; |
|
501 } |
|
502 outset.Side(s) = value; |
|
503 } |
|
504 return outset; |
|
505 } |
|
506 |
|
507 void |
|
508 nsStyleBorder::Destroy(nsPresContext* aContext) { |
|
509 UntrackImage(aContext); |
|
510 this->~nsStyleBorder(); |
|
511 aContext->FreeToShell(sizeof(nsStyleBorder), this); |
|
512 } |
|
513 |
|
514 nsChangeHint nsStyleBorder::CalcDifference(const nsStyleBorder& aOther) const |
|
515 { |
|
516 nsChangeHint shadowDifference = |
|
517 CalcShadowDifference(mBoxShadow, aOther.mBoxShadow); |
|
518 NS_ABORT_IF_FALSE(shadowDifference == unsigned(NS_STYLE_HINT_REFLOW) || |
|
519 shadowDifference == unsigned(NS_STYLE_HINT_VISUAL) || |
|
520 shadowDifference == unsigned(NS_STYLE_HINT_NONE), |
|
521 "should do more with shadowDifference"); |
|
522 |
|
523 // Note that differences in mBorder don't affect rendering (which should only |
|
524 // use mComputedBorder), so don't need to be tested for here. |
|
525 // XXXbz we should be able to return a more specific change hint for |
|
526 // at least GetComputedBorder() differences... |
|
527 if (mTwipsPerPixel != aOther.mTwipsPerPixel || |
|
528 GetComputedBorder() != aOther.GetComputedBorder() || |
|
529 mFloatEdge != aOther.mFloatEdge || |
|
530 mBorderImageOutset != aOther.mBorderImageOutset || |
|
531 (shadowDifference & nsChangeHint_NeedReflow)) |
|
532 return NS_STYLE_HINT_REFLOW; |
|
533 |
|
534 NS_FOR_CSS_SIDES(ix) { |
|
535 // See the explanation in nsChangeHint.h of |
|
536 // nsChangeHint_BorderStyleNoneChange . |
|
537 // Furthermore, even though we know *this* side is 0 width, just |
|
538 // assume a visual hint for some other change rather than bother |
|
539 // tracking this result through the rest of the function. |
|
540 if (HasVisibleStyle(ix) != aOther.HasVisibleStyle(ix)) { |
|
541 return NS_CombineHint(NS_STYLE_HINT_VISUAL, |
|
542 nsChangeHint_BorderStyleNoneChange); |
|
543 } |
|
544 } |
|
545 |
|
546 // Note that mBorderStyle stores not only the border style but also |
|
547 // color-related flags. Given that we've already done an mComputedBorder |
|
548 // comparison, border-style differences can only lead to a VISUAL hint. So |
|
549 // it's OK to just compare the values directly -- if either the actual |
|
550 // style or the color flags differ we want to repaint. |
|
551 NS_FOR_CSS_SIDES(ix) { |
|
552 if (mBorderStyle[ix] != aOther.mBorderStyle[ix] || |
|
553 mBorderColor[ix] != aOther.mBorderColor[ix]) |
|
554 return NS_STYLE_HINT_VISUAL; |
|
555 } |
|
556 |
|
557 if (mBorderRadius != aOther.mBorderRadius || |
|
558 !mBorderColors != !aOther.mBorderColors) |
|
559 return NS_STYLE_HINT_VISUAL; |
|
560 |
|
561 if (IsBorderImageLoaded() || aOther.IsBorderImageLoaded()) { |
|
562 if (mBorderImageSource != aOther.mBorderImageSource || |
|
563 mBorderImageRepeatH != aOther.mBorderImageRepeatH || |
|
564 mBorderImageRepeatV != aOther.mBorderImageRepeatV || |
|
565 mBorderImageSlice != aOther.mBorderImageSlice || |
|
566 mBorderImageFill != aOther.mBorderImageFill || |
|
567 mBorderImageWidth != aOther.mBorderImageWidth || |
|
568 mBorderImageOutset != aOther.mBorderImageOutset) |
|
569 return NS_STYLE_HINT_VISUAL; |
|
570 } |
|
571 |
|
572 // Note that at this point if mBorderColors is non-null so is |
|
573 // aOther.mBorderColors |
|
574 if (mBorderColors) { |
|
575 NS_FOR_CSS_SIDES(ix) { |
|
576 if (!nsBorderColors::Equal(mBorderColors[ix], |
|
577 aOther.mBorderColors[ix])) |
|
578 return NS_STYLE_HINT_VISUAL; |
|
579 } |
|
580 } |
|
581 |
|
582 return shadowDifference; |
|
583 } |
|
584 |
|
585 nsStyleOutline::nsStyleOutline(nsPresContext* aPresContext) |
|
586 { |
|
587 MOZ_COUNT_CTOR(nsStyleOutline); |
|
588 // spacing values not inherited |
|
589 nsStyleCoord zero(0, nsStyleCoord::CoordConstructor); |
|
590 NS_FOR_CSS_HALF_CORNERS(corner) { |
|
591 mOutlineRadius.Set(corner, zero); |
|
592 } |
|
593 |
|
594 mOutlineOffset = 0; |
|
595 |
|
596 mOutlineWidth = nsStyleCoord(NS_STYLE_BORDER_WIDTH_MEDIUM, eStyleUnit_Enumerated); |
|
597 mOutlineStyle = NS_STYLE_BORDER_STYLE_NONE; |
|
598 mOutlineColor = NS_RGB(0, 0, 0); |
|
599 |
|
600 mHasCachedOutline = false; |
|
601 mTwipsPerPixel = aPresContext->DevPixelsToAppUnits(1); |
|
602 } |
|
603 |
|
604 nsStyleOutline::nsStyleOutline(const nsStyleOutline& aSrc) { |
|
605 MOZ_COUNT_CTOR(nsStyleOutline); |
|
606 memcpy((nsStyleOutline*)this, &aSrc, sizeof(nsStyleOutline)); |
|
607 } |
|
608 |
|
609 void |
|
610 nsStyleOutline::RecalcData(nsPresContext* aContext) |
|
611 { |
|
612 if (NS_STYLE_BORDER_STYLE_NONE == GetOutlineStyle()) { |
|
613 mCachedOutlineWidth = 0; |
|
614 mHasCachedOutline = true; |
|
615 } else if (IsFixedUnit(mOutlineWidth, true)) { |
|
616 // Clamp negative calc() to 0. |
|
617 mCachedOutlineWidth = |
|
618 std::max(CalcCoord(mOutlineWidth, aContext->GetBorderWidthTable(), 3), 0); |
|
619 mCachedOutlineWidth = |
|
620 NS_ROUND_BORDER_TO_PIXELS(mCachedOutlineWidth, mTwipsPerPixel); |
|
621 mHasCachedOutline = true; |
|
622 } |
|
623 else |
|
624 mHasCachedOutline = false; |
|
625 } |
|
626 |
|
627 nsChangeHint nsStyleOutline::CalcDifference(const nsStyleOutline& aOther) const |
|
628 { |
|
629 bool outlineWasVisible = |
|
630 mCachedOutlineWidth > 0 && mOutlineStyle != NS_STYLE_BORDER_STYLE_NONE; |
|
631 bool outlineIsVisible = |
|
632 aOther.mCachedOutlineWidth > 0 && aOther.mOutlineStyle != NS_STYLE_BORDER_STYLE_NONE; |
|
633 if (outlineWasVisible != outlineIsVisible || |
|
634 (outlineIsVisible && (mOutlineOffset != aOther.mOutlineOffset || |
|
635 mOutlineWidth != aOther.mOutlineWidth || |
|
636 mTwipsPerPixel != aOther.mTwipsPerPixel))) { |
|
637 return NS_CombineHint(nsChangeHint_AllReflowHints, |
|
638 nsChangeHint_RepaintFrame); |
|
639 } |
|
640 if ((mOutlineStyle != aOther.mOutlineStyle) || |
|
641 (mOutlineColor != aOther.mOutlineColor) || |
|
642 (mOutlineRadius != aOther.mOutlineRadius)) { |
|
643 return nsChangeHint_RepaintFrame; |
|
644 } |
|
645 return NS_STYLE_HINT_NONE; |
|
646 } |
|
647 |
|
648 // -------------------- |
|
649 // nsStyleList |
|
650 // |
|
651 nsStyleList::nsStyleList() |
|
652 : mListStyleType(NS_STYLE_LIST_STYLE_DISC), |
|
653 mListStylePosition(NS_STYLE_LIST_STYLE_POSITION_OUTSIDE) |
|
654 { |
|
655 MOZ_COUNT_CTOR(nsStyleList); |
|
656 } |
|
657 |
|
658 nsStyleList::~nsStyleList() |
|
659 { |
|
660 MOZ_COUNT_DTOR(nsStyleList); |
|
661 } |
|
662 |
|
663 nsStyleList::nsStyleList(const nsStyleList& aSource) |
|
664 : mListStyleType(aSource.mListStyleType), |
|
665 mListStylePosition(aSource.mListStylePosition), |
|
666 mImageRegion(aSource.mImageRegion) |
|
667 { |
|
668 SetListStyleImage(aSource.GetListStyleImage()); |
|
669 MOZ_COUNT_CTOR(nsStyleList); |
|
670 } |
|
671 |
|
672 nsChangeHint nsStyleList::CalcDifference(const nsStyleList& aOther) const |
|
673 { |
|
674 if (mListStylePosition != aOther.mListStylePosition) |
|
675 return NS_STYLE_HINT_FRAMECHANGE; |
|
676 if (EqualImages(mListStyleImage, aOther.mListStyleImage) && |
|
677 mListStyleType == aOther.mListStyleType) { |
|
678 if (mImageRegion.IsEqualInterior(aOther.mImageRegion)) |
|
679 return NS_STYLE_HINT_NONE; |
|
680 if (mImageRegion.width == aOther.mImageRegion.width && |
|
681 mImageRegion.height == aOther.mImageRegion.height) |
|
682 return NS_STYLE_HINT_VISUAL; |
|
683 } |
|
684 return NS_STYLE_HINT_REFLOW; |
|
685 } |
|
686 |
|
687 // -------------------- |
|
688 // nsStyleXUL |
|
689 // |
|
690 nsStyleXUL::nsStyleXUL() |
|
691 { |
|
692 MOZ_COUNT_CTOR(nsStyleXUL); |
|
693 mBoxAlign = NS_STYLE_BOX_ALIGN_STRETCH; |
|
694 mBoxDirection = NS_STYLE_BOX_DIRECTION_NORMAL; |
|
695 mBoxFlex = 0.0f; |
|
696 mBoxOrient = NS_STYLE_BOX_ORIENT_HORIZONTAL; |
|
697 mBoxPack = NS_STYLE_BOX_PACK_START; |
|
698 mBoxOrdinal = 1; |
|
699 mStretchStack = true; |
|
700 } |
|
701 |
|
702 nsStyleXUL::~nsStyleXUL() |
|
703 { |
|
704 MOZ_COUNT_DTOR(nsStyleXUL); |
|
705 } |
|
706 |
|
707 nsStyleXUL::nsStyleXUL(const nsStyleXUL& aSource) |
|
708 { |
|
709 MOZ_COUNT_CTOR(nsStyleXUL); |
|
710 memcpy((nsStyleXUL*)this, &aSource, sizeof(nsStyleXUL)); |
|
711 } |
|
712 |
|
713 nsChangeHint nsStyleXUL::CalcDifference(const nsStyleXUL& aOther) const |
|
714 { |
|
715 if (mBoxAlign == aOther.mBoxAlign && |
|
716 mBoxDirection == aOther.mBoxDirection && |
|
717 mBoxFlex == aOther.mBoxFlex && |
|
718 mBoxOrient == aOther.mBoxOrient && |
|
719 mBoxPack == aOther.mBoxPack && |
|
720 mBoxOrdinal == aOther.mBoxOrdinal && |
|
721 mStretchStack == aOther.mStretchStack) |
|
722 return NS_STYLE_HINT_NONE; |
|
723 if (mBoxOrdinal != aOther.mBoxOrdinal) |
|
724 return NS_STYLE_HINT_FRAMECHANGE; |
|
725 return NS_STYLE_HINT_REFLOW; |
|
726 } |
|
727 |
|
728 // -------------------- |
|
729 // nsStyleColumn |
|
730 // |
|
731 /* static */ const uint32_t nsStyleColumn::kMaxColumnCount = 1000; |
|
732 |
|
733 nsStyleColumn::nsStyleColumn(nsPresContext* aPresContext) |
|
734 { |
|
735 MOZ_COUNT_CTOR(nsStyleColumn); |
|
736 mColumnCount = NS_STYLE_COLUMN_COUNT_AUTO; |
|
737 mColumnWidth.SetAutoValue(); |
|
738 mColumnGap.SetNormalValue(); |
|
739 mColumnFill = NS_STYLE_COLUMN_FILL_BALANCE; |
|
740 |
|
741 mColumnRuleWidth = (aPresContext->GetBorderWidthTable())[NS_STYLE_BORDER_WIDTH_MEDIUM]; |
|
742 mColumnRuleStyle = NS_STYLE_BORDER_STYLE_NONE; |
|
743 mColumnRuleColor = NS_RGB(0, 0, 0); |
|
744 mColumnRuleColorIsForeground = true; |
|
745 |
|
746 mTwipsPerPixel = aPresContext->AppUnitsPerDevPixel(); |
|
747 } |
|
748 |
|
749 nsStyleColumn::~nsStyleColumn() |
|
750 { |
|
751 MOZ_COUNT_DTOR(nsStyleColumn); |
|
752 } |
|
753 |
|
754 nsStyleColumn::nsStyleColumn(const nsStyleColumn& aSource) |
|
755 { |
|
756 MOZ_COUNT_CTOR(nsStyleColumn); |
|
757 memcpy((nsStyleColumn*)this, &aSource, sizeof(nsStyleColumn)); |
|
758 } |
|
759 |
|
760 nsChangeHint nsStyleColumn::CalcDifference(const nsStyleColumn& aOther) const |
|
761 { |
|
762 if ((mColumnWidth.GetUnit() == eStyleUnit_Auto) |
|
763 != (aOther.mColumnWidth.GetUnit() == eStyleUnit_Auto) || |
|
764 mColumnCount != aOther.mColumnCount) |
|
765 // We force column count changes to do a reframe, because it's tricky to handle |
|
766 // some edge cases where the column count gets smaller and content overflows. |
|
767 // XXX not ideal |
|
768 return NS_STYLE_HINT_FRAMECHANGE; |
|
769 |
|
770 if (mColumnWidth != aOther.mColumnWidth || |
|
771 mColumnGap != aOther.mColumnGap || |
|
772 mColumnFill != aOther.mColumnFill) |
|
773 return NS_STYLE_HINT_REFLOW; |
|
774 |
|
775 if (GetComputedColumnRuleWidth() != aOther.GetComputedColumnRuleWidth() || |
|
776 mColumnRuleStyle != aOther.mColumnRuleStyle || |
|
777 mColumnRuleColor != aOther.mColumnRuleColor || |
|
778 mColumnRuleColorIsForeground != aOther.mColumnRuleColorIsForeground) |
|
779 return NS_STYLE_HINT_VISUAL; |
|
780 |
|
781 return NS_STYLE_HINT_NONE; |
|
782 } |
|
783 |
|
784 // -------------------- |
|
785 // nsStyleSVG |
|
786 // |
|
787 nsStyleSVG::nsStyleSVG() |
|
788 { |
|
789 MOZ_COUNT_CTOR(nsStyleSVG); |
|
790 mFill.mType = eStyleSVGPaintType_Color; |
|
791 mFill.mPaint.mColor = NS_RGB(0,0,0); |
|
792 mFill.mFallbackColor = NS_RGB(0,0,0); |
|
793 mStroke.mType = eStyleSVGPaintType_None; |
|
794 mStroke.mPaint.mColor = NS_RGB(0,0,0); |
|
795 mStroke.mFallbackColor = NS_RGB(0,0,0); |
|
796 mStrokeDasharray = nullptr; |
|
797 |
|
798 mStrokeDashoffset.SetCoordValue(0); |
|
799 mStrokeWidth.SetCoordValue(nsPresContext::CSSPixelsToAppUnits(1)); |
|
800 |
|
801 mFillOpacity = 1.0f; |
|
802 mStrokeMiterlimit = 4.0f; |
|
803 mStrokeOpacity = 1.0f; |
|
804 |
|
805 mStrokeDasharrayLength = 0; |
|
806 mClipRule = NS_STYLE_FILL_RULE_NONZERO; |
|
807 mColorInterpolation = NS_STYLE_COLOR_INTERPOLATION_SRGB; |
|
808 mColorInterpolationFilters = NS_STYLE_COLOR_INTERPOLATION_LINEARRGB; |
|
809 mFillRule = NS_STYLE_FILL_RULE_NONZERO; |
|
810 mImageRendering = NS_STYLE_IMAGE_RENDERING_AUTO; |
|
811 mPaintOrder = NS_STYLE_PAINT_ORDER_NORMAL; |
|
812 mShapeRendering = NS_STYLE_SHAPE_RENDERING_AUTO; |
|
813 mStrokeLinecap = NS_STYLE_STROKE_LINECAP_BUTT; |
|
814 mStrokeLinejoin = NS_STYLE_STROKE_LINEJOIN_MITER; |
|
815 mTextAnchor = NS_STYLE_TEXT_ANCHOR_START; |
|
816 mTextRendering = NS_STYLE_TEXT_RENDERING_AUTO; |
|
817 mFillOpacitySource = eStyleSVGOpacitySource_Normal; |
|
818 mStrokeOpacitySource = eStyleSVGOpacitySource_Normal; |
|
819 mStrokeDasharrayFromObject = false; |
|
820 mStrokeDashoffsetFromObject = false; |
|
821 mStrokeWidthFromObject = false; |
|
822 } |
|
823 |
|
824 nsStyleSVG::~nsStyleSVG() |
|
825 { |
|
826 MOZ_COUNT_DTOR(nsStyleSVG); |
|
827 delete [] mStrokeDasharray; |
|
828 } |
|
829 |
|
830 nsStyleSVG::nsStyleSVG(const nsStyleSVG& aSource) |
|
831 { |
|
832 MOZ_COUNT_CTOR(nsStyleSVG); |
|
833 mFill = aSource.mFill; |
|
834 mStroke = aSource.mStroke; |
|
835 |
|
836 mMarkerEnd = aSource.mMarkerEnd; |
|
837 mMarkerMid = aSource.mMarkerMid; |
|
838 mMarkerStart = aSource.mMarkerStart; |
|
839 |
|
840 mStrokeDasharrayLength = aSource.mStrokeDasharrayLength; |
|
841 if (aSource.mStrokeDasharray) { |
|
842 mStrokeDasharray = new nsStyleCoord[mStrokeDasharrayLength]; |
|
843 if (mStrokeDasharray) |
|
844 memcpy(mStrokeDasharray, |
|
845 aSource.mStrokeDasharray, |
|
846 mStrokeDasharrayLength * sizeof(nsStyleCoord)); |
|
847 else |
|
848 mStrokeDasharrayLength = 0; |
|
849 } else { |
|
850 mStrokeDasharray = nullptr; |
|
851 } |
|
852 |
|
853 mStrokeDashoffset = aSource.mStrokeDashoffset; |
|
854 mStrokeWidth = aSource.mStrokeWidth; |
|
855 |
|
856 mFillOpacity = aSource.mFillOpacity; |
|
857 mStrokeMiterlimit = aSource.mStrokeMiterlimit; |
|
858 mStrokeOpacity = aSource.mStrokeOpacity; |
|
859 |
|
860 mClipRule = aSource.mClipRule; |
|
861 mColorInterpolation = aSource.mColorInterpolation; |
|
862 mColorInterpolationFilters = aSource.mColorInterpolationFilters; |
|
863 mFillRule = aSource.mFillRule; |
|
864 mImageRendering = aSource.mImageRendering; |
|
865 mPaintOrder = aSource.mPaintOrder; |
|
866 mShapeRendering = aSource.mShapeRendering; |
|
867 mStrokeLinecap = aSource.mStrokeLinecap; |
|
868 mStrokeLinejoin = aSource.mStrokeLinejoin; |
|
869 mTextAnchor = aSource.mTextAnchor; |
|
870 mTextRendering = aSource.mTextRendering; |
|
871 mFillOpacitySource = aSource.mFillOpacitySource; |
|
872 mStrokeOpacitySource = aSource.mStrokeOpacitySource; |
|
873 mStrokeDasharrayFromObject = aSource.mStrokeDasharrayFromObject; |
|
874 mStrokeDashoffsetFromObject = aSource.mStrokeDashoffsetFromObject; |
|
875 mStrokeWidthFromObject = aSource.mStrokeWidthFromObject; |
|
876 } |
|
877 |
|
878 static bool PaintURIChanged(const nsStyleSVGPaint& aPaint1, |
|
879 const nsStyleSVGPaint& aPaint2) |
|
880 { |
|
881 if (aPaint1.mType != aPaint2.mType) { |
|
882 return aPaint1.mType == eStyleSVGPaintType_Server || |
|
883 aPaint2.mType == eStyleSVGPaintType_Server; |
|
884 } |
|
885 return aPaint1.mType == eStyleSVGPaintType_Server && |
|
886 !EqualURIs(aPaint1.mPaint.mPaintServer, aPaint2.mPaint.mPaintServer); |
|
887 } |
|
888 |
|
889 nsChangeHint nsStyleSVG::CalcDifference(const nsStyleSVG& aOther) const |
|
890 { |
|
891 nsChangeHint hint = nsChangeHint(0); |
|
892 |
|
893 if (!EqualURIs(mMarkerEnd, aOther.mMarkerEnd) || |
|
894 !EqualURIs(mMarkerMid, aOther.mMarkerMid) || |
|
895 !EqualURIs(mMarkerStart, aOther.mMarkerStart)) { |
|
896 // Markers currently contribute to nsSVGPathGeometryFrame::mRect, |
|
897 // so we need a reflow as well as a repaint. No intrinsic sizes need |
|
898 // to change, so nsChangeHint_NeedReflow is sufficient. |
|
899 NS_UpdateHint(hint, nsChangeHint_UpdateEffects); |
|
900 NS_UpdateHint(hint, nsChangeHint_NeedReflow); |
|
901 NS_UpdateHint(hint, nsChangeHint_NeedDirtyReflow); // XXX remove me: bug 876085 |
|
902 NS_UpdateHint(hint, nsChangeHint_RepaintFrame); |
|
903 return hint; |
|
904 } |
|
905 |
|
906 if (mFill != aOther.mFill || |
|
907 mStroke != aOther.mStroke || |
|
908 mFillOpacity != aOther.mFillOpacity || |
|
909 mStrokeOpacity != aOther.mStrokeOpacity) { |
|
910 NS_UpdateHint(hint, nsChangeHint_RepaintFrame); |
|
911 if (HasStroke() != aOther.HasStroke() || |
|
912 (!HasStroke() && HasFill() != aOther.HasFill())) { |
|
913 // Frame bounds and overflow rects depend on whether we "have" fill or |
|
914 // stroke. Whether we have stroke or not just changed, or else we have no |
|
915 // stroke (in which case whether we have fill or not is significant to frame |
|
916 // bounds) and whether we have fill or not just changed. In either case we |
|
917 // need to reflow so the frame rect is updated. |
|
918 // XXXperf this is a waste on non nsSVGPathGeometryFrames. |
|
919 NS_UpdateHint(hint, nsChangeHint_NeedReflow); |
|
920 NS_UpdateHint(hint, nsChangeHint_NeedDirtyReflow); // XXX remove me: bug 876085 |
|
921 } |
|
922 if (PaintURIChanged(mFill, aOther.mFill) || |
|
923 PaintURIChanged(mStroke, aOther.mStroke)) { |
|
924 NS_UpdateHint(hint, nsChangeHint_UpdateEffects); |
|
925 } |
|
926 } |
|
927 |
|
928 // Stroke currently contributes to nsSVGPathGeometryFrame::mRect, so |
|
929 // we need a reflow here. No intrinsic sizes need to change, so |
|
930 // nsChangeHint_NeedReflow is sufficient. |
|
931 // Note that stroke-dashoffset does not affect nsSVGPathGeometryFrame::mRect. |
|
932 // text-anchor and text-rendering changes also require a reflow since they |
|
933 // change frames' rects. |
|
934 if (mStrokeWidth != aOther.mStrokeWidth || |
|
935 mStrokeMiterlimit != aOther.mStrokeMiterlimit || |
|
936 mStrokeLinecap != aOther.mStrokeLinecap || |
|
937 mStrokeLinejoin != aOther.mStrokeLinejoin || |
|
938 mTextAnchor != aOther.mTextAnchor || |
|
939 mTextRendering != aOther.mTextRendering) { |
|
940 NS_UpdateHint(hint, nsChangeHint_NeedReflow); |
|
941 NS_UpdateHint(hint, nsChangeHint_NeedDirtyReflow); // XXX remove me: bug 876085 |
|
942 NS_UpdateHint(hint, nsChangeHint_RepaintFrame); |
|
943 return hint; |
|
944 } |
|
945 |
|
946 if (hint & nsChangeHint_RepaintFrame) { |
|
947 return hint; // we don't add anything else below |
|
948 } |
|
949 |
|
950 if ( mStrokeDashoffset != aOther.mStrokeDashoffset || |
|
951 mClipRule != aOther.mClipRule || |
|
952 mColorInterpolation != aOther.mColorInterpolation || |
|
953 mColorInterpolationFilters != aOther.mColorInterpolationFilters || |
|
954 mFillRule != aOther.mFillRule || |
|
955 mImageRendering != aOther.mImageRendering || |
|
956 mPaintOrder != aOther.mPaintOrder || |
|
957 mShapeRendering != aOther.mShapeRendering || |
|
958 mStrokeDasharrayLength != aOther.mStrokeDasharrayLength || |
|
959 mFillOpacitySource != aOther.mFillOpacitySource || |
|
960 mStrokeOpacitySource != aOther.mStrokeOpacitySource || |
|
961 mStrokeDasharrayFromObject != aOther.mStrokeDasharrayFromObject || |
|
962 mStrokeDashoffsetFromObject != aOther.mStrokeDashoffsetFromObject || |
|
963 mStrokeWidthFromObject != aOther.mStrokeWidthFromObject) { |
|
964 NS_UpdateHint(hint, nsChangeHint_RepaintFrame); |
|
965 return hint; |
|
966 } |
|
967 |
|
968 // length of stroke dasharrays are the same (tested above) - check entries |
|
969 for (uint32_t i=0; i<mStrokeDasharrayLength; i++) |
|
970 if (mStrokeDasharray[i] != aOther.mStrokeDasharray[i]) { |
|
971 NS_UpdateHint(hint, nsChangeHint_RepaintFrame); |
|
972 return hint; |
|
973 } |
|
974 |
|
975 return hint; |
|
976 } |
|
977 |
|
978 // -------------------- |
|
979 // nsStyleFilter |
|
980 // |
|
981 nsStyleFilter::nsStyleFilter() |
|
982 : mType(NS_STYLE_FILTER_NONE) |
|
983 , mDropShadow(nullptr) |
|
984 { |
|
985 MOZ_COUNT_CTOR(nsStyleFilter); |
|
986 } |
|
987 |
|
988 nsStyleFilter::nsStyleFilter(const nsStyleFilter& aSource) |
|
989 : mType(NS_STYLE_FILTER_NONE) |
|
990 , mDropShadow(nullptr) |
|
991 { |
|
992 MOZ_COUNT_CTOR(nsStyleFilter); |
|
993 if (aSource.mType == NS_STYLE_FILTER_URL) { |
|
994 SetURL(aSource.mURL); |
|
995 } else if (aSource.mType == NS_STYLE_FILTER_DROP_SHADOW) { |
|
996 SetDropShadow(aSource.mDropShadow); |
|
997 } else if (aSource.mType != NS_STYLE_FILTER_NONE) { |
|
998 SetFilterParameter(aSource.mFilterParameter, aSource.mType); |
|
999 } |
|
1000 } |
|
1001 |
|
1002 nsStyleFilter::~nsStyleFilter() |
|
1003 { |
|
1004 ReleaseRef(); |
|
1005 MOZ_COUNT_DTOR(nsStyleFilter); |
|
1006 } |
|
1007 |
|
1008 nsStyleFilter& |
|
1009 nsStyleFilter::operator=(const nsStyleFilter& aOther) |
|
1010 { |
|
1011 if (this == &aOther) |
|
1012 return *this; |
|
1013 |
|
1014 if (aOther.mType == NS_STYLE_FILTER_URL) { |
|
1015 SetURL(aOther.mURL); |
|
1016 } else if (aOther.mType == NS_STYLE_FILTER_DROP_SHADOW) { |
|
1017 SetDropShadow(aOther.mDropShadow); |
|
1018 } else if (aOther.mType != NS_STYLE_FILTER_NONE) { |
|
1019 SetFilterParameter(aOther.mFilterParameter, aOther.mType); |
|
1020 } |
|
1021 return *this; |
|
1022 } |
|
1023 |
|
1024 |
|
1025 bool |
|
1026 nsStyleFilter::operator==(const nsStyleFilter& aOther) const |
|
1027 { |
|
1028 if (mType != aOther.mType) { |
|
1029 return false; |
|
1030 } |
|
1031 |
|
1032 if (mType == NS_STYLE_FILTER_URL) { |
|
1033 return EqualURIs(mURL, aOther.mURL); |
|
1034 } else if (mType == NS_STYLE_FILTER_DROP_SHADOW) { |
|
1035 return *mDropShadow == *aOther.mDropShadow; |
|
1036 } else if (mType != NS_STYLE_FILTER_NONE) { |
|
1037 return mFilterParameter == aOther.mFilterParameter; |
|
1038 } |
|
1039 |
|
1040 return true; |
|
1041 } |
|
1042 |
|
1043 void |
|
1044 nsStyleFilter::ReleaseRef() |
|
1045 { |
|
1046 if (mType == NS_STYLE_FILTER_DROP_SHADOW) { |
|
1047 NS_ASSERTION(mDropShadow, "expected pointer"); |
|
1048 mDropShadow->Release(); |
|
1049 } else if (mType == NS_STYLE_FILTER_URL) { |
|
1050 NS_ASSERTION(mURL, "expected pointer"); |
|
1051 mURL->Release(); |
|
1052 } |
|
1053 } |
|
1054 |
|
1055 void |
|
1056 nsStyleFilter::SetFilterParameter(const nsStyleCoord& aFilterParameter, |
|
1057 int32_t aType) |
|
1058 { |
|
1059 ReleaseRef(); |
|
1060 mFilterParameter = aFilterParameter; |
|
1061 mType = aType; |
|
1062 } |
|
1063 |
|
1064 void |
|
1065 nsStyleFilter::SetURL(nsIURI* aURL) |
|
1066 { |
|
1067 NS_ASSERTION(aURL, "expected pointer"); |
|
1068 ReleaseRef(); |
|
1069 mURL = aURL; |
|
1070 mURL->AddRef(); |
|
1071 mType = NS_STYLE_FILTER_URL; |
|
1072 } |
|
1073 |
|
1074 void |
|
1075 nsStyleFilter::SetDropShadow(nsCSSShadowArray* aDropShadow) |
|
1076 { |
|
1077 NS_ASSERTION(aDropShadow, "expected pointer"); |
|
1078 ReleaseRef(); |
|
1079 mDropShadow = aDropShadow; |
|
1080 mDropShadow->AddRef(); |
|
1081 mType = NS_STYLE_FILTER_DROP_SHADOW; |
|
1082 } |
|
1083 |
|
1084 // -------------------- |
|
1085 // nsStyleSVGReset |
|
1086 // |
|
1087 nsStyleSVGReset::nsStyleSVGReset() |
|
1088 { |
|
1089 MOZ_COUNT_CTOR(nsStyleSVGReset); |
|
1090 mStopColor = NS_RGB(0,0,0); |
|
1091 mFloodColor = NS_RGB(0,0,0); |
|
1092 mLightingColor = NS_RGB(255,255,255); |
|
1093 mClipPath = nullptr; |
|
1094 mMask = nullptr; |
|
1095 mStopOpacity = 1.0f; |
|
1096 mFloodOpacity = 1.0f; |
|
1097 mDominantBaseline = NS_STYLE_DOMINANT_BASELINE_AUTO; |
|
1098 mVectorEffect = NS_STYLE_VECTOR_EFFECT_NONE; |
|
1099 mMaskType = NS_STYLE_MASK_TYPE_LUMINANCE; |
|
1100 } |
|
1101 |
|
1102 nsStyleSVGReset::~nsStyleSVGReset() |
|
1103 { |
|
1104 MOZ_COUNT_DTOR(nsStyleSVGReset); |
|
1105 } |
|
1106 |
|
1107 nsStyleSVGReset::nsStyleSVGReset(const nsStyleSVGReset& aSource) |
|
1108 { |
|
1109 MOZ_COUNT_CTOR(nsStyleSVGReset); |
|
1110 mStopColor = aSource.mStopColor; |
|
1111 mFloodColor = aSource.mFloodColor; |
|
1112 mLightingColor = aSource.mLightingColor; |
|
1113 mClipPath = aSource.mClipPath; |
|
1114 mFilters = aSource.mFilters; |
|
1115 mMask = aSource.mMask; |
|
1116 mStopOpacity = aSource.mStopOpacity; |
|
1117 mFloodOpacity = aSource.mFloodOpacity; |
|
1118 mDominantBaseline = aSource.mDominantBaseline; |
|
1119 mVectorEffect = aSource.mVectorEffect; |
|
1120 mMaskType = aSource.mMaskType; |
|
1121 } |
|
1122 |
|
1123 nsChangeHint nsStyleSVGReset::CalcDifference(const nsStyleSVGReset& aOther) const |
|
1124 { |
|
1125 nsChangeHint hint = nsChangeHint(0); |
|
1126 |
|
1127 bool equalFilters = (mFilters == aOther.mFilters); |
|
1128 |
|
1129 if (!equalFilters) { |
|
1130 NS_UpdateHint(hint, nsChangeHint_UpdateOverflow); |
|
1131 } |
|
1132 |
|
1133 if (!EqualURIs(mClipPath, aOther.mClipPath) || |
|
1134 !EqualURIs(mMask, aOther.mMask) || |
|
1135 !equalFilters) { |
|
1136 NS_UpdateHint(hint, nsChangeHint_UpdateEffects); |
|
1137 NS_UpdateHint(hint, nsChangeHint_RepaintFrame); |
|
1138 } |
|
1139 |
|
1140 if (mDominantBaseline != aOther.mDominantBaseline) { |
|
1141 // XXXjwatt: why NS_STYLE_HINT_REFLOW? Isn't that excessive? |
|
1142 NS_UpdateHint(hint, NS_STYLE_HINT_REFLOW); |
|
1143 } else if (mVectorEffect != aOther.mVectorEffect) { |
|
1144 // Stroke currently affects nsSVGPathGeometryFrame::mRect, and |
|
1145 // vector-effect affect stroke. As a result we need to reflow if |
|
1146 // vector-effect changes in order to have nsSVGPathGeometryFrame:: |
|
1147 // ReflowSVG called to update its mRect. No intrinsic sizes need |
|
1148 // to change so nsChangeHint_NeedReflow is sufficient. |
|
1149 NS_UpdateHint(hint, nsChangeHint_NeedReflow); |
|
1150 NS_UpdateHint(hint, nsChangeHint_NeedDirtyReflow); // XXX remove me: bug 876085 |
|
1151 NS_UpdateHint(hint, nsChangeHint_RepaintFrame); |
|
1152 } else if (mStopColor != aOther.mStopColor || |
|
1153 mFloodColor != aOther.mFloodColor || |
|
1154 mLightingColor != aOther.mLightingColor || |
|
1155 mStopOpacity != aOther.mStopOpacity || |
|
1156 mFloodOpacity != aOther.mFloodOpacity || |
|
1157 mMaskType != aOther.mMaskType) { |
|
1158 NS_UpdateHint(hint, nsChangeHint_RepaintFrame); |
|
1159 } |
|
1160 |
|
1161 return hint; |
|
1162 } |
|
1163 |
|
1164 // nsStyleSVGPaint implementation |
|
1165 nsStyleSVGPaint::~nsStyleSVGPaint() |
|
1166 { |
|
1167 if (mType == eStyleSVGPaintType_Server) { |
|
1168 NS_IF_RELEASE(mPaint.mPaintServer); |
|
1169 } |
|
1170 } |
|
1171 |
|
1172 void |
|
1173 nsStyleSVGPaint::SetType(nsStyleSVGPaintType aType) |
|
1174 { |
|
1175 if (mType == eStyleSVGPaintType_Server) { |
|
1176 this->~nsStyleSVGPaint(); |
|
1177 new (this) nsStyleSVGPaint(); |
|
1178 } |
|
1179 mType = aType; |
|
1180 } |
|
1181 |
|
1182 nsStyleSVGPaint& nsStyleSVGPaint::operator=(const nsStyleSVGPaint& aOther) |
|
1183 { |
|
1184 if (this == &aOther) |
|
1185 return *this; |
|
1186 |
|
1187 SetType(aOther.mType); |
|
1188 |
|
1189 mFallbackColor = aOther.mFallbackColor; |
|
1190 if (mType == eStyleSVGPaintType_Server) { |
|
1191 mPaint.mPaintServer = aOther.mPaint.mPaintServer; |
|
1192 NS_IF_ADDREF(mPaint.mPaintServer); |
|
1193 } else { |
|
1194 mPaint.mColor = aOther.mPaint.mColor; |
|
1195 } |
|
1196 return *this; |
|
1197 } |
|
1198 |
|
1199 bool nsStyleSVGPaint::operator==(const nsStyleSVGPaint& aOther) const |
|
1200 { |
|
1201 if (mType != aOther.mType) |
|
1202 return false; |
|
1203 if (mType == eStyleSVGPaintType_Server) |
|
1204 return EqualURIs(mPaint.mPaintServer, aOther.mPaint.mPaintServer) && |
|
1205 mFallbackColor == aOther.mFallbackColor; |
|
1206 if (mType == eStyleSVGPaintType_Color) |
|
1207 return mPaint.mColor == aOther.mPaint.mColor; |
|
1208 return true; |
|
1209 } |
|
1210 |
|
1211 |
|
1212 // -------------------- |
|
1213 // nsStylePosition |
|
1214 // |
|
1215 nsStylePosition::nsStylePosition(void) |
|
1216 { |
|
1217 MOZ_COUNT_CTOR(nsStylePosition); |
|
1218 // positioning values not inherited |
|
1219 nsStyleCoord autoCoord(eStyleUnit_Auto); |
|
1220 mOffset.SetLeft(autoCoord); |
|
1221 mOffset.SetTop(autoCoord); |
|
1222 mOffset.SetRight(autoCoord); |
|
1223 mOffset.SetBottom(autoCoord); |
|
1224 mWidth.SetAutoValue(); |
|
1225 mMinWidth.SetCoordValue(0); |
|
1226 mMaxWidth.SetNoneValue(); |
|
1227 mHeight.SetAutoValue(); |
|
1228 mMinHeight.SetCoordValue(0); |
|
1229 mMaxHeight.SetNoneValue(); |
|
1230 mFlexBasis.SetAutoValue(); |
|
1231 |
|
1232 // The initial value of grid-auto-columns and grid-auto-rows is 'auto', |
|
1233 // which computes to 'minmax(min-content, max-content)'. |
|
1234 mGridAutoColumnsMin.SetIntValue(NS_STYLE_GRID_TRACK_BREADTH_MIN_CONTENT, |
|
1235 eStyleUnit_Enumerated); |
|
1236 mGridAutoColumnsMax.SetIntValue(NS_STYLE_GRID_TRACK_BREADTH_MAX_CONTENT, |
|
1237 eStyleUnit_Enumerated); |
|
1238 mGridAutoRowsMin.SetIntValue(NS_STYLE_GRID_TRACK_BREADTH_MIN_CONTENT, |
|
1239 eStyleUnit_Enumerated); |
|
1240 mGridAutoRowsMax.SetIntValue(NS_STYLE_GRID_TRACK_BREADTH_MAX_CONTENT, |
|
1241 eStyleUnit_Enumerated); |
|
1242 |
|
1243 mGridAutoFlow = NS_STYLE_GRID_AUTO_FLOW_NONE; |
|
1244 mBoxSizing = NS_STYLE_BOX_SIZING_CONTENT; |
|
1245 mAlignContent = NS_STYLE_ALIGN_CONTENT_STRETCH; |
|
1246 mAlignItems = NS_STYLE_ALIGN_ITEMS_INITIAL_VALUE; |
|
1247 mAlignSelf = NS_STYLE_ALIGN_SELF_AUTO; |
|
1248 mFlexDirection = NS_STYLE_FLEX_DIRECTION_ROW; |
|
1249 mFlexWrap = NS_STYLE_FLEX_WRAP_NOWRAP; |
|
1250 mJustifyContent = NS_STYLE_JUSTIFY_CONTENT_FLEX_START; |
|
1251 mOrder = NS_STYLE_ORDER_INITIAL; |
|
1252 mFlexGrow = 0.0f; |
|
1253 mFlexShrink = 1.0f; |
|
1254 mZIndex.SetAutoValue(); |
|
1255 mGridAutoPositionColumn.SetToInteger(1); |
|
1256 mGridAutoPositionRow.SetToInteger(1); |
|
1257 // Other members get their default constructors |
|
1258 // which initialize them to representations of their respective initial value. |
|
1259 // mGridTemplateAreas: nullptr for 'none' |
|
1260 // mGridTemplate{Rows,Columns}: false and empty arrays for 'none' |
|
1261 // mGrid{Column,Row}{Start,End}: false/0/empty values for 'auto' |
|
1262 } |
|
1263 |
|
1264 nsStylePosition::~nsStylePosition(void) |
|
1265 { |
|
1266 MOZ_COUNT_DTOR(nsStylePosition); |
|
1267 } |
|
1268 |
|
1269 nsStylePosition::nsStylePosition(const nsStylePosition& aSource) |
|
1270 : mGridTemplateColumns(aSource.mGridTemplateColumns) |
|
1271 , mGridTemplateRows(aSource.mGridTemplateRows) |
|
1272 , mGridTemplateAreas(aSource.mGridTemplateAreas) |
|
1273 , mGridAutoPositionColumn(aSource.mGridAutoPositionColumn) |
|
1274 , mGridAutoPositionRow(aSource.mGridAutoPositionRow) |
|
1275 , mGridColumnStart(aSource.mGridColumnStart) |
|
1276 , mGridColumnEnd(aSource.mGridColumnEnd) |
|
1277 , mGridRowStart(aSource.mGridRowStart) |
|
1278 , mGridRowEnd(aSource.mGridRowEnd) |
|
1279 { |
|
1280 MOZ_COUNT_CTOR(nsStylePosition); |
|
1281 // If you add any memcpy'able member vars, |
|
1282 // they should be declared before mGridTemplateColumns. |
|
1283 // If you add any non-memcpy'able member vars, |
|
1284 // they should be declared after mGridTemplateColumns, |
|
1285 // and you should invoke their copy constructor in the init list above |
|
1286 // and update this static-assert to include their "sizeof()" |
|
1287 static_assert(sizeof(nsStylePosition) == |
|
1288 offsetof(nsStylePosition, mGridTemplateColumns) + |
|
1289 sizeof(mGridTemplateColumns) + |
|
1290 sizeof(mGridTemplateRows) + |
|
1291 sizeof(mGridTemplateAreas) + |
|
1292 sizeof(mGridAutoPositionColumn) + |
|
1293 sizeof(mGridAutoPositionRow) + |
|
1294 sizeof(mGridColumnStart) + |
|
1295 sizeof(mGridColumnEnd) + |
|
1296 sizeof(mGridRowStart) + |
|
1297 sizeof(mGridRowEnd), |
|
1298 "Unexpected size or offset in nsStylePosition"); |
|
1299 memcpy((nsStylePosition*) this, |
|
1300 &aSource, |
|
1301 offsetof(nsStylePosition, mGridTemplateColumns)); |
|
1302 } |
|
1303 |
|
1304 static bool |
|
1305 IsAutonessEqual(const nsStyleSides& aSides1, const nsStyleSides& aSides2) |
|
1306 { |
|
1307 NS_FOR_CSS_SIDES(side) { |
|
1308 if ((aSides1.GetUnit(side) == eStyleUnit_Auto) != |
|
1309 (aSides2.GetUnit(side) == eStyleUnit_Auto)) { |
|
1310 return false; |
|
1311 } |
|
1312 } |
|
1313 return true; |
|
1314 } |
|
1315 |
|
1316 nsChangeHint nsStylePosition::CalcDifference(const nsStylePosition& aOther) const |
|
1317 { |
|
1318 nsChangeHint hint = |
|
1319 (mZIndex == aOther.mZIndex) ? NS_STYLE_HINT_NONE : nsChangeHint_RepaintFrame; |
|
1320 |
|
1321 if (mBoxSizing != aOther.mBoxSizing) { |
|
1322 // Can affect both widths and heights; just a bad scene. |
|
1323 return NS_CombineHint(hint, nsChangeHint_AllReflowHints); |
|
1324 } |
|
1325 |
|
1326 // Properties that apply to flex items: |
|
1327 // NOTE: Changes to "order" on a flex item may trigger some repositioning. |
|
1328 // If we're in a multi-line flex container, it also may affect our size |
|
1329 // (and that of our container & siblings) by shuffling items between lines. |
|
1330 if (mAlignSelf != aOther.mAlignSelf || |
|
1331 mFlexBasis != aOther.mFlexBasis || |
|
1332 mFlexGrow != aOther.mFlexGrow || |
|
1333 mFlexShrink != aOther.mFlexShrink || |
|
1334 mOrder != aOther.mOrder) { |
|
1335 return NS_CombineHint(hint, nsChangeHint_AllReflowHints); |
|
1336 } |
|
1337 |
|
1338 // Properties that apply to flex containers: |
|
1339 // - flex-direction can swap a flex container between vertical & horizontal. |
|
1340 // - align-items can change the sizing of a flex container & the positioning |
|
1341 // of its children. |
|
1342 // - flex-wrap changes whether a flex container's children are wrapped, which |
|
1343 // impacts their sizing/positioning and hence impacts the container's size. |
|
1344 if (mAlignItems != aOther.mAlignItems || |
|
1345 mFlexDirection != aOther.mFlexDirection || |
|
1346 mFlexWrap != aOther.mFlexWrap) { |
|
1347 return NS_CombineHint(hint, nsChangeHint_AllReflowHints); |
|
1348 } |
|
1349 |
|
1350 // Properties that apply to grid containers: |
|
1351 // FIXME: only for grid containers |
|
1352 // (ie. 'display: grid' or 'display: inline-grid') |
|
1353 if (mGridTemplateColumns != aOther.mGridTemplateColumns || |
|
1354 mGridTemplateRows != aOther.mGridTemplateRows || |
|
1355 mGridTemplateAreas != aOther.mGridTemplateAreas || |
|
1356 mGridAutoColumnsMin != aOther.mGridAutoColumnsMin || |
|
1357 mGridAutoColumnsMax != aOther.mGridAutoColumnsMax || |
|
1358 mGridAutoRowsMin != aOther.mGridAutoRowsMin || |
|
1359 mGridAutoRowsMax != aOther.mGridAutoRowsMax || |
|
1360 mGridAutoFlow != aOther.mGridAutoFlow) { |
|
1361 return NS_CombineHint(hint, nsChangeHint_AllReflowHints); |
|
1362 } |
|
1363 |
|
1364 // Properties that apply to grid items: |
|
1365 // FIXME: only for grid items |
|
1366 // (ie. parent frame is 'display: grid' or 'display: inline-grid') |
|
1367 if (mGridColumnStart != aOther.mGridColumnStart || |
|
1368 mGridColumnEnd != aOther.mGridColumnEnd || |
|
1369 mGridRowStart != aOther.mGridRowStart || |
|
1370 mGridRowEnd != aOther.mGridRowEnd) { |
|
1371 return NS_CombineHint(hint, nsChangeHint_AllReflowHints); |
|
1372 } |
|
1373 |
|
1374 // Changing justify-content on a flexbox might affect the positioning of its |
|
1375 // children, but it won't affect any sizing. |
|
1376 if (mJustifyContent != aOther.mJustifyContent) { |
|
1377 NS_UpdateHint(hint, nsChangeHint_NeedReflow); |
|
1378 } |
|
1379 |
|
1380 // Properties that apply only to multi-line flex containers: |
|
1381 // 'align-content' can change the positioning & sizing of a multi-line flex |
|
1382 // container's children when there's extra space in the cross axis, but it |
|
1383 // shouldn't affect the container's own sizing. |
|
1384 // |
|
1385 // NOTE: If we get here, we know that mFlexWrap == aOther.mFlexWrap |
|
1386 // (otherwise, we would've returned earlier). So it doesn't matter which one |
|
1387 // of those we check to see if we're multi-line. |
|
1388 if (mFlexWrap != NS_STYLE_FLEX_WRAP_NOWRAP && |
|
1389 mAlignContent != aOther.mAlignContent) { |
|
1390 NS_UpdateHint(hint, nsChangeHint_NeedReflow); |
|
1391 } |
|
1392 |
|
1393 if (mHeight != aOther.mHeight || |
|
1394 mMinHeight != aOther.mMinHeight || |
|
1395 mMaxHeight != aOther.mMaxHeight) { |
|
1396 // Height changes can affect descendant intrinsic sizes due to replaced |
|
1397 // elements with percentage heights in descendants which also have |
|
1398 // percentage heights. And due to our not-so-great computation of mVResize |
|
1399 // in nsHTMLReflowState, they do need to force reflow of the whole subtree. |
|
1400 // XXXbz due to XUL caching heights as well, height changes also need to |
|
1401 // clear ancestor intrinsics! |
|
1402 return NS_CombineHint(hint, nsChangeHint_AllReflowHints); |
|
1403 } |
|
1404 |
|
1405 if (mWidth != aOther.mWidth || |
|
1406 mMinWidth != aOther.mMinWidth || |
|
1407 mMaxWidth != aOther.mMaxWidth) { |
|
1408 // None of our width differences can affect descendant intrinsic |
|
1409 // sizes and none of them need to force children to reflow. |
|
1410 return |
|
1411 NS_CombineHint(hint, |
|
1412 NS_SubtractHint(nsChangeHint_AllReflowHints, |
|
1413 NS_CombineHint(nsChangeHint_ClearDescendantIntrinsics, |
|
1414 nsChangeHint_NeedDirtyReflow))); |
|
1415 } |
|
1416 |
|
1417 // If width and height have not changed, but any of the offsets have changed, |
|
1418 // then return the respective hints so that we would hopefully be able to |
|
1419 // avoid reflowing. |
|
1420 // Note that it is possible that we'll need to reflow when processing |
|
1421 // restyles, but we don't have enough information to make a good decision |
|
1422 // right now. |
|
1423 // Don't try to handle changes between "auto" and non-auto efficiently; |
|
1424 // that's tricky to do and will hardly ever be able to avoid a reflow. |
|
1425 if (mOffset != aOther.mOffset) { |
|
1426 if (IsAutonessEqual(mOffset, aOther.mOffset)) { |
|
1427 NS_UpdateHint(hint, nsChangeHint(nsChangeHint_RecomputePosition | |
|
1428 nsChangeHint_UpdateOverflow)); |
|
1429 } else { |
|
1430 return NS_CombineHint(hint, nsChangeHint_AllReflowHints); |
|
1431 } |
|
1432 } |
|
1433 return hint; |
|
1434 } |
|
1435 |
|
1436 /* static */ bool |
|
1437 nsStylePosition::WidthCoordDependsOnContainer(const nsStyleCoord &aCoord) |
|
1438 { |
|
1439 return aCoord.GetUnit() == eStyleUnit_Auto || |
|
1440 aCoord.HasPercent() || |
|
1441 (aCoord.GetUnit() == eStyleUnit_Enumerated && |
|
1442 (aCoord.GetIntValue() == NS_STYLE_WIDTH_FIT_CONTENT || |
|
1443 aCoord.GetIntValue() == NS_STYLE_WIDTH_AVAILABLE)); |
|
1444 } |
|
1445 |
|
1446 // -------------------- |
|
1447 // nsStyleTable |
|
1448 // |
|
1449 |
|
1450 nsStyleTable::nsStyleTable() |
|
1451 { |
|
1452 MOZ_COUNT_CTOR(nsStyleTable); |
|
1453 // values not inherited |
|
1454 mLayoutStrategy = NS_STYLE_TABLE_LAYOUT_AUTO; |
|
1455 mFrame = NS_STYLE_TABLE_FRAME_NONE; |
|
1456 mRules = NS_STYLE_TABLE_RULES_NONE; |
|
1457 mSpan = 1; |
|
1458 } |
|
1459 |
|
1460 nsStyleTable::~nsStyleTable(void) |
|
1461 { |
|
1462 MOZ_COUNT_DTOR(nsStyleTable); |
|
1463 } |
|
1464 |
|
1465 nsStyleTable::nsStyleTable(const nsStyleTable& aSource) |
|
1466 { |
|
1467 MOZ_COUNT_CTOR(nsStyleTable); |
|
1468 memcpy((nsStyleTable*)this, &aSource, sizeof(nsStyleTable)); |
|
1469 } |
|
1470 |
|
1471 nsChangeHint nsStyleTable::CalcDifference(const nsStyleTable& aOther) const |
|
1472 { |
|
1473 // Changes in mRules may require reframing (if border-collapse stuff changes, for example). |
|
1474 if (mRules != aOther.mRules || mSpan != aOther.mSpan || |
|
1475 mLayoutStrategy != aOther.mLayoutStrategy) |
|
1476 return NS_STYLE_HINT_FRAMECHANGE; |
|
1477 if (mFrame != aOther.mFrame) |
|
1478 return NS_STYLE_HINT_REFLOW; |
|
1479 return NS_STYLE_HINT_NONE; |
|
1480 } |
|
1481 |
|
1482 // ----------------------- |
|
1483 // nsStyleTableBorder |
|
1484 |
|
1485 nsStyleTableBorder::nsStyleTableBorder(nsPresContext* aPresContext) |
|
1486 { |
|
1487 MOZ_COUNT_CTOR(nsStyleTableBorder); |
|
1488 mBorderCollapse = NS_STYLE_BORDER_SEPARATE; |
|
1489 |
|
1490 nsCompatibility compatMode = eCompatibility_FullStandards; |
|
1491 if (aPresContext) |
|
1492 compatMode = aPresContext->CompatibilityMode(); |
|
1493 mEmptyCells = (compatMode == eCompatibility_NavQuirks) |
|
1494 ? NS_STYLE_TABLE_EMPTY_CELLS_SHOW_BACKGROUND |
|
1495 : NS_STYLE_TABLE_EMPTY_CELLS_SHOW; |
|
1496 mCaptionSide = NS_STYLE_CAPTION_SIDE_TOP; |
|
1497 mBorderSpacingX = 0; |
|
1498 mBorderSpacingY = 0; |
|
1499 } |
|
1500 |
|
1501 nsStyleTableBorder::~nsStyleTableBorder(void) |
|
1502 { |
|
1503 MOZ_COUNT_DTOR(nsStyleTableBorder); |
|
1504 } |
|
1505 |
|
1506 nsStyleTableBorder::nsStyleTableBorder(const nsStyleTableBorder& aSource) |
|
1507 { |
|
1508 MOZ_COUNT_CTOR(nsStyleTableBorder); |
|
1509 memcpy((nsStyleTableBorder*)this, &aSource, sizeof(nsStyleTableBorder)); |
|
1510 } |
|
1511 |
|
1512 nsChangeHint nsStyleTableBorder::CalcDifference(const nsStyleTableBorder& aOther) const |
|
1513 { |
|
1514 // Border-collapse changes need a reframe, because we use a different frame |
|
1515 // class for table cells in the collapsed border model. This is used to |
|
1516 // conserve memory when using the separated border model (collapsed borders |
|
1517 // require extra state to be stored). |
|
1518 if (mBorderCollapse != aOther.mBorderCollapse) { |
|
1519 return NS_STYLE_HINT_FRAMECHANGE; |
|
1520 } |
|
1521 |
|
1522 if ((mCaptionSide == aOther.mCaptionSide) && |
|
1523 (mBorderSpacingX == aOther.mBorderSpacingX) && |
|
1524 (mBorderSpacingY == aOther.mBorderSpacingY)) { |
|
1525 if (mEmptyCells == aOther.mEmptyCells) |
|
1526 return NS_STYLE_HINT_NONE; |
|
1527 return NS_STYLE_HINT_VISUAL; |
|
1528 } |
|
1529 else |
|
1530 return NS_STYLE_HINT_REFLOW; |
|
1531 } |
|
1532 |
|
1533 // -------------------- |
|
1534 // nsStyleColor |
|
1535 // |
|
1536 |
|
1537 nsStyleColor::nsStyleColor(nsPresContext* aPresContext) |
|
1538 { |
|
1539 MOZ_COUNT_CTOR(nsStyleColor); |
|
1540 mColor = aPresContext->DefaultColor(); |
|
1541 } |
|
1542 |
|
1543 nsStyleColor::nsStyleColor(const nsStyleColor& aSource) |
|
1544 { |
|
1545 MOZ_COUNT_CTOR(nsStyleColor); |
|
1546 mColor = aSource.mColor; |
|
1547 } |
|
1548 |
|
1549 nsChangeHint nsStyleColor::CalcDifference(const nsStyleColor& aOther) const |
|
1550 { |
|
1551 if (mColor == aOther.mColor) |
|
1552 return NS_STYLE_HINT_NONE; |
|
1553 return NS_STYLE_HINT_VISUAL; |
|
1554 } |
|
1555 |
|
1556 // -------------------- |
|
1557 // nsStyleGradient |
|
1558 // |
|
1559 bool |
|
1560 nsStyleGradient::operator==(const nsStyleGradient& aOther) const |
|
1561 { |
|
1562 NS_ABORT_IF_FALSE(mSize == NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER || |
|
1563 mShape != NS_STYLE_GRADIENT_SHAPE_LINEAR, |
|
1564 "incorrect combination of shape and size"); |
|
1565 NS_ABORT_IF_FALSE(aOther.mSize == NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER || |
|
1566 aOther.mShape != NS_STYLE_GRADIENT_SHAPE_LINEAR, |
|
1567 "incorrect combination of shape and size"); |
|
1568 |
|
1569 if (mShape != aOther.mShape || |
|
1570 mSize != aOther.mSize || |
|
1571 mRepeating != aOther.mRepeating || |
|
1572 mLegacySyntax != aOther.mLegacySyntax || |
|
1573 mBgPosX != aOther.mBgPosX || |
|
1574 mBgPosY != aOther.mBgPosY || |
|
1575 mAngle != aOther.mAngle || |
|
1576 mRadiusX != aOther.mRadiusX || |
|
1577 mRadiusY != aOther.mRadiusY) |
|
1578 return false; |
|
1579 |
|
1580 if (mStops.Length() != aOther.mStops.Length()) |
|
1581 return false; |
|
1582 |
|
1583 for (uint32_t i = 0; i < mStops.Length(); i++) { |
|
1584 if (mStops[i].mLocation != aOther.mStops[i].mLocation || |
|
1585 mStops[i].mColor != aOther.mStops[i].mColor) |
|
1586 return false; |
|
1587 } |
|
1588 |
|
1589 return true; |
|
1590 } |
|
1591 |
|
1592 nsStyleGradient::nsStyleGradient(void) |
|
1593 : mShape(NS_STYLE_GRADIENT_SHAPE_LINEAR) |
|
1594 , mSize(NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER) |
|
1595 , mRepeating(false) |
|
1596 , mLegacySyntax(false) |
|
1597 { |
|
1598 } |
|
1599 |
|
1600 bool |
|
1601 nsStyleGradient::IsOpaque() |
|
1602 { |
|
1603 for (uint32_t i = 0; i < mStops.Length(); i++) { |
|
1604 if (NS_GET_A(mStops[i].mColor) < 255) |
|
1605 return false; |
|
1606 } |
|
1607 return true; |
|
1608 } |
|
1609 |
|
1610 bool |
|
1611 nsStyleGradient::HasCalc() |
|
1612 { |
|
1613 for (uint32_t i = 0; i < mStops.Length(); i++) { |
|
1614 if (mStops[i].mLocation.IsCalcUnit()) |
|
1615 return true; |
|
1616 } |
|
1617 return mBgPosX.IsCalcUnit() || mBgPosY.IsCalcUnit() || mAngle.IsCalcUnit() || |
|
1618 mRadiusX.IsCalcUnit() || mRadiusY.IsCalcUnit(); |
|
1619 } |
|
1620 |
|
1621 // -------------------- |
|
1622 // nsStyleImage |
|
1623 // |
|
1624 |
|
1625 nsStyleImage::nsStyleImage() |
|
1626 : mType(eStyleImageType_Null) |
|
1627 , mCropRect(nullptr) |
|
1628 #ifdef DEBUG |
|
1629 , mImageTracked(false) |
|
1630 #endif |
|
1631 { |
|
1632 MOZ_COUNT_CTOR(nsStyleImage); |
|
1633 } |
|
1634 |
|
1635 nsStyleImage::~nsStyleImage() |
|
1636 { |
|
1637 MOZ_COUNT_DTOR(nsStyleImage); |
|
1638 if (mType != eStyleImageType_Null) |
|
1639 SetNull(); |
|
1640 } |
|
1641 |
|
1642 nsStyleImage::nsStyleImage(const nsStyleImage& aOther) |
|
1643 : mType(eStyleImageType_Null) |
|
1644 , mCropRect(nullptr) |
|
1645 #ifdef DEBUG |
|
1646 , mImageTracked(false) |
|
1647 #endif |
|
1648 { |
|
1649 // We need our own copy constructor because we don't want |
|
1650 // to copy the reference count |
|
1651 MOZ_COUNT_CTOR(nsStyleImage); |
|
1652 DoCopy(aOther); |
|
1653 } |
|
1654 |
|
1655 nsStyleImage& |
|
1656 nsStyleImage::operator=(const nsStyleImage& aOther) |
|
1657 { |
|
1658 if (this != &aOther) |
|
1659 DoCopy(aOther); |
|
1660 |
|
1661 return *this; |
|
1662 } |
|
1663 |
|
1664 void |
|
1665 nsStyleImage::DoCopy(const nsStyleImage& aOther) |
|
1666 { |
|
1667 SetNull(); |
|
1668 |
|
1669 if (aOther.mType == eStyleImageType_Image) |
|
1670 SetImageData(aOther.mImage); |
|
1671 else if (aOther.mType == eStyleImageType_Gradient) |
|
1672 SetGradientData(aOther.mGradient); |
|
1673 else if (aOther.mType == eStyleImageType_Element) |
|
1674 SetElementId(aOther.mElementId); |
|
1675 |
|
1676 SetCropRect(aOther.mCropRect); |
|
1677 } |
|
1678 |
|
1679 void |
|
1680 nsStyleImage::SetNull() |
|
1681 { |
|
1682 NS_ABORT_IF_FALSE(!mImageTracked, |
|
1683 "Calling SetNull() with image tracked!"); |
|
1684 |
|
1685 if (mType == eStyleImageType_Gradient) |
|
1686 mGradient->Release(); |
|
1687 else if (mType == eStyleImageType_Image) |
|
1688 NS_RELEASE(mImage); |
|
1689 else if (mType == eStyleImageType_Element) |
|
1690 NS_Free(mElementId); |
|
1691 |
|
1692 mType = eStyleImageType_Null; |
|
1693 mCropRect = nullptr; |
|
1694 } |
|
1695 |
|
1696 void |
|
1697 nsStyleImage::SetImageData(imgIRequest* aImage) |
|
1698 { |
|
1699 NS_ABORT_IF_FALSE(!mImageTracked, |
|
1700 "Setting a new image without untracking the old one!"); |
|
1701 |
|
1702 NS_IF_ADDREF(aImage); |
|
1703 |
|
1704 if (mType != eStyleImageType_Null) |
|
1705 SetNull(); |
|
1706 |
|
1707 if (aImage) { |
|
1708 mImage = aImage; |
|
1709 mType = eStyleImageType_Image; |
|
1710 } |
|
1711 mSubImages.Clear(); |
|
1712 } |
|
1713 |
|
1714 void |
|
1715 nsStyleImage::TrackImage(nsPresContext* aContext) |
|
1716 { |
|
1717 // Sanity |
|
1718 NS_ABORT_IF_FALSE(!mImageTracked, "Already tracking image!"); |
|
1719 NS_ABORT_IF_FALSE(mType == eStyleImageType_Image, |
|
1720 "Can't track image when there isn't one!"); |
|
1721 |
|
1722 // Register the image with the document |
|
1723 nsIDocument* doc = aContext->Document(); |
|
1724 if (doc) |
|
1725 doc->AddImage(mImage); |
|
1726 |
|
1727 // Mark state |
|
1728 #ifdef DEBUG |
|
1729 mImageTracked = true; |
|
1730 #endif |
|
1731 } |
|
1732 |
|
1733 void |
|
1734 nsStyleImage::UntrackImage(nsPresContext* aContext) |
|
1735 { |
|
1736 // Sanity |
|
1737 NS_ABORT_IF_FALSE(mImageTracked, "Image not tracked!"); |
|
1738 NS_ABORT_IF_FALSE(mType == eStyleImageType_Image, |
|
1739 "Can't untrack image when there isn't one!"); |
|
1740 |
|
1741 // Unregister the image with the document |
|
1742 nsIDocument* doc = aContext->Document(); |
|
1743 if (doc) |
|
1744 doc->RemoveImage(mImage, nsIDocument::REQUEST_DISCARD); |
|
1745 |
|
1746 // Mark state |
|
1747 #ifdef DEBUG |
|
1748 mImageTracked = false; |
|
1749 #endif |
|
1750 } |
|
1751 |
|
1752 void |
|
1753 nsStyleImage::SetGradientData(nsStyleGradient* aGradient) |
|
1754 { |
|
1755 if (aGradient) |
|
1756 aGradient->AddRef(); |
|
1757 |
|
1758 if (mType != eStyleImageType_Null) |
|
1759 SetNull(); |
|
1760 |
|
1761 if (aGradient) { |
|
1762 mGradient = aGradient; |
|
1763 mType = eStyleImageType_Gradient; |
|
1764 } |
|
1765 } |
|
1766 |
|
1767 void |
|
1768 nsStyleImage::SetElementId(const char16_t* aElementId) |
|
1769 { |
|
1770 if (mType != eStyleImageType_Null) |
|
1771 SetNull(); |
|
1772 |
|
1773 if (aElementId) { |
|
1774 mElementId = NS_strdup(aElementId); |
|
1775 mType = eStyleImageType_Element; |
|
1776 } |
|
1777 } |
|
1778 |
|
1779 void |
|
1780 nsStyleImage::SetCropRect(nsStyleSides* aCropRect) |
|
1781 { |
|
1782 if (aCropRect) { |
|
1783 mCropRect = new nsStyleSides(*aCropRect); |
|
1784 // There is really not much we can do if 'new' fails |
|
1785 } else { |
|
1786 mCropRect = nullptr; |
|
1787 } |
|
1788 } |
|
1789 |
|
1790 static int32_t |
|
1791 ConvertToPixelCoord(const nsStyleCoord& aCoord, int32_t aPercentScale) |
|
1792 { |
|
1793 double pixelValue; |
|
1794 switch (aCoord.GetUnit()) { |
|
1795 case eStyleUnit_Percent: |
|
1796 pixelValue = aCoord.GetPercentValue() * aPercentScale; |
|
1797 break; |
|
1798 case eStyleUnit_Factor: |
|
1799 pixelValue = aCoord.GetFactorValue(); |
|
1800 break; |
|
1801 default: |
|
1802 NS_NOTREACHED("unexpected unit for image crop rect"); |
|
1803 return 0; |
|
1804 } |
|
1805 NS_ABORT_IF_FALSE(pixelValue >= 0, "we ensured non-negative while parsing"); |
|
1806 pixelValue = std::min(pixelValue, double(INT32_MAX)); // avoid overflow |
|
1807 return NS_lround(pixelValue); |
|
1808 } |
|
1809 |
|
1810 bool |
|
1811 nsStyleImage::ComputeActualCropRect(nsIntRect& aActualCropRect, |
|
1812 bool* aIsEntireImage) const |
|
1813 { |
|
1814 if (mType != eStyleImageType_Image) |
|
1815 return false; |
|
1816 |
|
1817 nsCOMPtr<imgIContainer> imageContainer; |
|
1818 mImage->GetImage(getter_AddRefs(imageContainer)); |
|
1819 if (!imageContainer) |
|
1820 return false; |
|
1821 |
|
1822 nsIntSize imageSize; |
|
1823 imageContainer->GetWidth(&imageSize.width); |
|
1824 imageContainer->GetHeight(&imageSize.height); |
|
1825 if (imageSize.width <= 0 || imageSize.height <= 0) |
|
1826 return false; |
|
1827 |
|
1828 int32_t left = ConvertToPixelCoord(mCropRect->GetLeft(), imageSize.width); |
|
1829 int32_t top = ConvertToPixelCoord(mCropRect->GetTop(), imageSize.height); |
|
1830 int32_t right = ConvertToPixelCoord(mCropRect->GetRight(), imageSize.width); |
|
1831 int32_t bottom = ConvertToPixelCoord(mCropRect->GetBottom(), imageSize.height); |
|
1832 |
|
1833 // IntersectRect() returns an empty rect if we get negative width or height |
|
1834 nsIntRect cropRect(left, top, right - left, bottom - top); |
|
1835 nsIntRect imageRect(nsIntPoint(0, 0), imageSize); |
|
1836 aActualCropRect.IntersectRect(imageRect, cropRect); |
|
1837 |
|
1838 if (aIsEntireImage) |
|
1839 *aIsEntireImage = aActualCropRect.IsEqualInterior(imageRect); |
|
1840 return true; |
|
1841 } |
|
1842 |
|
1843 nsresult |
|
1844 nsStyleImage::StartDecoding() const |
|
1845 { |
|
1846 if ((mType == eStyleImageType_Image) && mImage) |
|
1847 return mImage->StartDecoding(); |
|
1848 return NS_OK; |
|
1849 } |
|
1850 |
|
1851 bool |
|
1852 nsStyleImage::IsOpaque() const |
|
1853 { |
|
1854 if (!IsComplete()) |
|
1855 return false; |
|
1856 |
|
1857 if (mType == eStyleImageType_Gradient) |
|
1858 return mGradient->IsOpaque(); |
|
1859 |
|
1860 if (mType == eStyleImageType_Element) |
|
1861 return false; |
|
1862 |
|
1863 NS_ABORT_IF_FALSE(mType == eStyleImageType_Image, "unexpected image type"); |
|
1864 |
|
1865 nsCOMPtr<imgIContainer> imageContainer; |
|
1866 mImage->GetImage(getter_AddRefs(imageContainer)); |
|
1867 NS_ABORT_IF_FALSE(imageContainer, "IsComplete() said image container is ready"); |
|
1868 |
|
1869 // Check if the crop region of the current image frame is opaque. |
|
1870 if (imageContainer->FrameIsOpaque(imgIContainer::FRAME_CURRENT)) { |
|
1871 if (!mCropRect) |
|
1872 return true; |
|
1873 |
|
1874 // Must make sure if mCropRect contains at least a pixel. |
|
1875 // XXX Is this optimization worth it? Maybe I should just return false. |
|
1876 nsIntRect actualCropRect; |
|
1877 bool rv = ComputeActualCropRect(actualCropRect); |
|
1878 NS_ASSERTION(rv, "ComputeActualCropRect() can not fail here"); |
|
1879 return rv && !actualCropRect.IsEmpty(); |
|
1880 } |
|
1881 |
|
1882 return false; |
|
1883 } |
|
1884 |
|
1885 bool |
|
1886 nsStyleImage::IsComplete() const |
|
1887 { |
|
1888 switch (mType) { |
|
1889 case eStyleImageType_Null: |
|
1890 return false; |
|
1891 case eStyleImageType_Gradient: |
|
1892 case eStyleImageType_Element: |
|
1893 return true; |
|
1894 case eStyleImageType_Image: |
|
1895 { |
|
1896 uint32_t status = imgIRequest::STATUS_ERROR; |
|
1897 return NS_SUCCEEDED(mImage->GetImageStatus(&status)) && |
|
1898 (status & imgIRequest::STATUS_SIZE_AVAILABLE) && |
|
1899 (status & imgIRequest::STATUS_FRAME_COMPLETE); |
|
1900 } |
|
1901 default: |
|
1902 NS_NOTREACHED("unexpected image type"); |
|
1903 return false; |
|
1904 } |
|
1905 } |
|
1906 |
|
1907 bool |
|
1908 nsStyleImage::IsLoaded() const |
|
1909 { |
|
1910 switch (mType) { |
|
1911 case eStyleImageType_Null: |
|
1912 return false; |
|
1913 case eStyleImageType_Gradient: |
|
1914 case eStyleImageType_Element: |
|
1915 return true; |
|
1916 case eStyleImageType_Image: |
|
1917 { |
|
1918 uint32_t status = imgIRequest::STATUS_ERROR; |
|
1919 return NS_SUCCEEDED(mImage->GetImageStatus(&status)) && |
|
1920 !(status & imgIRequest::STATUS_ERROR) && |
|
1921 (status & imgIRequest::STATUS_LOAD_COMPLETE); |
|
1922 } |
|
1923 default: |
|
1924 NS_NOTREACHED("unexpected image type"); |
|
1925 return false; |
|
1926 } |
|
1927 } |
|
1928 |
|
1929 static inline bool |
|
1930 EqualRects(const nsStyleSides* aRect1, const nsStyleSides* aRect2) |
|
1931 { |
|
1932 return aRect1 == aRect2 || /* handles null== null, and optimize */ |
|
1933 (aRect1 && aRect2 && *aRect1 == *aRect2); |
|
1934 } |
|
1935 |
|
1936 bool |
|
1937 nsStyleImage::operator==(const nsStyleImage& aOther) const |
|
1938 { |
|
1939 if (mType != aOther.mType) |
|
1940 return false; |
|
1941 |
|
1942 if (!EqualRects(mCropRect, aOther.mCropRect)) |
|
1943 return false; |
|
1944 |
|
1945 if (mType == eStyleImageType_Image) |
|
1946 return EqualImages(mImage, aOther.mImage); |
|
1947 |
|
1948 if (mType == eStyleImageType_Gradient) |
|
1949 return *mGradient == *aOther.mGradient; |
|
1950 |
|
1951 if (mType == eStyleImageType_Element) |
|
1952 return NS_strcmp(mElementId, aOther.mElementId) == 0; |
|
1953 |
|
1954 return true; |
|
1955 } |
|
1956 |
|
1957 // -------------------- |
|
1958 // nsStyleBackground |
|
1959 // |
|
1960 |
|
1961 nsStyleBackground::nsStyleBackground() |
|
1962 : mAttachmentCount(1) |
|
1963 , mClipCount(1) |
|
1964 , mOriginCount(1) |
|
1965 , mRepeatCount(1) |
|
1966 , mPositionCount(1) |
|
1967 , mImageCount(1) |
|
1968 , mSizeCount(1) |
|
1969 , mBlendModeCount(1) |
|
1970 , mBackgroundColor(NS_RGBA(0, 0, 0, 0)) |
|
1971 , mBackgroundInlinePolicy(NS_STYLE_BG_INLINE_POLICY_CONTINUOUS) |
|
1972 { |
|
1973 MOZ_COUNT_CTOR(nsStyleBackground); |
|
1974 Layer *onlyLayer = mLayers.AppendElement(); |
|
1975 NS_ASSERTION(onlyLayer, "auto array must have room for 1 element"); |
|
1976 onlyLayer->SetInitialValues(); |
|
1977 } |
|
1978 |
|
1979 nsStyleBackground::nsStyleBackground(const nsStyleBackground& aSource) |
|
1980 : mAttachmentCount(aSource.mAttachmentCount) |
|
1981 , mClipCount(aSource.mClipCount) |
|
1982 , mOriginCount(aSource.mOriginCount) |
|
1983 , mRepeatCount(aSource.mRepeatCount) |
|
1984 , mPositionCount(aSource.mPositionCount) |
|
1985 , mImageCount(aSource.mImageCount) |
|
1986 , mSizeCount(aSource.mSizeCount) |
|
1987 , mBlendModeCount(aSource.mBlendModeCount) |
|
1988 , mLayers(aSource.mLayers) // deep copy |
|
1989 , mBackgroundColor(aSource.mBackgroundColor) |
|
1990 , mBackgroundInlinePolicy(aSource.mBackgroundInlinePolicy) |
|
1991 { |
|
1992 MOZ_COUNT_CTOR(nsStyleBackground); |
|
1993 // If the deep copy of mLayers failed, truncate the counts. |
|
1994 uint32_t count = mLayers.Length(); |
|
1995 if (count != aSource.mLayers.Length()) { |
|
1996 NS_WARNING("truncating counts due to out-of-memory"); |
|
1997 mAttachmentCount = std::max(mAttachmentCount, count); |
|
1998 mClipCount = std::max(mClipCount, count); |
|
1999 mOriginCount = std::max(mOriginCount, count); |
|
2000 mRepeatCount = std::max(mRepeatCount, count); |
|
2001 mPositionCount = std::max(mPositionCount, count); |
|
2002 mImageCount = std::max(mImageCount, count); |
|
2003 mSizeCount = std::max(mSizeCount, count); |
|
2004 mBlendModeCount = std::max(mSizeCount, count); |
|
2005 } |
|
2006 } |
|
2007 |
|
2008 nsStyleBackground::~nsStyleBackground() |
|
2009 { |
|
2010 MOZ_COUNT_DTOR(nsStyleBackground); |
|
2011 } |
|
2012 |
|
2013 void |
|
2014 nsStyleBackground::Destroy(nsPresContext* aContext) |
|
2015 { |
|
2016 // Untrack all the images stored in our layers |
|
2017 for (uint32_t i = 0; i < mImageCount; ++i) |
|
2018 mLayers[i].UntrackImages(aContext); |
|
2019 |
|
2020 this->~nsStyleBackground(); |
|
2021 aContext->FreeToShell(sizeof(nsStyleBackground), this); |
|
2022 } |
|
2023 |
|
2024 nsChangeHint nsStyleBackground::CalcDifference(const nsStyleBackground& aOther) const |
|
2025 { |
|
2026 const nsStyleBackground* moreLayers = |
|
2027 mImageCount > aOther.mImageCount ? this : &aOther; |
|
2028 const nsStyleBackground* lessLayers = |
|
2029 mImageCount > aOther.mImageCount ? &aOther : this; |
|
2030 |
|
2031 bool hasVisualDifference = false; |
|
2032 |
|
2033 NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, moreLayers) { |
|
2034 if (i < lessLayers->mImageCount) { |
|
2035 if (moreLayers->mLayers[i] != lessLayers->mLayers[i]) { |
|
2036 if ((moreLayers->mLayers[i].mImage.GetType() == eStyleImageType_Element) || |
|
2037 (lessLayers->mLayers[i].mImage.GetType() == eStyleImageType_Element)) |
|
2038 return NS_CombineHint(nsChangeHint_UpdateEffects, NS_STYLE_HINT_VISUAL); |
|
2039 hasVisualDifference = true; |
|
2040 } |
|
2041 } else { |
|
2042 if (moreLayers->mLayers[i].mImage.GetType() == eStyleImageType_Element) |
|
2043 return NS_CombineHint(nsChangeHint_UpdateEffects, NS_STYLE_HINT_VISUAL); |
|
2044 hasVisualDifference = true; |
|
2045 } |
|
2046 } |
|
2047 |
|
2048 if (hasVisualDifference || |
|
2049 mBackgroundColor != aOther.mBackgroundColor || |
|
2050 mBackgroundInlinePolicy != aOther.mBackgroundInlinePolicy) |
|
2051 return NS_STYLE_HINT_VISUAL; |
|
2052 |
|
2053 return NS_STYLE_HINT_NONE; |
|
2054 } |
|
2055 |
|
2056 bool nsStyleBackground::HasFixedBackground() const |
|
2057 { |
|
2058 NS_FOR_VISIBLE_BACKGROUND_LAYERS_BACK_TO_FRONT(i, this) { |
|
2059 const Layer &layer = mLayers[i]; |
|
2060 if (layer.mAttachment == NS_STYLE_BG_ATTACHMENT_FIXED && |
|
2061 !layer.mImage.IsEmpty()) { |
|
2062 return true; |
|
2063 } |
|
2064 } |
|
2065 return false; |
|
2066 } |
|
2067 |
|
2068 bool nsStyleBackground::IsTransparent() const |
|
2069 { |
|
2070 return BottomLayer().mImage.IsEmpty() && |
|
2071 mImageCount == 1 && |
|
2072 NS_GET_A(mBackgroundColor) == 0; |
|
2073 } |
|
2074 |
|
2075 void |
|
2076 nsStyleBackground::Position::SetInitialValues() |
|
2077 { |
|
2078 // Initial value is "0% 0%" |
|
2079 mXPosition.mPercent = 0.0f; |
|
2080 mXPosition.mLength = 0; |
|
2081 mXPosition.mHasPercent = true; |
|
2082 mYPosition.mPercent = 0.0f; |
|
2083 mYPosition.mLength = 0; |
|
2084 mYPosition.mHasPercent = true; |
|
2085 } |
|
2086 |
|
2087 bool |
|
2088 nsStyleBackground::Size::DependsOnPositioningAreaSize(const nsStyleImage& aImage) const |
|
2089 { |
|
2090 NS_ABORT_IF_FALSE(aImage.GetType() != eStyleImageType_Null, |
|
2091 "caller should have handled this"); |
|
2092 |
|
2093 // If either dimension contains a non-zero percentage, rendering for that |
|
2094 // dimension straightforwardly depends on frame size. |
|
2095 if ((mWidthType == eLengthPercentage && mWidth.mPercent != 0.0f) || |
|
2096 (mHeightType == eLengthPercentage && mHeight.mPercent != 0.0f)) { |
|
2097 return true; |
|
2098 } |
|
2099 |
|
2100 // So too for contain and cover. |
|
2101 if (mWidthType == eContain || mWidthType == eCover) { |
|
2102 return true; |
|
2103 } |
|
2104 |
|
2105 // If both dimensions are fixed lengths, there's no dependency. |
|
2106 if (mWidthType == eLengthPercentage && mHeightType == eLengthPercentage) { |
|
2107 return false; |
|
2108 } |
|
2109 |
|
2110 NS_ABORT_IF_FALSE((mWidthType == eLengthPercentage && mHeightType == eAuto) || |
|
2111 (mWidthType == eAuto && mHeightType == eLengthPercentage) || |
|
2112 (mWidthType == eAuto && mHeightType == eAuto), |
|
2113 "logic error"); |
|
2114 |
|
2115 nsStyleImageType type = aImage.GetType(); |
|
2116 |
|
2117 // Gradient rendering depends on frame size when auto is involved because |
|
2118 // gradients have no intrinsic ratio or dimensions, and therefore the relevant |
|
2119 // dimension is "treat[ed] as 100%". |
|
2120 if (type == eStyleImageType_Gradient) { |
|
2121 return true; |
|
2122 } |
|
2123 |
|
2124 // XXX Element rendering for auto or fixed length doesn't depend on frame size |
|
2125 // according to the spec. However, we don't implement the spec yet, so |
|
2126 // for now we bail and say element() plus auto affects ultimate size. |
|
2127 if (type == eStyleImageType_Element) { |
|
2128 return true; |
|
2129 } |
|
2130 |
|
2131 if (type == eStyleImageType_Image) { |
|
2132 nsCOMPtr<imgIContainer> imgContainer; |
|
2133 aImage.GetImageData()->GetImage(getter_AddRefs(imgContainer)); |
|
2134 if (imgContainer) { |
|
2135 nsIntSize imageSize; |
|
2136 nsSize imageRatio; |
|
2137 bool hasWidth, hasHeight; |
|
2138 nsLayoutUtils::ComputeSizeForDrawing(imgContainer, imageSize, imageRatio, |
|
2139 hasWidth, hasHeight); |
|
2140 |
|
2141 // If the image has a fixed width and height, rendering never depends on |
|
2142 // the frame size. |
|
2143 if (hasWidth && hasHeight) { |
|
2144 return false; |
|
2145 } |
|
2146 |
|
2147 // If the image has an intrinsic ratio, rendering will depend on frame |
|
2148 // size when background-size is all auto. |
|
2149 if (imageRatio != nsSize(0, 0)) { |
|
2150 return mWidthType == mHeightType; |
|
2151 } |
|
2152 |
|
2153 // Otherwise, rendering depends on frame size when the image dimensions |
|
2154 // and background-size don't complement each other. |
|
2155 return !(hasWidth && mHeightType == eLengthPercentage) && |
|
2156 !(hasHeight && mWidthType == eLengthPercentage); |
|
2157 } |
|
2158 } else { |
|
2159 NS_NOTREACHED("missed an enum value"); |
|
2160 } |
|
2161 |
|
2162 // Passed the gauntlet: no dependency. |
|
2163 return false; |
|
2164 } |
|
2165 |
|
2166 void |
|
2167 nsStyleBackground::Size::SetInitialValues() |
|
2168 { |
|
2169 mWidthType = mHeightType = eAuto; |
|
2170 } |
|
2171 |
|
2172 bool |
|
2173 nsStyleBackground::Size::operator==(const Size& aOther) const |
|
2174 { |
|
2175 NS_ABORT_IF_FALSE(mWidthType < eDimensionType_COUNT, |
|
2176 "bad mWidthType for this"); |
|
2177 NS_ABORT_IF_FALSE(mHeightType < eDimensionType_COUNT, |
|
2178 "bad mHeightType for this"); |
|
2179 NS_ABORT_IF_FALSE(aOther.mWidthType < eDimensionType_COUNT, |
|
2180 "bad mWidthType for aOther"); |
|
2181 NS_ABORT_IF_FALSE(aOther.mHeightType < eDimensionType_COUNT, |
|
2182 "bad mHeightType for aOther"); |
|
2183 |
|
2184 return mWidthType == aOther.mWidthType && |
|
2185 mHeightType == aOther.mHeightType && |
|
2186 (mWidthType != eLengthPercentage || mWidth == aOther.mWidth) && |
|
2187 (mHeightType != eLengthPercentage || mHeight == aOther.mHeight); |
|
2188 } |
|
2189 |
|
2190 void |
|
2191 nsStyleBackground::Repeat::SetInitialValues() |
|
2192 { |
|
2193 mXRepeat = NS_STYLE_BG_REPEAT_REPEAT; |
|
2194 mYRepeat = NS_STYLE_BG_REPEAT_REPEAT; |
|
2195 } |
|
2196 |
|
2197 nsStyleBackground::Layer::Layer() |
|
2198 { |
|
2199 } |
|
2200 |
|
2201 nsStyleBackground::Layer::~Layer() |
|
2202 { |
|
2203 } |
|
2204 |
|
2205 void |
|
2206 nsStyleBackground::Layer::SetInitialValues() |
|
2207 { |
|
2208 mAttachment = NS_STYLE_BG_ATTACHMENT_SCROLL; |
|
2209 mClip = NS_STYLE_BG_CLIP_BORDER; |
|
2210 mOrigin = NS_STYLE_BG_ORIGIN_PADDING; |
|
2211 mRepeat.SetInitialValues(); |
|
2212 mBlendMode = NS_STYLE_BLEND_NORMAL; |
|
2213 mPosition.SetInitialValues(); |
|
2214 mSize.SetInitialValues(); |
|
2215 mImage.SetNull(); |
|
2216 } |
|
2217 |
|
2218 bool |
|
2219 nsStyleBackground::Layer::RenderingMightDependOnPositioningAreaSizeChange() const |
|
2220 { |
|
2221 // Do we even have an image? |
|
2222 if (mImage.IsEmpty()) { |
|
2223 return false; |
|
2224 } |
|
2225 |
|
2226 return mPosition.DependsOnPositioningAreaSize() || |
|
2227 mSize.DependsOnPositioningAreaSize(mImage); |
|
2228 } |
|
2229 |
|
2230 bool |
|
2231 nsStyleBackground::Layer::operator==(const Layer& aOther) const |
|
2232 { |
|
2233 return mAttachment == aOther.mAttachment && |
|
2234 mClip == aOther.mClip && |
|
2235 mOrigin == aOther.mOrigin && |
|
2236 mRepeat == aOther.mRepeat && |
|
2237 mBlendMode == aOther.mBlendMode && |
|
2238 mPosition == aOther.mPosition && |
|
2239 mSize == aOther.mSize && |
|
2240 mImage == aOther.mImage; |
|
2241 } |
|
2242 |
|
2243 // -------------------- |
|
2244 // nsStyleDisplay |
|
2245 // |
|
2246 void nsTimingFunction::AssignFromKeyword(int32_t aTimingFunctionType) |
|
2247 { |
|
2248 switch (aTimingFunctionType) { |
|
2249 case NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_START: |
|
2250 mType = StepStart; |
|
2251 mSteps = 1; |
|
2252 return; |
|
2253 case NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END: |
|
2254 mType = StepEnd; |
|
2255 mSteps = 1; |
|
2256 return; |
|
2257 default: |
|
2258 mType = Function; |
|
2259 break; |
|
2260 } |
|
2261 |
|
2262 static_assert(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE == 0 && |
|
2263 NS_STYLE_TRANSITION_TIMING_FUNCTION_LINEAR == 1 && |
|
2264 NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE_IN == 2 && |
|
2265 NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE_OUT == 3 && |
|
2266 NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE_IN_OUT == 4, |
|
2267 "transition timing function constants not as expected"); |
|
2268 |
|
2269 static const float timingFunctionValues[5][4] = { |
|
2270 { 0.25f, 0.10f, 0.25f, 1.00f }, // ease |
|
2271 { 0.00f, 0.00f, 1.00f, 1.00f }, // linear |
|
2272 { 0.42f, 0.00f, 1.00f, 1.00f }, // ease-in |
|
2273 { 0.00f, 0.00f, 0.58f, 1.00f }, // ease-out |
|
2274 { 0.42f, 0.00f, 0.58f, 1.00f } // ease-in-out |
|
2275 }; |
|
2276 |
|
2277 NS_ABORT_IF_FALSE(0 <= aTimingFunctionType && aTimingFunctionType < 5, |
|
2278 "keyword out of range"); |
|
2279 mFunc.mX1 = timingFunctionValues[aTimingFunctionType][0]; |
|
2280 mFunc.mY1 = timingFunctionValues[aTimingFunctionType][1]; |
|
2281 mFunc.mX2 = timingFunctionValues[aTimingFunctionType][2]; |
|
2282 mFunc.mY2 = timingFunctionValues[aTimingFunctionType][3]; |
|
2283 } |
|
2284 |
|
2285 nsTransition::nsTransition(const nsTransition& aCopy) |
|
2286 : mTimingFunction(aCopy.mTimingFunction) |
|
2287 , mDuration(aCopy.mDuration) |
|
2288 , mDelay(aCopy.mDelay) |
|
2289 , mProperty(aCopy.mProperty) |
|
2290 , mUnknownProperty(aCopy.mUnknownProperty) |
|
2291 { |
|
2292 } |
|
2293 |
|
2294 void nsTransition::SetInitialValues() |
|
2295 { |
|
2296 mTimingFunction = nsTimingFunction(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE); |
|
2297 mDuration = 0.0; |
|
2298 mDelay = 0.0; |
|
2299 mProperty = eCSSPropertyExtra_all_properties; |
|
2300 } |
|
2301 |
|
2302 void nsTransition::SetUnknownProperty(const nsAString& aUnknownProperty) |
|
2303 { |
|
2304 NS_ASSERTION(nsCSSProps::LookupProperty(aUnknownProperty, |
|
2305 nsCSSProps::eEnabledForAllContent) == |
|
2306 eCSSProperty_UNKNOWN, |
|
2307 "should be unknown property"); |
|
2308 mProperty = eCSSProperty_UNKNOWN; |
|
2309 mUnknownProperty = do_GetAtom(aUnknownProperty); |
|
2310 } |
|
2311 |
|
2312 nsAnimation::nsAnimation(const nsAnimation& aCopy) |
|
2313 : mTimingFunction(aCopy.mTimingFunction) |
|
2314 , mDuration(aCopy.mDuration) |
|
2315 , mDelay(aCopy.mDelay) |
|
2316 , mName(aCopy.mName) |
|
2317 , mDirection(aCopy.mDirection) |
|
2318 , mFillMode(aCopy.mFillMode) |
|
2319 , mPlayState(aCopy.mPlayState) |
|
2320 , mIterationCount(aCopy.mIterationCount) |
|
2321 { |
|
2322 } |
|
2323 |
|
2324 void |
|
2325 nsAnimation::SetInitialValues() |
|
2326 { |
|
2327 mTimingFunction = nsTimingFunction(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE); |
|
2328 mDuration = 0.0; |
|
2329 mDelay = 0.0; |
|
2330 mName = EmptyString(); |
|
2331 mDirection = NS_STYLE_ANIMATION_DIRECTION_NORMAL; |
|
2332 mFillMode = NS_STYLE_ANIMATION_FILL_MODE_NONE; |
|
2333 mPlayState = NS_STYLE_ANIMATION_PLAY_STATE_RUNNING; |
|
2334 mIterationCount = 1.0f; |
|
2335 } |
|
2336 |
|
2337 nsStyleDisplay::nsStyleDisplay() |
|
2338 : mWillChangeBitField(0) |
|
2339 { |
|
2340 MOZ_COUNT_CTOR(nsStyleDisplay); |
|
2341 mAppearance = NS_THEME_NONE; |
|
2342 mDisplay = NS_STYLE_DISPLAY_INLINE; |
|
2343 mOriginalDisplay = mDisplay; |
|
2344 mPosition = NS_STYLE_POSITION_STATIC; |
|
2345 mFloats = NS_STYLE_FLOAT_NONE; |
|
2346 mOriginalFloats = mFloats; |
|
2347 mBreakType = NS_STYLE_CLEAR_NONE; |
|
2348 mBreakInside = NS_STYLE_PAGE_BREAK_AUTO; |
|
2349 mBreakBefore = false; |
|
2350 mBreakAfter = false; |
|
2351 mOverflowX = NS_STYLE_OVERFLOW_VISIBLE; |
|
2352 mOverflowY = NS_STYLE_OVERFLOW_VISIBLE; |
|
2353 mOverflowClipBox = NS_STYLE_OVERFLOW_CLIP_BOX_PADDING_BOX; |
|
2354 mResize = NS_STYLE_RESIZE_NONE; |
|
2355 mClipFlags = NS_STYLE_CLIP_AUTO; |
|
2356 mClip.SetRect(0,0,0,0); |
|
2357 mOpacity = 1.0f; |
|
2358 mSpecifiedTransform = nullptr; |
|
2359 mTransformOrigin[0].SetPercentValue(0.5f); // Transform is centered on origin |
|
2360 mTransformOrigin[1].SetPercentValue(0.5f); |
|
2361 mTransformOrigin[2].SetCoordValue(0); |
|
2362 mPerspectiveOrigin[0].SetPercentValue(0.5f); |
|
2363 mPerspectiveOrigin[1].SetPercentValue(0.5f); |
|
2364 mChildPerspective.SetNoneValue(); |
|
2365 mBackfaceVisibility = NS_STYLE_BACKFACE_VISIBILITY_VISIBLE; |
|
2366 mTransformStyle = NS_STYLE_TRANSFORM_STYLE_FLAT; |
|
2367 mOrient = NS_STYLE_ORIENT_AUTO; |
|
2368 mMixBlendMode = NS_STYLE_BLEND_NORMAL; |
|
2369 mTouchAction = NS_STYLE_TOUCH_ACTION_AUTO; |
|
2370 |
|
2371 mTransitions.AppendElement(); |
|
2372 NS_ABORT_IF_FALSE(mTransitions.Length() == 1, |
|
2373 "appending within auto buffer should never fail"); |
|
2374 mTransitions[0].SetInitialValues(); |
|
2375 mTransitionTimingFunctionCount = 1; |
|
2376 mTransitionDurationCount = 1; |
|
2377 mTransitionDelayCount = 1; |
|
2378 mTransitionPropertyCount = 1; |
|
2379 |
|
2380 mAnimations.AppendElement(); |
|
2381 NS_ABORT_IF_FALSE(mAnimations.Length() == 1, |
|
2382 "appending within auto buffer should never fail"); |
|
2383 mAnimations[0].SetInitialValues(); |
|
2384 mAnimationTimingFunctionCount = 1; |
|
2385 mAnimationDurationCount = 1; |
|
2386 mAnimationDelayCount = 1; |
|
2387 mAnimationNameCount = 1; |
|
2388 mAnimationDirectionCount = 1; |
|
2389 mAnimationFillModeCount = 1; |
|
2390 mAnimationPlayStateCount = 1; |
|
2391 mAnimationIterationCountCount = 1; |
|
2392 } |
|
2393 |
|
2394 nsStyleDisplay::nsStyleDisplay(const nsStyleDisplay& aSource) |
|
2395 : mBinding(aSource.mBinding) |
|
2396 , mClip(aSource.mClip) |
|
2397 , mOpacity(aSource.mOpacity) |
|
2398 , mDisplay(aSource.mDisplay) |
|
2399 , mOriginalDisplay(aSource.mOriginalDisplay) |
|
2400 , mAppearance(aSource.mAppearance) |
|
2401 , mPosition(aSource.mPosition) |
|
2402 , mFloats(aSource.mFloats) |
|
2403 , mOriginalFloats(aSource.mOriginalFloats) |
|
2404 , mBreakType(aSource.mBreakType) |
|
2405 , mBreakInside(aSource.mBreakInside) |
|
2406 , mBreakBefore(aSource.mBreakBefore) |
|
2407 , mBreakAfter(aSource.mBreakAfter) |
|
2408 , mOverflowX(aSource.mOverflowX) |
|
2409 , mOverflowY(aSource.mOverflowY) |
|
2410 , mOverflowClipBox(aSource.mOverflowClipBox) |
|
2411 , mResize(aSource.mResize) |
|
2412 , mClipFlags(aSource.mClipFlags) |
|
2413 , mOrient(aSource.mOrient) |
|
2414 , mMixBlendMode(aSource.mMixBlendMode) |
|
2415 , mWillChangeBitField(aSource.mWillChangeBitField) |
|
2416 , mWillChange(aSource.mWillChange) |
|
2417 , mTouchAction(aSource.mTouchAction) |
|
2418 , mBackfaceVisibility(aSource.mBackfaceVisibility) |
|
2419 , mTransformStyle(aSource.mTransformStyle) |
|
2420 , mSpecifiedTransform(aSource.mSpecifiedTransform) |
|
2421 , mChildPerspective(aSource.mChildPerspective) |
|
2422 , mTransitions(aSource.mTransitions) |
|
2423 , mTransitionTimingFunctionCount(aSource.mTransitionTimingFunctionCount) |
|
2424 , mTransitionDurationCount(aSource.mTransitionDurationCount) |
|
2425 , mTransitionDelayCount(aSource.mTransitionDelayCount) |
|
2426 , mTransitionPropertyCount(aSource.mTransitionPropertyCount) |
|
2427 , mAnimations(aSource.mAnimations) |
|
2428 , mAnimationTimingFunctionCount(aSource.mAnimationTimingFunctionCount) |
|
2429 , mAnimationDurationCount(aSource.mAnimationDurationCount) |
|
2430 , mAnimationDelayCount(aSource.mAnimationDelayCount) |
|
2431 , mAnimationNameCount(aSource.mAnimationNameCount) |
|
2432 , mAnimationDirectionCount(aSource.mAnimationDirectionCount) |
|
2433 , mAnimationFillModeCount(aSource.mAnimationFillModeCount) |
|
2434 , mAnimationPlayStateCount(aSource.mAnimationPlayStateCount) |
|
2435 , mAnimationIterationCountCount(aSource.mAnimationIterationCountCount) |
|
2436 { |
|
2437 MOZ_COUNT_CTOR(nsStyleDisplay); |
|
2438 |
|
2439 /* Copy over transform origin. */ |
|
2440 mTransformOrigin[0] = aSource.mTransformOrigin[0]; |
|
2441 mTransformOrigin[1] = aSource.mTransformOrigin[1]; |
|
2442 mTransformOrigin[2] = aSource.mTransformOrigin[2]; |
|
2443 mPerspectiveOrigin[0] = aSource.mPerspectiveOrigin[0]; |
|
2444 mPerspectiveOrigin[1] = aSource.mPerspectiveOrigin[1]; |
|
2445 } |
|
2446 |
|
2447 nsChangeHint nsStyleDisplay::CalcDifference(const nsStyleDisplay& aOther) const |
|
2448 { |
|
2449 nsChangeHint hint = nsChangeHint(0); |
|
2450 |
|
2451 if (!EqualURIs(mBinding, aOther.mBinding) |
|
2452 || mPosition != aOther.mPosition |
|
2453 || mDisplay != aOther.mDisplay |
|
2454 || (mFloats == NS_STYLE_FLOAT_NONE) != (aOther.mFloats == NS_STYLE_FLOAT_NONE) |
|
2455 || mOverflowX != aOther.mOverflowX |
|
2456 || mOverflowY != aOther.mOverflowY |
|
2457 || mResize != aOther.mResize) |
|
2458 NS_UpdateHint(hint, nsChangeHint_ReconstructFrame); |
|
2459 |
|
2460 if ((mAppearance == NS_THEME_TEXTFIELD && |
|
2461 aOther.mAppearance != NS_THEME_TEXTFIELD) || |
|
2462 (mAppearance != NS_THEME_TEXTFIELD && |
|
2463 aOther.mAppearance == NS_THEME_TEXTFIELD)) { |
|
2464 // This is for <input type=number> where we allow authors to specify a |
|
2465 // |-moz-appearance:textfield| to get a control without a spinner. (The |
|
2466 // spinner is present for |-moz-appearance:number-input| but also other |
|
2467 // values such as 'none'.) We need to reframe since we want to use |
|
2468 // nsTextControlFrame instead of nsNumberControlFrame if the author |
|
2469 // specifies 'textfield'. |
|
2470 return nsChangeHint_ReconstructFrame; |
|
2471 } |
|
2472 |
|
2473 if (mFloats != aOther.mFloats) { |
|
2474 // Changing which side we float on doesn't affect descendants directly |
|
2475 NS_UpdateHint(hint, |
|
2476 NS_SubtractHint(nsChangeHint_AllReflowHints, |
|
2477 NS_CombineHint(nsChangeHint_ClearDescendantIntrinsics, |
|
2478 nsChangeHint_NeedDirtyReflow))); |
|
2479 } |
|
2480 |
|
2481 // XXX the following is conservative, for now: changing float breaking shouldn't |
|
2482 // necessarily require a repaint, reflow should suffice. |
|
2483 if (mBreakType != aOther.mBreakType |
|
2484 || mBreakInside != aOther.mBreakInside |
|
2485 || mBreakBefore != aOther.mBreakBefore |
|
2486 || mBreakAfter != aOther.mBreakAfter |
|
2487 || mAppearance != aOther.mAppearance |
|
2488 || mOrient != aOther.mOrient |
|
2489 || mOverflowClipBox != aOther.mOverflowClipBox |
|
2490 || mClipFlags != aOther.mClipFlags || !mClip.IsEqualInterior(aOther.mClip)) |
|
2491 NS_UpdateHint(hint, NS_CombineHint(nsChangeHint_AllReflowHints, |
|
2492 nsChangeHint_RepaintFrame)); |
|
2493 |
|
2494 if (mOpacity != aOther.mOpacity) { |
|
2495 // If we're going from the optimized >=0.99 opacity value to 1.0 or back, then |
|
2496 // repaint the frame because DLBI will not catch the invalidation. Otherwise, |
|
2497 // just update the opacity layer. |
|
2498 if ((mOpacity >= 0.99f && mOpacity < 1.0f && aOther.mOpacity == 1.0f) || |
|
2499 (aOther.mOpacity >= 0.99f && aOther.mOpacity < 1.0f && mOpacity == 1.0f)) { |
|
2500 NS_UpdateHint(hint, nsChangeHint_RepaintFrame); |
|
2501 } else { |
|
2502 NS_UpdateHint(hint, nsChangeHint_UpdateOpacityLayer); |
|
2503 } |
|
2504 } |
|
2505 |
|
2506 /* If we've added or removed the transform property, we need to reconstruct the frame to add |
|
2507 * or remove the view object, and also to handle abs-pos and fixed-pos containers. |
|
2508 */ |
|
2509 if (HasTransformStyle() != aOther.HasTransformStyle()) { |
|
2510 // We do not need to apply nsChangeHint_UpdateTransformLayer since |
|
2511 // nsChangeHint_RepaintFrame will forcibly invalidate the frame area and |
|
2512 // ensure layers are rebuilt (or removed). |
|
2513 NS_UpdateHint(hint, NS_CombineHint(nsChangeHint_AddOrRemoveTransform, |
|
2514 NS_CombineHint(nsChangeHint_UpdateOverflow, |
|
2515 nsChangeHint_RepaintFrame))); |
|
2516 } |
|
2517 else if (HasTransformStyle()) { |
|
2518 /* Otherwise, if we've kept the property lying around and we already had a |
|
2519 * transform, we need to see whether or not we've changed the transform. |
|
2520 * If so, we need to recompute its overflow rect (which probably changed |
|
2521 * if the transform changed) and to redraw within the bounds of that new |
|
2522 * overflow rect. |
|
2523 */ |
|
2524 if (!mSpecifiedTransform != !aOther.mSpecifiedTransform || |
|
2525 (mSpecifiedTransform && |
|
2526 *mSpecifiedTransform != *aOther.mSpecifiedTransform)) { |
|
2527 NS_UpdateHint(hint, NS_CombineHint(nsChangeHint_UpdatePostTransformOverflow, |
|
2528 nsChangeHint_UpdateTransformLayer)); |
|
2529 } |
|
2530 |
|
2531 const nsChangeHint kUpdateOverflowAndRepaintHint = |
|
2532 NS_CombineHint(nsChangeHint_UpdateOverflow, nsChangeHint_RepaintFrame); |
|
2533 for (uint8_t index = 0; index < 3; ++index) |
|
2534 if (mTransformOrigin[index] != aOther.mTransformOrigin[index]) { |
|
2535 NS_UpdateHint(hint, kUpdateOverflowAndRepaintHint); |
|
2536 break; |
|
2537 } |
|
2538 |
|
2539 for (uint8_t index = 0; index < 2; ++index) |
|
2540 if (mPerspectiveOrigin[index] != aOther.mPerspectiveOrigin[index]) { |
|
2541 NS_UpdateHint(hint, kUpdateOverflowAndRepaintHint); |
|
2542 break; |
|
2543 } |
|
2544 |
|
2545 if (mChildPerspective != aOther.mChildPerspective || |
|
2546 mTransformStyle != aOther.mTransformStyle) |
|
2547 NS_UpdateHint(hint, kUpdateOverflowAndRepaintHint); |
|
2548 |
|
2549 if (mBackfaceVisibility != aOther.mBackfaceVisibility) |
|
2550 NS_UpdateHint(hint, nsChangeHint_RepaintFrame); |
|
2551 } |
|
2552 |
|
2553 uint8_t willChangeBitsChanged = |
|
2554 mWillChangeBitField ^ aOther.mWillChangeBitField; |
|
2555 if (willChangeBitsChanged & NS_STYLE_WILL_CHANGE_STACKING_CONTEXT) { |
|
2556 NS_UpdateHint(hint, nsChangeHint_RepaintFrame); |
|
2557 } |
|
2558 if (willChangeBitsChanged & ~uint8_t(NS_STYLE_WILL_CHANGE_STACKING_CONTEXT)) { |
|
2559 // FIXME (Bug 974125): Don't reconstruct the frame |
|
2560 NS_UpdateHint(hint, nsChangeHint_ReconstructFrame); |
|
2561 } |
|
2562 |
|
2563 // Note: Our current behavior for handling changes to the |
|
2564 // transition-duration, transition-delay, and transition-timing-function |
|
2565 // properties is to do nothing. In other words, the transition |
|
2566 // property that matters is what it is when the transition begins, and |
|
2567 // we don't stop a transition later because the transition property |
|
2568 // changed. |
|
2569 // We do handle changes to transition-property, but we don't need to |
|
2570 // bother with anything here, since the transition manager is notified |
|
2571 // of any style context change anyway. |
|
2572 |
|
2573 // Note: Likewise, for animation-*, the animation manager gets |
|
2574 // notified about every new style context constructed, and it uses |
|
2575 // that opportunity to handle dynamic changes appropriately. |
|
2576 |
|
2577 return hint; |
|
2578 } |
|
2579 |
|
2580 // -------------------- |
|
2581 // nsStyleVisibility |
|
2582 // |
|
2583 |
|
2584 nsStyleVisibility::nsStyleVisibility(nsPresContext* aPresContext) |
|
2585 { |
|
2586 MOZ_COUNT_CTOR(nsStyleVisibility); |
|
2587 uint32_t bidiOptions = aPresContext->GetBidi(); |
|
2588 if (GET_BIDI_OPTION_DIRECTION(bidiOptions) == IBMBIDI_TEXTDIRECTION_RTL) |
|
2589 mDirection = NS_STYLE_DIRECTION_RTL; |
|
2590 else |
|
2591 mDirection = NS_STYLE_DIRECTION_LTR; |
|
2592 |
|
2593 mVisible = NS_STYLE_VISIBILITY_VISIBLE; |
|
2594 mPointerEvents = NS_STYLE_POINTER_EVENTS_AUTO; |
|
2595 mWritingMode = NS_STYLE_WRITING_MODE_HORIZONTAL_TB; |
|
2596 } |
|
2597 |
|
2598 nsStyleVisibility::nsStyleVisibility(const nsStyleVisibility& aSource) |
|
2599 { |
|
2600 MOZ_COUNT_CTOR(nsStyleVisibility); |
|
2601 mImageOrientation = aSource.mImageOrientation; |
|
2602 mDirection = aSource.mDirection; |
|
2603 mVisible = aSource.mVisible; |
|
2604 mPointerEvents = aSource.mPointerEvents; |
|
2605 mWritingMode = aSource.mWritingMode; |
|
2606 } |
|
2607 |
|
2608 nsChangeHint nsStyleVisibility::CalcDifference(const nsStyleVisibility& aOther) const |
|
2609 { |
|
2610 nsChangeHint hint = nsChangeHint(0); |
|
2611 |
|
2612 if (mDirection != aOther.mDirection || mWritingMode != aOther.mWritingMode) { |
|
2613 NS_UpdateHint(hint, nsChangeHint_ReconstructFrame); |
|
2614 } else { |
|
2615 if ((mImageOrientation != aOther.mImageOrientation)) { |
|
2616 NS_UpdateHint(hint, nsChangeHint_AllReflowHints); |
|
2617 } |
|
2618 if (mVisible != aOther.mVisible) { |
|
2619 if ((NS_STYLE_VISIBILITY_COLLAPSE == mVisible) || |
|
2620 (NS_STYLE_VISIBILITY_COLLAPSE == aOther.mVisible)) { |
|
2621 NS_UpdateHint(hint, NS_STYLE_HINT_REFLOW); |
|
2622 } else { |
|
2623 NS_UpdateHint(hint, NS_STYLE_HINT_VISUAL); |
|
2624 } |
|
2625 } |
|
2626 if (mPointerEvents != aOther.mPointerEvents) { |
|
2627 // nsSVGPathGeometryFrame's mRect depends on stroke _and_ on the value |
|
2628 // of pointer-events. See nsSVGPathGeometryFrame::ReflowSVG's use of |
|
2629 // GetHitTestFlags. (Only a reflow, no visual change.) |
|
2630 NS_UpdateHint(hint, nsChangeHint_NeedReflow); |
|
2631 NS_UpdateHint(hint, nsChangeHint_NeedDirtyReflow); // XXX remove me: bug 876085 |
|
2632 } |
|
2633 } |
|
2634 return hint; |
|
2635 } |
|
2636 |
|
2637 nsStyleContentData::~nsStyleContentData() |
|
2638 { |
|
2639 NS_ABORT_IF_FALSE(!mImageTracked, |
|
2640 "nsStyleContentData being destroyed while still tracking image!"); |
|
2641 if (mType == eStyleContentType_Image) { |
|
2642 NS_IF_RELEASE(mContent.mImage); |
|
2643 } else if (mType == eStyleContentType_Counter || |
|
2644 mType == eStyleContentType_Counters) { |
|
2645 mContent.mCounters->Release(); |
|
2646 } else if (mContent.mString) { |
|
2647 NS_Free(mContent.mString); |
|
2648 } |
|
2649 } |
|
2650 |
|
2651 nsStyleContentData& nsStyleContentData::operator=(const nsStyleContentData& aOther) |
|
2652 { |
|
2653 if (this == &aOther) |
|
2654 return *this; |
|
2655 this->~nsStyleContentData(); |
|
2656 new (this) nsStyleContentData(); |
|
2657 |
|
2658 mType = aOther.mType; |
|
2659 if (mType == eStyleContentType_Image) { |
|
2660 mContent.mImage = aOther.mContent.mImage; |
|
2661 NS_IF_ADDREF(mContent.mImage); |
|
2662 } else if (mType == eStyleContentType_Counter || |
|
2663 mType == eStyleContentType_Counters) { |
|
2664 mContent.mCounters = aOther.mContent.mCounters; |
|
2665 mContent.mCounters->AddRef(); |
|
2666 } else if (aOther.mContent.mString) { |
|
2667 mContent.mString = NS_strdup(aOther.mContent.mString); |
|
2668 } else { |
|
2669 mContent.mString = nullptr; |
|
2670 } |
|
2671 return *this; |
|
2672 } |
|
2673 |
|
2674 bool nsStyleContentData::operator==(const nsStyleContentData& aOther) const |
|
2675 { |
|
2676 if (mType != aOther.mType) |
|
2677 return false; |
|
2678 if (mType == eStyleContentType_Image) { |
|
2679 if (!mContent.mImage || !aOther.mContent.mImage) |
|
2680 return mContent.mImage == aOther.mContent.mImage; |
|
2681 bool eq; |
|
2682 nsCOMPtr<nsIURI> thisURI, otherURI; |
|
2683 mContent.mImage->GetURI(getter_AddRefs(thisURI)); |
|
2684 aOther.mContent.mImage->GetURI(getter_AddRefs(otherURI)); |
|
2685 return thisURI == otherURI || // handles null==null |
|
2686 (thisURI && otherURI && |
|
2687 NS_SUCCEEDED(thisURI->Equals(otherURI, &eq)) && |
|
2688 eq); |
|
2689 } |
|
2690 if (mType == eStyleContentType_Counter || |
|
2691 mType == eStyleContentType_Counters) |
|
2692 return *mContent.mCounters == *aOther.mContent.mCounters; |
|
2693 return safe_strcmp(mContent.mString, aOther.mContent.mString) == 0; |
|
2694 } |
|
2695 |
|
2696 void |
|
2697 nsStyleContentData::TrackImage(nsPresContext* aContext) |
|
2698 { |
|
2699 // Sanity |
|
2700 NS_ABORT_IF_FALSE(!mImageTracked, "Already tracking image!"); |
|
2701 NS_ABORT_IF_FALSE(mType == eStyleContentType_Image, |
|
2702 "Trying to do image tracking on non-image!"); |
|
2703 NS_ABORT_IF_FALSE(mContent.mImage, |
|
2704 "Can't track image when there isn't one!"); |
|
2705 |
|
2706 // Register the image with the document |
|
2707 nsIDocument* doc = aContext->Document(); |
|
2708 if (doc) |
|
2709 doc->AddImage(mContent.mImage); |
|
2710 |
|
2711 // Mark state |
|
2712 #ifdef DEBUG |
|
2713 mImageTracked = true; |
|
2714 #endif |
|
2715 } |
|
2716 |
|
2717 void |
|
2718 nsStyleContentData::UntrackImage(nsPresContext* aContext) |
|
2719 { |
|
2720 // Sanity |
|
2721 NS_ABORT_IF_FALSE(mImageTracked, "Image not tracked!"); |
|
2722 NS_ABORT_IF_FALSE(mType == eStyleContentType_Image, |
|
2723 "Trying to do image tracking on non-image!"); |
|
2724 NS_ABORT_IF_FALSE(mContent.mImage, |
|
2725 "Can't untrack image when there isn't one!"); |
|
2726 |
|
2727 // Unregister the image with the document |
|
2728 nsIDocument* doc = aContext->Document(); |
|
2729 if (doc) |
|
2730 doc->RemoveImage(mContent.mImage, nsIDocument::REQUEST_DISCARD); |
|
2731 |
|
2732 // Mark state |
|
2733 #ifdef DEBUG |
|
2734 mImageTracked = false; |
|
2735 #endif |
|
2736 } |
|
2737 |
|
2738 |
|
2739 //----------------------- |
|
2740 // nsStyleContent |
|
2741 // |
|
2742 |
|
2743 nsStyleContent::nsStyleContent(void) |
|
2744 : mMarkerOffset(), |
|
2745 mContents(nullptr), |
|
2746 mIncrements(nullptr), |
|
2747 mResets(nullptr), |
|
2748 mContentCount(0), |
|
2749 mIncrementCount(0), |
|
2750 mResetCount(0) |
|
2751 { |
|
2752 MOZ_COUNT_CTOR(nsStyleContent); |
|
2753 mMarkerOffset.SetAutoValue(); |
|
2754 } |
|
2755 |
|
2756 nsStyleContent::~nsStyleContent(void) |
|
2757 { |
|
2758 MOZ_COUNT_DTOR(nsStyleContent); |
|
2759 DELETE_ARRAY_IF(mContents); |
|
2760 DELETE_ARRAY_IF(mIncrements); |
|
2761 DELETE_ARRAY_IF(mResets); |
|
2762 } |
|
2763 |
|
2764 void |
|
2765 nsStyleContent::Destroy(nsPresContext* aContext) |
|
2766 { |
|
2767 // Unregister any images we might have with the document. |
|
2768 for (uint32_t i = 0; i < mContentCount; ++i) { |
|
2769 if ((mContents[i].mType == eStyleContentType_Image) && |
|
2770 mContents[i].mContent.mImage) { |
|
2771 mContents[i].UntrackImage(aContext); |
|
2772 } |
|
2773 } |
|
2774 |
|
2775 this->~nsStyleContent(); |
|
2776 aContext->FreeToShell(sizeof(nsStyleContent), this); |
|
2777 } |
|
2778 |
|
2779 nsStyleContent::nsStyleContent(const nsStyleContent& aSource) |
|
2780 :mMarkerOffset(), |
|
2781 mContents(nullptr), |
|
2782 mIncrements(nullptr), |
|
2783 mResets(nullptr), |
|
2784 mContentCount(0), |
|
2785 mIncrementCount(0), |
|
2786 mResetCount(0) |
|
2787 |
|
2788 { |
|
2789 MOZ_COUNT_CTOR(nsStyleContent); |
|
2790 mMarkerOffset = aSource.mMarkerOffset; |
|
2791 |
|
2792 uint32_t index; |
|
2793 if (NS_SUCCEEDED(AllocateContents(aSource.ContentCount()))) { |
|
2794 for (index = 0; index < mContentCount; index++) { |
|
2795 ContentAt(index) = aSource.ContentAt(index); |
|
2796 } |
|
2797 } |
|
2798 |
|
2799 if (NS_SUCCEEDED(AllocateCounterIncrements(aSource.CounterIncrementCount()))) { |
|
2800 for (index = 0; index < mIncrementCount; index++) { |
|
2801 const nsStyleCounterData *data = aSource.GetCounterIncrementAt(index); |
|
2802 mIncrements[index].mCounter = data->mCounter; |
|
2803 mIncrements[index].mValue = data->mValue; |
|
2804 } |
|
2805 } |
|
2806 |
|
2807 if (NS_SUCCEEDED(AllocateCounterResets(aSource.CounterResetCount()))) { |
|
2808 for (index = 0; index < mResetCount; index++) { |
|
2809 const nsStyleCounterData *data = aSource.GetCounterResetAt(index); |
|
2810 mResets[index].mCounter = data->mCounter; |
|
2811 mResets[index].mValue = data->mValue; |
|
2812 } |
|
2813 } |
|
2814 } |
|
2815 |
|
2816 nsChangeHint nsStyleContent::CalcDifference(const nsStyleContent& aOther) const |
|
2817 { |
|
2818 // In ReResolveStyleContext we assume that if there's no existing |
|
2819 // ::before or ::after and we don't have to restyle children of the |
|
2820 // node then we can't end up with a ::before or ::after due to the |
|
2821 // restyle of the node itself. That's not quite true, but the only |
|
2822 // exception to the above is when the 'content' property of the node |
|
2823 // changes and the pseudo-element inherits the changed value. Since |
|
2824 // the code here triggers a frame change on the node in that case, |
|
2825 // the optimization in ReResolveStyleContext is ok. But if we ever |
|
2826 // change this code to not reconstruct frames on changes to the |
|
2827 // 'content' property, then we will need to revisit the optimization |
|
2828 // in ReResolveStyleContext. |
|
2829 |
|
2830 if (mContentCount != aOther.mContentCount || |
|
2831 mIncrementCount != aOther.mIncrementCount || |
|
2832 mResetCount != aOther.mResetCount) { |
|
2833 return NS_STYLE_HINT_FRAMECHANGE; |
|
2834 } |
|
2835 |
|
2836 uint32_t ix = mContentCount; |
|
2837 while (0 < ix--) { |
|
2838 if (mContents[ix] != aOther.mContents[ix]) { |
|
2839 // Unfortunately we need to reframe here; a simple reflow |
|
2840 // will not pick up different text or different image URLs, |
|
2841 // since we set all that up in the CSSFrameConstructor |
|
2842 return NS_STYLE_HINT_FRAMECHANGE; |
|
2843 } |
|
2844 } |
|
2845 ix = mIncrementCount; |
|
2846 while (0 < ix--) { |
|
2847 if ((mIncrements[ix].mValue != aOther.mIncrements[ix].mValue) || |
|
2848 (mIncrements[ix].mCounter != aOther.mIncrements[ix].mCounter)) { |
|
2849 return NS_STYLE_HINT_FRAMECHANGE; |
|
2850 } |
|
2851 } |
|
2852 ix = mResetCount; |
|
2853 while (0 < ix--) { |
|
2854 if ((mResets[ix].mValue != aOther.mResets[ix].mValue) || |
|
2855 (mResets[ix].mCounter != aOther.mResets[ix].mCounter)) { |
|
2856 return NS_STYLE_HINT_FRAMECHANGE; |
|
2857 } |
|
2858 } |
|
2859 if (mMarkerOffset != aOther.mMarkerOffset) { |
|
2860 return NS_STYLE_HINT_REFLOW; |
|
2861 } |
|
2862 return NS_STYLE_HINT_NONE; |
|
2863 } |
|
2864 |
|
2865 nsresult nsStyleContent::AllocateContents(uint32_t aCount) |
|
2866 { |
|
2867 // We need to run the destructors of the elements of mContents, so we |
|
2868 // delete and reallocate even if aCount == mContentCount. (If |
|
2869 // nsStyleContentData had its members private and managed their |
|
2870 // ownership on setting, we wouldn't need this, but that seems |
|
2871 // unnecessary at this point.) |
|
2872 DELETE_ARRAY_IF(mContents); |
|
2873 if (aCount) { |
|
2874 mContents = new nsStyleContentData[aCount]; |
|
2875 if (! mContents) { |
|
2876 mContentCount = 0; |
|
2877 return NS_ERROR_OUT_OF_MEMORY; |
|
2878 } |
|
2879 } |
|
2880 mContentCount = aCount; |
|
2881 return NS_OK; |
|
2882 } |
|
2883 |
|
2884 // --------------------- |
|
2885 // nsStyleQuotes |
|
2886 // |
|
2887 |
|
2888 nsStyleQuotes::nsStyleQuotes(void) |
|
2889 : mQuotesCount(0), |
|
2890 mQuotes(nullptr) |
|
2891 { |
|
2892 MOZ_COUNT_CTOR(nsStyleQuotes); |
|
2893 SetInitial(); |
|
2894 } |
|
2895 |
|
2896 nsStyleQuotes::~nsStyleQuotes(void) |
|
2897 { |
|
2898 MOZ_COUNT_DTOR(nsStyleQuotes); |
|
2899 DELETE_ARRAY_IF(mQuotes); |
|
2900 } |
|
2901 |
|
2902 nsStyleQuotes::nsStyleQuotes(const nsStyleQuotes& aSource) |
|
2903 : mQuotesCount(0), |
|
2904 mQuotes(nullptr) |
|
2905 { |
|
2906 MOZ_COUNT_CTOR(nsStyleQuotes); |
|
2907 CopyFrom(aSource); |
|
2908 } |
|
2909 |
|
2910 void |
|
2911 nsStyleQuotes::SetInitial() |
|
2912 { |
|
2913 // The initial value for quotes is the en-US typographic convention: |
|
2914 // outermost are LEFT and RIGHT DOUBLE QUOTATION MARK, alternating |
|
2915 // with LEFT and RIGHT SINGLE QUOTATION MARK. |
|
2916 static const char16_t initialQuotes[8] = { |
|
2917 0x201C, 0, 0x201D, 0, 0x2018, 0, 0x2019, 0 |
|
2918 }; |
|
2919 |
|
2920 if (NS_SUCCEEDED(AllocateQuotes(2))) { |
|
2921 SetQuotesAt(0, |
|
2922 nsDependentString(&initialQuotes[0], 1), |
|
2923 nsDependentString(&initialQuotes[2], 1)); |
|
2924 SetQuotesAt(1, |
|
2925 nsDependentString(&initialQuotes[4], 1), |
|
2926 nsDependentString(&initialQuotes[6], 1)); |
|
2927 } |
|
2928 } |
|
2929 |
|
2930 void |
|
2931 nsStyleQuotes::CopyFrom(const nsStyleQuotes& aSource) |
|
2932 { |
|
2933 if (NS_SUCCEEDED(AllocateQuotes(aSource.QuotesCount()))) { |
|
2934 uint32_t count = (mQuotesCount * 2); |
|
2935 for (uint32_t index = 0; index < count; index += 2) { |
|
2936 aSource.GetQuotesAt(index, mQuotes[index], mQuotes[index + 1]); |
|
2937 } |
|
2938 } |
|
2939 } |
|
2940 |
|
2941 nsChangeHint nsStyleQuotes::CalcDifference(const nsStyleQuotes& aOther) const |
|
2942 { |
|
2943 // If the quotes implementation is ever going to change we might not need |
|
2944 // a framechange here and a reflow should be sufficient. See bug 35768. |
|
2945 if (mQuotesCount == aOther.mQuotesCount) { |
|
2946 uint32_t ix = (mQuotesCount * 2); |
|
2947 while (0 < ix--) { |
|
2948 if (mQuotes[ix] != aOther.mQuotes[ix]) { |
|
2949 return NS_STYLE_HINT_FRAMECHANGE; |
|
2950 } |
|
2951 } |
|
2952 |
|
2953 return NS_STYLE_HINT_NONE; |
|
2954 } |
|
2955 return NS_STYLE_HINT_FRAMECHANGE; |
|
2956 } |
|
2957 |
|
2958 // -------------------- |
|
2959 // nsStyleTextReset |
|
2960 // |
|
2961 |
|
2962 nsStyleTextReset::nsStyleTextReset(void) |
|
2963 { |
|
2964 MOZ_COUNT_CTOR(nsStyleTextReset); |
|
2965 mVerticalAlign.SetIntValue(NS_STYLE_VERTICAL_ALIGN_BASELINE, eStyleUnit_Enumerated); |
|
2966 mTextDecorationLine = NS_STYLE_TEXT_DECORATION_LINE_NONE; |
|
2967 mTextDecorationColor = NS_RGB(0,0,0); |
|
2968 mTextDecorationStyle = |
|
2969 NS_STYLE_TEXT_DECORATION_STYLE_SOLID | BORDER_COLOR_FOREGROUND; |
|
2970 mUnicodeBidi = NS_STYLE_UNICODE_BIDI_NORMAL; |
|
2971 } |
|
2972 |
|
2973 nsStyleTextReset::nsStyleTextReset(const nsStyleTextReset& aSource) |
|
2974 { |
|
2975 MOZ_COUNT_CTOR(nsStyleTextReset); |
|
2976 *this = aSource; |
|
2977 } |
|
2978 |
|
2979 nsStyleTextReset::~nsStyleTextReset(void) |
|
2980 { |
|
2981 MOZ_COUNT_DTOR(nsStyleTextReset); |
|
2982 } |
|
2983 |
|
2984 nsChangeHint nsStyleTextReset::CalcDifference(const nsStyleTextReset& aOther) const |
|
2985 { |
|
2986 if (mVerticalAlign == aOther.mVerticalAlign |
|
2987 && mUnicodeBidi == aOther.mUnicodeBidi) { |
|
2988 uint8_t lineStyle = GetDecorationStyle(); |
|
2989 uint8_t otherLineStyle = aOther.GetDecorationStyle(); |
|
2990 if (mTextDecorationLine != aOther.mTextDecorationLine || |
|
2991 lineStyle != otherLineStyle) { |
|
2992 // Reflow for decoration line style changes only to or from double or |
|
2993 // wave because that may cause overflow area changes |
|
2994 if (lineStyle == NS_STYLE_TEXT_DECORATION_STYLE_DOUBLE || |
|
2995 lineStyle == NS_STYLE_TEXT_DECORATION_STYLE_WAVY || |
|
2996 otherLineStyle == NS_STYLE_TEXT_DECORATION_STYLE_DOUBLE || |
|
2997 otherLineStyle == NS_STYLE_TEXT_DECORATION_STYLE_WAVY) { |
|
2998 return NS_STYLE_HINT_REFLOW; |
|
2999 } |
|
3000 // Repaint for other style decoration lines because they must be in |
|
3001 // default overflow rect |
|
3002 return NS_STYLE_HINT_VISUAL; |
|
3003 } |
|
3004 |
|
3005 // Repaint for decoration color changes |
|
3006 nscolor decColor, otherDecColor; |
|
3007 bool isFG, otherIsFG; |
|
3008 GetDecorationColor(decColor, isFG); |
|
3009 aOther.GetDecorationColor(otherDecColor, otherIsFG); |
|
3010 if (isFG != otherIsFG || (!isFG && decColor != otherDecColor)) { |
|
3011 return NS_STYLE_HINT_VISUAL; |
|
3012 } |
|
3013 |
|
3014 if (mTextOverflow != aOther.mTextOverflow) { |
|
3015 return NS_STYLE_HINT_VISUAL; |
|
3016 } |
|
3017 return NS_STYLE_HINT_NONE; |
|
3018 } |
|
3019 return NS_STYLE_HINT_REFLOW; |
|
3020 } |
|
3021 |
|
3022 // Allowed to return one of NS_STYLE_HINT_NONE, NS_STYLE_HINT_REFLOW |
|
3023 // or NS_STYLE_HINT_VISUAL. Currently we just return NONE or REFLOW, though. |
|
3024 // XXXbz can this not return a more specific hint? If that's ever |
|
3025 // changed, nsStyleBorder::CalcDifference will need changing too. |
|
3026 static nsChangeHint |
|
3027 CalcShadowDifference(nsCSSShadowArray* lhs, |
|
3028 nsCSSShadowArray* rhs) |
|
3029 { |
|
3030 if (lhs == rhs) |
|
3031 return NS_STYLE_HINT_NONE; |
|
3032 |
|
3033 if (!lhs || !rhs || lhs->Length() != rhs->Length()) |
|
3034 return NS_STYLE_HINT_REFLOW; |
|
3035 |
|
3036 for (uint32_t i = 0; i < lhs->Length(); ++i) { |
|
3037 if (*lhs->ShadowAt(i) != *rhs->ShadowAt(i)) |
|
3038 return NS_STYLE_HINT_REFLOW; |
|
3039 } |
|
3040 return NS_STYLE_HINT_NONE; |
|
3041 } |
|
3042 |
|
3043 // -------------------- |
|
3044 // nsStyleText |
|
3045 // |
|
3046 |
|
3047 nsStyleText::nsStyleText(void) |
|
3048 { |
|
3049 MOZ_COUNT_CTOR(nsStyleText); |
|
3050 mTextAlign = NS_STYLE_TEXT_ALIGN_DEFAULT; |
|
3051 mTextAlignLast = NS_STYLE_TEXT_ALIGN_AUTO; |
|
3052 mTextAlignTrue = false; |
|
3053 mTextAlignLastTrue = false; |
|
3054 mTextTransform = NS_STYLE_TEXT_TRANSFORM_NONE; |
|
3055 mWhiteSpace = NS_STYLE_WHITESPACE_NORMAL; |
|
3056 mWordBreak = NS_STYLE_WORDBREAK_NORMAL; |
|
3057 mWordWrap = NS_STYLE_WORDWRAP_NORMAL; |
|
3058 mHyphens = NS_STYLE_HYPHENS_MANUAL; |
|
3059 mTextSizeAdjust = NS_STYLE_TEXT_SIZE_ADJUST_AUTO; |
|
3060 mTextOrientation = NS_STYLE_TEXT_ORIENTATION_AUTO; |
|
3061 mTextCombineUpright = NS_STYLE_TEXT_COMBINE_UPRIGHT_NONE; |
|
3062 mControlCharacterVisibility = NS_STYLE_CONTROL_CHARACTER_VISIBILITY_HIDDEN; |
|
3063 |
|
3064 mLetterSpacing.SetNormalValue(); |
|
3065 mLineHeight.SetNormalValue(); |
|
3066 mTextIndent.SetCoordValue(0); |
|
3067 mWordSpacing = 0; |
|
3068 |
|
3069 mTextShadow = nullptr; |
|
3070 mTabSize = NS_STYLE_TABSIZE_INITIAL; |
|
3071 } |
|
3072 |
|
3073 nsStyleText::nsStyleText(const nsStyleText& aSource) |
|
3074 : mTextAlign(aSource.mTextAlign), |
|
3075 mTextAlignLast(aSource.mTextAlignLast), |
|
3076 mTextAlignTrue(false), |
|
3077 mTextAlignLastTrue(false), |
|
3078 mTextTransform(aSource.mTextTransform), |
|
3079 mWhiteSpace(aSource.mWhiteSpace), |
|
3080 mWordBreak(aSource.mWordBreak), |
|
3081 mWordWrap(aSource.mWordWrap), |
|
3082 mHyphens(aSource.mHyphens), |
|
3083 mTextSizeAdjust(aSource.mTextSizeAdjust), |
|
3084 mTextOrientation(aSource.mTextOrientation), |
|
3085 mTextCombineUpright(aSource.mTextCombineUpright), |
|
3086 mControlCharacterVisibility(aSource.mControlCharacterVisibility), |
|
3087 mTabSize(aSource.mTabSize), |
|
3088 mWordSpacing(aSource.mWordSpacing), |
|
3089 mLetterSpacing(aSource.mLetterSpacing), |
|
3090 mLineHeight(aSource.mLineHeight), |
|
3091 mTextIndent(aSource.mTextIndent), |
|
3092 mTextShadow(aSource.mTextShadow) |
|
3093 { |
|
3094 MOZ_COUNT_CTOR(nsStyleText); |
|
3095 } |
|
3096 |
|
3097 nsStyleText::~nsStyleText(void) |
|
3098 { |
|
3099 MOZ_COUNT_DTOR(nsStyleText); |
|
3100 } |
|
3101 |
|
3102 nsChangeHint nsStyleText::CalcDifference(const nsStyleText& aOther) const |
|
3103 { |
|
3104 if (WhiteSpaceOrNewlineIsSignificant() != |
|
3105 aOther.WhiteSpaceOrNewlineIsSignificant()) { |
|
3106 // This may require construction of suppressed text frames |
|
3107 return NS_STYLE_HINT_FRAMECHANGE; |
|
3108 } |
|
3109 |
|
3110 if (mTextCombineUpright != aOther.mTextCombineUpright || |
|
3111 mControlCharacterVisibility != aOther.mControlCharacterVisibility) { |
|
3112 return nsChangeHint_ReconstructFrame; |
|
3113 } |
|
3114 |
|
3115 if ((mTextAlign != aOther.mTextAlign) || |
|
3116 (mTextAlignLast != aOther.mTextAlignLast) || |
|
3117 (mTextAlignTrue != aOther.mTextAlignTrue) || |
|
3118 (mTextAlignLastTrue != aOther.mTextAlignLastTrue) || |
|
3119 (mTextTransform != aOther.mTextTransform) || |
|
3120 (mWhiteSpace != aOther.mWhiteSpace) || |
|
3121 (mWordBreak != aOther.mWordBreak) || |
|
3122 (mWordWrap != aOther.mWordWrap) || |
|
3123 (mHyphens != aOther.mHyphens) || |
|
3124 (mTextSizeAdjust != aOther.mTextSizeAdjust) || |
|
3125 (mTextOrientation != aOther.mTextOrientation) || |
|
3126 (mLetterSpacing != aOther.mLetterSpacing) || |
|
3127 (mLineHeight != aOther.mLineHeight) || |
|
3128 (mTextIndent != aOther.mTextIndent) || |
|
3129 (mWordSpacing != aOther.mWordSpacing) || |
|
3130 (mTabSize != aOther.mTabSize)) |
|
3131 return NS_STYLE_HINT_REFLOW; |
|
3132 |
|
3133 return CalcShadowDifference(mTextShadow, aOther.mTextShadow); |
|
3134 } |
|
3135 |
|
3136 //----------------------- |
|
3137 // nsStyleUserInterface |
|
3138 // |
|
3139 |
|
3140 nsCursorImage::nsCursorImage() |
|
3141 : mHaveHotspot(false) |
|
3142 , mHotspotX(0.0f) |
|
3143 , mHotspotY(0.0f) |
|
3144 { |
|
3145 } |
|
3146 |
|
3147 nsCursorImage::nsCursorImage(const nsCursorImage& aOther) |
|
3148 : mHaveHotspot(aOther.mHaveHotspot) |
|
3149 , mHotspotX(aOther.mHotspotX) |
|
3150 , mHotspotY(aOther.mHotspotY) |
|
3151 { |
|
3152 SetImage(aOther.GetImage()); |
|
3153 } |
|
3154 |
|
3155 nsCursorImage::~nsCursorImage() |
|
3156 { |
|
3157 SetImage(nullptr); |
|
3158 } |
|
3159 |
|
3160 nsCursorImage& |
|
3161 nsCursorImage::operator=(const nsCursorImage& aOther) |
|
3162 { |
|
3163 if (this != &aOther) { |
|
3164 mHaveHotspot = aOther.mHaveHotspot; |
|
3165 mHotspotX = aOther.mHotspotX; |
|
3166 mHotspotY = aOther.mHotspotY; |
|
3167 SetImage(aOther.GetImage()); |
|
3168 } |
|
3169 |
|
3170 return *this; |
|
3171 } |
|
3172 |
|
3173 nsStyleUserInterface::nsStyleUserInterface(void) |
|
3174 { |
|
3175 MOZ_COUNT_CTOR(nsStyleUserInterface); |
|
3176 mUserInput = NS_STYLE_USER_INPUT_AUTO; |
|
3177 mUserModify = NS_STYLE_USER_MODIFY_READ_ONLY; |
|
3178 mUserFocus = NS_STYLE_USER_FOCUS_NONE; |
|
3179 |
|
3180 mCursor = NS_STYLE_CURSOR_AUTO; // fix for bugzilla bug 51113 |
|
3181 |
|
3182 mCursorArrayLength = 0; |
|
3183 mCursorArray = nullptr; |
|
3184 } |
|
3185 |
|
3186 nsStyleUserInterface::nsStyleUserInterface(const nsStyleUserInterface& aSource) : |
|
3187 mUserInput(aSource.mUserInput), |
|
3188 mUserModify(aSource.mUserModify), |
|
3189 mUserFocus(aSource.mUserFocus), |
|
3190 mCursor(aSource.mCursor) |
|
3191 { |
|
3192 MOZ_COUNT_CTOR(nsStyleUserInterface); |
|
3193 CopyCursorArrayFrom(aSource); |
|
3194 } |
|
3195 |
|
3196 nsStyleUserInterface::~nsStyleUserInterface(void) |
|
3197 { |
|
3198 MOZ_COUNT_DTOR(nsStyleUserInterface); |
|
3199 delete [] mCursorArray; |
|
3200 } |
|
3201 |
|
3202 nsChangeHint nsStyleUserInterface::CalcDifference(const nsStyleUserInterface& aOther) const |
|
3203 { |
|
3204 nsChangeHint hint = nsChangeHint(0); |
|
3205 if (mCursor != aOther.mCursor) |
|
3206 NS_UpdateHint(hint, nsChangeHint_UpdateCursor); |
|
3207 |
|
3208 // We could do better. But it wouldn't be worth it, URL-specified cursors are |
|
3209 // rare. |
|
3210 if (mCursorArrayLength > 0 || aOther.mCursorArrayLength > 0) |
|
3211 NS_UpdateHint(hint, nsChangeHint_UpdateCursor); |
|
3212 |
|
3213 if (mUserModify != aOther.mUserModify) |
|
3214 NS_UpdateHint(hint, NS_STYLE_HINT_VISUAL); |
|
3215 |
|
3216 if ((mUserInput != aOther.mUserInput) && |
|
3217 ((NS_STYLE_USER_INPUT_NONE == mUserInput) || |
|
3218 (NS_STYLE_USER_INPUT_NONE == aOther.mUserInput))) { |
|
3219 NS_UpdateHint(hint, NS_STYLE_HINT_FRAMECHANGE); |
|
3220 } |
|
3221 |
|
3222 // ignore mUserFocus |
|
3223 |
|
3224 return hint; |
|
3225 } |
|
3226 |
|
3227 void |
|
3228 nsStyleUserInterface::CopyCursorArrayFrom(const nsStyleUserInterface& aSource) |
|
3229 { |
|
3230 mCursorArray = nullptr; |
|
3231 mCursorArrayLength = 0; |
|
3232 if (aSource.mCursorArrayLength) { |
|
3233 mCursorArray = new nsCursorImage[aSource.mCursorArrayLength]; |
|
3234 if (mCursorArray) { |
|
3235 mCursorArrayLength = aSource.mCursorArrayLength; |
|
3236 for (uint32_t i = 0; i < mCursorArrayLength; ++i) |
|
3237 mCursorArray[i] = aSource.mCursorArray[i]; |
|
3238 } |
|
3239 } |
|
3240 } |
|
3241 |
|
3242 //----------------------- |
|
3243 // nsStyleUIReset |
|
3244 // |
|
3245 |
|
3246 nsStyleUIReset::nsStyleUIReset(void) |
|
3247 { |
|
3248 MOZ_COUNT_CTOR(nsStyleUIReset); |
|
3249 mUserSelect = NS_STYLE_USER_SELECT_AUTO; |
|
3250 mForceBrokenImageIcon = 0; |
|
3251 mIMEMode = NS_STYLE_IME_MODE_AUTO; |
|
3252 mWindowShadow = NS_STYLE_WINDOW_SHADOW_DEFAULT; |
|
3253 } |
|
3254 |
|
3255 nsStyleUIReset::nsStyleUIReset(const nsStyleUIReset& aSource) |
|
3256 { |
|
3257 MOZ_COUNT_CTOR(nsStyleUIReset); |
|
3258 mUserSelect = aSource.mUserSelect; |
|
3259 mForceBrokenImageIcon = aSource.mForceBrokenImageIcon; |
|
3260 mIMEMode = aSource.mIMEMode; |
|
3261 mWindowShadow = aSource.mWindowShadow; |
|
3262 } |
|
3263 |
|
3264 nsStyleUIReset::~nsStyleUIReset(void) |
|
3265 { |
|
3266 MOZ_COUNT_DTOR(nsStyleUIReset); |
|
3267 } |
|
3268 |
|
3269 nsChangeHint nsStyleUIReset::CalcDifference(const nsStyleUIReset& aOther) const |
|
3270 { |
|
3271 // ignore mIMEMode |
|
3272 if (mForceBrokenImageIcon != aOther.mForceBrokenImageIcon) |
|
3273 return NS_STYLE_HINT_FRAMECHANGE; |
|
3274 if (mWindowShadow != aOther.mWindowShadow) { |
|
3275 // We really need just an nsChangeHint_SyncFrameView, except |
|
3276 // on an ancestor of the frame, so we get that by doing a |
|
3277 // reflow. |
|
3278 return NS_STYLE_HINT_REFLOW; |
|
3279 } |
|
3280 if (mUserSelect != aOther.mUserSelect) |
|
3281 return NS_STYLE_HINT_VISUAL; |
|
3282 return NS_STYLE_HINT_NONE; |
|
3283 } |
|
3284 |
|
3285 //----------------------- |
|
3286 // nsStyleVariables |
|
3287 // |
|
3288 |
|
3289 nsStyleVariables::nsStyleVariables() |
|
3290 { |
|
3291 MOZ_COUNT_CTOR(nsStyleVariables); |
|
3292 } |
|
3293 |
|
3294 nsStyleVariables::nsStyleVariables(const nsStyleVariables& aSource) |
|
3295 { |
|
3296 MOZ_COUNT_CTOR(nsStyleVariables); |
|
3297 } |
|
3298 |
|
3299 nsStyleVariables::~nsStyleVariables(void) |
|
3300 { |
|
3301 MOZ_COUNT_DTOR(nsStyleVariables); |
|
3302 } |
|
3303 |
|
3304 nsChangeHint |
|
3305 nsStyleVariables::CalcDifference(const nsStyleVariables& aOther) const |
|
3306 { |
|
3307 return nsChangeHint(0); |
|
3308 } |