layout/style/nsStyleStruct.cpp

Fri, 16 Jan 2015 18:13:44 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 18:13:44 +0100
branch
TOR_BUG_9701
changeset 14
925c144e1f1f
permissions
-rw-r--r--

Integrate suggestion from review to improve consistency with existing code.

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 }

mercurial