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