layout/style/nsStyleStruct.cpp

Wed, 31 Dec 2014 07:16:47 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:16:47 +0100
branch
TOR_BUG_9701
changeset 3
141e0f1194b1
permissions
-rw-r--r--

Revert simplistic fix pending revisit of Mozilla integration attempt.

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

mercurial