LCOV - code coverage report
Current view: top level - layout/style - nsStyleStruct.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 1339 2190 61.1 %
Date: 2017-07-14 16:53:18 Functions: 162 241 67.2 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13