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

Generated by: LCOV version 1.13-14-ga5dd952