LCOV - code coverage report
Current view: top level - layout/style - nsRuleNode.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 2574 4673 55.1 %
Date: 2017-07-14 16:53:18 Functions: 212 345 61.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set ts=2 et sw=2 tw=78: */
       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             :  * a node in the lexicographic tree of rules that match an element,
       9             :  * responsible for converting the rules' information into computed style
      10             :  */
      11             : 
      12             : #include "nsRuleNode.h"
      13             : 
      14             : #include <algorithm>
      15             : #include <functional>
      16             : 
      17             : #include "mozilla/ArrayUtils.h"
      18             : #include "mozilla/Assertions.h"
      19             : #include "mozilla/DebugOnly.h"
      20             : #include "mozilla/dom/AnimationEffectReadOnlyBinding.h" // for PlaybackDirection
      21             : #include "mozilla/Likely.h"
      22             : #include "mozilla/LookAndFeel.h"
      23             : #include "mozilla/Maybe.h"
      24             : #include "mozilla/OperatorNewExtensions.h"
      25             : #include "mozilla/Unused.h"
      26             : 
      27             : #include "mozilla/css/Declaration.h"
      28             : #include "mozilla/TypeTraits.h"
      29             : 
      30             : #include "gfxContext.h"
      31             : #include "nsAlgorithm.h" // for clamped()
      32             : #include "nscore.h"
      33             : #include "nsCRT.h" // for IsAscii()
      34             : #include "nsIWidget.h"
      35             : #include "nsIPresShell.h"
      36             : #include "nsFontMetrics.h"
      37             : #include "gfxFont.h"
      38             : #include "nsCSSAnonBoxes.h"
      39             : #include "nsCSSPseudoElements.h"
      40             : #include "nsThemeConstants.h"
      41             : #include "PLDHashTable.h"
      42             : #include "GeckoStyleContext.h"
      43             : #include "nsStyleSet.h"
      44             : #include "nsStyleStruct.h"
      45             : #include "nsSize.h"
      46             : #include "nsRuleData.h"
      47             : #include "nsIStyleRule.h"
      48             : #include "nsBidiUtils.h"
      49             : #include "nsStyleStructInlines.h"
      50             : #include "nsCSSProps.h"
      51             : #include "nsTArray.h"
      52             : #include "nsContentUtils.h"
      53             : #include "CSSCalc.h"
      54             : #include "nsPrintfCString.h"
      55             : #include "nsStyleUtil.h"
      56             : #include "nsIDocument.h"
      57             : #include "prtime.h"
      58             : #include "CSSVariableResolver.h"
      59             : #include "nsCSSParser.h"
      60             : #include "CounterStyleManager.h"
      61             : #include "nsCSSPropertyIDSet.h"
      62             : #include "mozilla/RuleNodeCacheConditions.h"
      63             : #include "nsDeviceContext.h"
      64             : #include "nsQueryObject.h"
      65             : #include "nsUnicodeProperties.h"
      66             : 
      67             : #if defined(_MSC_VER) || defined(__MINGW32__)
      68             : #include <malloc.h>
      69             : #ifdef _MSC_VER
      70             : #define alloca _alloca
      71             : #endif
      72             : #endif
      73             : #ifdef SOLARIS
      74             : #include <alloca.h>
      75             : #endif
      76             : 
      77             : using std::max;
      78             : using std::min;
      79             : using namespace mozilla;
      80             : using namespace mozilla::dom;
      81             : 
      82             : namespace mozilla {
      83             : 
      84             : enum UnsetAction
      85             : {
      86             :   eUnsetInitial,
      87             :   eUnsetInherit
      88             : };
      89             : 
      90             : } // namespace mozilla
      91             : 
      92             : void*
      93          50 : nsConditionalResetStyleData::GetConditionalStyleData(nsStyleStructID aSID,
      94             :                                GeckoStyleContext* aStyleContext) const
      95             : {
      96          50 :   Entry* e = static_cast<Entry*>(mEntries[aSID]);
      97          50 :   MOZ_ASSERT(e, "if mConditionalBits bit is set, we must have at least one "
      98             :                 "conditional style struct");
      99           0 :   do {
     100          50 :     if (e->mConditions.Matches(aStyleContext)) {
     101          50 :       void* data = e->mStyleStruct;
     102             : 
     103             :       // For reset structs with conditions, we cache the data on the
     104             :       // style context.
     105             :       // Tell the style context that it doesn't own the data
     106          50 :       aStyleContext->AddStyleBit(GetBitForSID(aSID));
     107          50 :       aStyleContext->SetStyle(aSID, data);
     108             : 
     109          50 :       return data;
     110             :     }
     111           0 :     e = e->mNext;
     112           0 :   } while (e);
     113           0 :   return nullptr;
     114             : }
     115             : 
     116             : // Creates an imgRequestProxy based on the specified value in aValue and
     117             : // returns it.  If the nsPresContext is static (e.g. for printing), then
     118             : // a static request (i.e. showing the first frame, without animation)
     119             : // will be created.
     120             : static already_AddRefed<imgRequestProxy>
     121         141 : CreateImageRequest(nsPresContext* aPresContext, const nsCSSValue& aValue)
     122             : {
     123             :   RefPtr<imgRequestProxy> req =
     124         282 :     aValue.GetPossiblyStaticImageValue(aPresContext->Document(),
     125         282 :                                        aPresContext);
     126         282 :   return req.forget();
     127             : }
     128             : 
     129             : static already_AddRefed<nsStyleImageRequest>
     130         141 : CreateStyleImageRequest(nsPresContext* aPresContext, const nsCSSValue& aValue,
     131             :                         nsStyleImageRequest::Mode aModeFlags =
     132             :                           nsStyleImageRequest::Mode::Track)
     133             : {
     134         141 :   css::ImageValue* imageValue = aValue.GetImageStructValue();
     135             :   ImageTracker* imageTracker =
     136         282 :     (aModeFlags & nsStyleImageRequest::Mode::Track)
     137         141 :     ? aPresContext->Document()->ImageTracker()
     138         282 :     : nullptr;
     139         282 :   RefPtr<imgRequestProxy> proxy = CreateImageRequest(aPresContext, aValue);
     140             :   RefPtr<nsStyleImageRequest> request =
     141         423 :     new nsStyleImageRequest(aModeFlags, proxy, imageValue, imageTracker);
     142         282 :   return request.forget();
     143             : }
     144             : 
     145             : static void
     146             : SetStyleShapeSourceToCSSValue(StyleShapeSource* aShapeSource,
     147             :                               const nsCSSValue* aValue,
     148             :                               GeckoStyleContext* aStyleContext,
     149             :                               nsPresContext* aPresContext,
     150             :                               RuleNodeCacheConditions& aConditions);
     151             : 
     152             : /* Helper function to convert a CSS <position> specified value into its
     153             :  * computed-style form. */
     154             : static void
     155             : ComputePositionValue(GeckoStyleContext* aStyleContext,
     156             :                      const nsCSSValue& aValue,
     157             :                      Position& aComputedValue,
     158             :                      RuleNodeCacheConditions& aConditions);
     159             : 
     160             : /*
     161             :  * For storage of an |nsRuleNode|'s children in a PLDHashTable.
     162             :  */
     163             : 
     164             : struct ChildrenHashEntry : public PLDHashEntryHdr {
     165             :   // key is |mRuleNode->GetKey()|
     166             :   nsRuleNode *mRuleNode;
     167             : };
     168             : 
     169             : /* static */ PLDHashNumber
     170        1797 : nsRuleNode::ChildrenHashHashKey(const void *aKey)
     171             : {
     172             :   const nsRuleNode::Key *key =
     173        1797 :     static_cast<const nsRuleNode::Key*>(aKey);
     174             :   // Disagreement on importance and level for the same rule is extremely
     175             :   // rare, so hash just on the rule.
     176        1797 :   return PLDHashTable::HashVoidPtrKeyStub(key->mRule);
     177             : }
     178             : 
     179             : /* static */ bool
     180        1669 : nsRuleNode::ChildrenHashMatchEntry(const PLDHashEntryHdr *aHdr,
     181             :                                    const void *aKey)
     182             : {
     183             :   const ChildrenHashEntry *entry =
     184        1669 :     static_cast<const ChildrenHashEntry*>(aHdr);
     185             :   const nsRuleNode::Key *key =
     186        1669 :     static_cast<const nsRuleNode::Key*>(aKey);
     187        1669 :   return entry->mRuleNode->GetKey() == *key;
     188             : }
     189             : 
     190             : /* static */ const PLDHashTableOps
     191             : nsRuleNode::ChildrenHashOps = {
     192             :   // It's probably better to allocate the table itself using malloc and
     193             :   // free rather than the pres shell's arena because the table doesn't
     194             :   // grow very often and the pres shell's arena doesn't recycle very
     195             :   // large size allocations.
     196             :   ChildrenHashHashKey,
     197             :   ChildrenHashMatchEntry,
     198             :   PLDHashTable::MoveEntryStub,
     199             :   PLDHashTable::ClearEntryStub,
     200             :   nullptr
     201             : };
     202             : 
     203             : 
     204             : // EnsureBlockDisplay:
     205             : // Never change display:none or display:contents *ever*, otherwise:
     206             : //  - if the display value (argument) is not a block-type
     207             : //    then we set it to a valid block display value
     208             : //  - For enforcing the floated/positioned element CSS2 rules
     209             : //  - We allow the behavior of "list-item" to be customized.
     210             : //    CSS21 says that position/float do not convert 'list-item' to 'block',
     211             : //    but it explicitly does not define whether 'list-item' should be
     212             : //    converted to block *on the root node*. To allow for flexibility
     213             : //    (so that we don't have to support a list-item root node), this method
     214             : //    lets the caller pick either behavior, using the 'aConvertListItem' arg.
     215             : //    Reference: http://www.w3.org/TR/CSS21/visuren.html#dis-pos-flo
     216             : /* static */
     217             : void
     218         193 : nsRuleNode::EnsureBlockDisplay(StyleDisplay& display,
     219             :                                bool aConvertListItem /* = false */)
     220             : {
     221             :   // see if the display value is already a block
     222         193 :   switch (display) {
     223             :   case StyleDisplay::ListItem:
     224           0 :     if (aConvertListItem) {
     225           0 :       display = StyleDisplay::Block;
     226           0 :       break;
     227             :     } // else, fall through to share the 'break' for non-changing display vals
     228             :     MOZ_FALLTHROUGH;
     229             :   case StyleDisplay::None:
     230             :   case StyleDisplay::Contents:
     231             :     // never change display:none or display:contents *ever*
     232             :   case StyleDisplay::Table:
     233             :   case StyleDisplay::Block:
     234             :   case StyleDisplay::Flex:
     235             :   case StyleDisplay::WebkitBox:
     236             :   case StyleDisplay::Grid:
     237             :   case StyleDisplay::FlowRoot:
     238             :     // do not muck with these at all - already blocks
     239             :     // This is equivalent to nsStyleDisplay::IsBlockOutside.  (XXX Maybe we
     240             :     // should just call that?)
     241             :     // This needs to match the check done in
     242             :     // nsCSSFrameConstructor::FindMathMLData for <math>.
     243          85 :     break;
     244             : 
     245             :   case StyleDisplay::InlineTable:
     246             :     // make inline tables into tables
     247           0 :     display = StyleDisplay::Table;
     248           0 :     break;
     249             : 
     250             :   case StyleDisplay::InlineFlex:
     251             :     // make inline flex containers into flex containers
     252           0 :     display = StyleDisplay::Flex;
     253           0 :     break;
     254             : 
     255             :   case StyleDisplay::WebkitInlineBox:
     256             :     // make -webkit-inline-box containers into -webkit-box containers
     257           0 :     display = StyleDisplay::WebkitBox;
     258           0 :     break;
     259             : 
     260             :   case StyleDisplay::InlineGrid:
     261             :     // make inline grid containers into grid containers
     262           0 :     display = StyleDisplay::Grid;
     263           0 :     break;
     264             : 
     265             :   default:
     266             :     // make it a block
     267         108 :     display = StyleDisplay::Block;
     268             :   }
     269         193 : }
     270             : 
     271             : // EnsureInlineDisplay:
     272             : //  - if the display value (argument) is not an inline type
     273             : //    then we set it to a valid inline display value
     274             : /* static */
     275             : void
     276           0 : nsRuleNode::EnsureInlineDisplay(StyleDisplay& display)
     277             : {
     278             :   // see if the display value is already inline
     279           0 :   switch (display) {
     280             :     case StyleDisplay::Block:
     281             :     case StyleDisplay::FlowRoot:
     282           0 :       display = StyleDisplay::InlineBlock;
     283           0 :       break;
     284             :     case StyleDisplay::Table:
     285           0 :       display = StyleDisplay::InlineTable;
     286           0 :       break;
     287             :     case StyleDisplay::Flex:
     288           0 :       display = StyleDisplay::InlineFlex;
     289           0 :       break;
     290             :     case StyleDisplay::WebkitBox:
     291           0 :       display = StyleDisplay::WebkitInlineBox;
     292           0 :       break;
     293             :     case StyleDisplay::Grid:
     294           0 :       display = StyleDisplay::InlineGrid;
     295           0 :       break;
     296             :     case StyleDisplay::MozBox:
     297           0 :       display = StyleDisplay::MozInlineBox;
     298           0 :       break;
     299             :     case StyleDisplay::MozStack:
     300           0 :       display = StyleDisplay::MozInlineStack;
     301           0 :       break;
     302             :     default:
     303           0 :       break; // Do nothing
     304             :   }
     305           0 : }
     306             : 
     307             : static nscoord CalcLengthWith(const nsCSSValue& aValue,
     308             :                               nscoord aFontSize,
     309             :                               const nsStyleFont* aStyleFont,
     310             :                               nsStyleContext* aStyleContext,
     311             :                               nsPresContext* aPresContext,
     312             :                               bool aUseProvidedRootEmSize,
     313             :                               bool aUseUserFontSet,
     314             :                               RuleNodeCacheConditions& aConditions);
     315             : 
     316             : struct CalcLengthCalcOps : public css::BasicCoordCalcOps,
     317             :                            public css::FloatCoeffsAlreadyNormalizedOps
     318             : {
     319             :   // Declare that we have floats as coefficients so that we unambiguously
     320             :   // resolve coeff_type (BasicCoordCalcOps and FloatCoeffsAlreadyNormalizedOps
     321             :   // both have |typedef float coeff_type|).
     322             :   typedef float coeff_type;
     323             : 
     324             :   // All of the parameters to CalcLengthWith except aValue.
     325             :   const nscoord mFontSize;
     326             :   const nsStyleFont* const mStyleFont;
     327             :   nsStyleContext* const mStyleContext;
     328             :   nsPresContext* const mPresContext;
     329             :   const bool mUseProvidedRootEmSize;
     330             :   const bool mUseUserFontSet;
     331             :   RuleNodeCacheConditions& mConditions;
     332             : 
     333           0 :   CalcLengthCalcOps(nscoord aFontSize, const nsStyleFont* aStyleFont,
     334             :                     nsStyleContext* aStyleContext, nsPresContext* aPresContext,
     335             :                     bool aUseProvidedRootEmSize, bool aUseUserFontSet,
     336             :                     RuleNodeCacheConditions& aConditions)
     337           0 :     : mFontSize(aFontSize),
     338             :       mStyleFont(aStyleFont),
     339             :       mStyleContext(aStyleContext),
     340             :       mPresContext(aPresContext),
     341             :       mUseProvidedRootEmSize(aUseProvidedRootEmSize),
     342             :       mUseUserFontSet(aUseUserFontSet),
     343           0 :       mConditions(aConditions)
     344             :   {
     345           0 :   }
     346             : 
     347           0 :   result_type ComputeLeafValue(const nsCSSValue& aValue)
     348             :   {
     349           0 :     return CalcLengthWith(aValue, mFontSize, mStyleFont,
     350           0 :                           mStyleContext, mPresContext, mUseProvidedRootEmSize,
     351           0 :                           mUseUserFontSet, mConditions);
     352             :   }
     353             : };
     354             : 
     355          19 : static inline nscoord ScaleCoordRound(const nsCSSValue& aValue, float aFactor)
     356             : {
     357          19 :   return NSToCoordRoundWithClamp(aValue.GetFloatValue() * aFactor);
     358             : }
     359             : 
     360           0 : static inline nscoord ScaleViewportCoordTrunc(const nsCSSValue& aValue,
     361             :                                               nscoord aViewportSize)
     362             : {
     363             :   // For units (like percentages and viewport units) where authors might
     364             :   // repeatedly use a value and expect some multiple of the value to be
     365             :   // smaller than a container, we need to use floor rather than round.
     366             :   // We need to use division by 100.0 rather than multiplication by 0.1f
     367             :   // to avoid introducing error.
     368           0 :   return NSToCoordTruncClamped(aValue.GetFloatValue() *
     369           0 :                                aViewportSize / 100.0f);
     370             : }
     371             : 
     372             : /* static */
     373             : already_AddRefed<nsFontMetrics>
     374           8 : nsRuleNode::GetMetricsFor(nsPresContext* aPresContext,
     375             :                           bool aIsVertical,
     376             :                           const nsStyleFont* aStyleFont,
     377             :                           nscoord aFontSize,
     378             :                           bool aUseUserFontSet)
     379             : {
     380          16 :   nsFont font = aStyleFont->mFont;
     381           8 :   font.size = aFontSize;
     382             :   gfxFont::Orientation orientation
     383           8 :     = aIsVertical ? gfxFont::eVertical : gfxFont::eHorizontal;
     384           8 :   nsFontMetrics::Params params;
     385           8 :   params.language = aStyleFont->mLanguage;
     386           8 :   params.explicitLanguage = aStyleFont->mExplicitLanguage;
     387           8 :   params.orientation = orientation;
     388           8 :   params.userFontSet =
     389           8 :     aUseUserFontSet ? aPresContext->GetUserFontSet() : nullptr;
     390           8 :   params.textPerf = aPresContext->GetTextPerfMetrics();
     391          16 :   return aPresContext->DeviceContext()->GetMetricsFor(font, params);
     392             : }
     393             : 
     394             : /* static */
     395             : already_AddRefed<nsFontMetrics>
     396           8 : nsRuleNode::GetMetricsFor(nsPresContext* aPresContext,
     397             :                           nsStyleContext* aStyleContext,
     398             :                           const nsStyleFont* aStyleFont,
     399             :                           nscoord aFontSize, // overrides value from aStyleFont
     400             :                           bool aUseUserFontSet)
     401             : {
     402           8 :   bool isVertical = false;
     403           8 :   if (aStyleContext) {
     404           8 :     WritingMode wm(aStyleContext);
     405           8 :     if (wm.IsVertical() && !wm.IsSideways()) {
     406           0 :       isVertical = true;
     407             :     }
     408             :   }
     409             :   return nsRuleNode::GetMetricsFor(aPresContext, isVertical, aStyleFont,
     410           8 :                                    aFontSize, aUseUserFontSet);
     411             : }
     412             : 
     413             : /* static */
     414             : void
     415           0 : nsRuleNode::FixupNoneGeneric(nsFont* aFont,
     416             :                              const nsPresContext* aPresContext,
     417             :                              uint8_t aGenericFontID,
     418             :                              const nsFont* aDefaultVariableFont)
     419             : {
     420             :   bool useDocumentFonts =
     421           0 :     aPresContext->GetCachedBoolPref(kPresContext_UseDocumentFonts);
     422           0 :   if (aGenericFontID == kGenericFont_NONE ||
     423           0 :       (!useDocumentFonts && (aGenericFontID == kGenericFont_cursive ||
     424             :                              aGenericFontID == kGenericFont_fantasy))) {
     425             :     FontFamilyType defaultGeneric =
     426           0 :       aDefaultVariableFont->fontlist.FirstGeneric();
     427           0 :     MOZ_ASSERT(aDefaultVariableFont->fontlist.Length() == 1 &&
     428             :                (defaultGeneric == eFamily_serif ||
     429             :                 defaultGeneric == eFamily_sans_serif));
     430           0 :     if (defaultGeneric != eFamily_none) {
     431           0 :       if (useDocumentFonts) {
     432           0 :         aFont->fontlist.SetDefaultFontType(defaultGeneric);
     433             :       } else {
     434             :         // Either prioritize the first generic in the list,
     435             :         // or (if there isn't one) prepend the default variable font.
     436           0 :         if (!aFont->fontlist.PrioritizeFirstGeneric()) {
     437           0 :           aFont->fontlist.PrependGeneric(defaultGeneric);
     438             :         }
     439             :       }
     440           0 :     }
     441             :   } else {
     442           0 :     aFont->fontlist.SetDefaultFontType(eFamily_none);
     443             :   }
     444           0 : }
     445             : 
     446             : /* static */
     447             : void
     448          12 : nsRuleNode::ApplyMinFontSize(nsStyleFont* aFont,
     449             :                              const nsPresContext* aPresContext,
     450             :                              nscoord aMinFontSize)
     451             : {
     452          12 :   nscoord fontSize = aFont->mSize;
     453             : 
     454             :   // enforce the user' specified minimum font-size on the value that we expose
     455             :   // (but don't change font-size:0, since that would unhide hidden text)
     456          12 :   if (fontSize > 0) {
     457          12 :     if (aMinFontSize < 0) {
     458           0 :       aMinFontSize = 0;
     459             :     } else {
     460          12 :       aMinFontSize = (aMinFontSize * aFont->mMinFontSizeRatio) / 100;
     461             :     }
     462          12 :     if (fontSize < aMinFontSize && !aPresContext->IsChrome()) {
     463             :       // override the minimum font-size constraint
     464           0 :       fontSize = aMinFontSize;
     465             :     }
     466             :   }
     467          12 :   aFont->mFont.size = fontSize;
     468          12 : }
     469             : 
     470           0 : static nsSize CalcViewportUnitsScale(nsPresContext* aPresContext)
     471             : {
     472             :   // The caller is making use of viewport units, so notify the pres context
     473             :   // that it will need to rebuild the rule tree if the size of the viewport
     474             :   // changes.
     475           0 :   aPresContext->SetUsesViewportUnits(true);
     476             : 
     477             :   // The default (when we have 'overflow: auto' on the root element, or
     478             :   // trivially for 'overflow: hidden' since we never have scrollbars in that
     479             :   // case) is to define the scale of the viewport units without considering
     480             :   // scrollbars.
     481           0 :   nsSize viewportSize(aPresContext->GetVisibleArea().Size());
     482             : 
     483             :   // Check for 'overflow: scroll' styles on the root scroll frame. If we find
     484             :   // any, the standard requires us to take scrollbars into account.
     485             :   nsIScrollableFrame* scrollFrame =
     486           0 :     aPresContext->PresShell()->GetRootScrollFrameAsScrollable();
     487           0 :   if (scrollFrame) {
     488           0 :     ScrollbarStyles styles(scrollFrame->GetScrollbarStyles());
     489             : 
     490           0 :     if (styles.mHorizontal == NS_STYLE_OVERFLOW_SCROLL ||
     491           0 :         styles.mVertical == NS_STYLE_OVERFLOW_SCROLL) {
     492             :       // Gather scrollbar size information.
     493             :       RefPtr<gfxContext> context =
     494           0 :         aPresContext->PresShell()->CreateReferenceRenderingContext();
     495           0 :       nsMargin sizes(scrollFrame->GetDesiredScrollbarSizes(aPresContext, context));
     496             : 
     497           0 :       if (styles.mHorizontal == NS_STYLE_OVERFLOW_SCROLL) {
     498             :         // 'overflow-x: scroll' means we must consider the horizontal scrollbar,
     499             :         // which affects the scale of viewport height units.
     500           0 :         viewportSize.height -= sizes.TopBottom();
     501             :       }
     502             : 
     503           0 :       if (styles.mVertical == NS_STYLE_OVERFLOW_SCROLL) {
     504             :         // 'overflow-y: scroll' means we must consider the vertical scrollbar,
     505             :         // which affects the scale of viewport width units.
     506           0 :         viewportSize.width -= sizes.LeftRight();
     507             :       }
     508             :     }
     509             :   }
     510             : 
     511           0 :   return viewportSize;
     512             : }
     513             : 
     514             : // If |aStyleFont| is nullptr, aStyleContext->StyleFont() is used.
     515             : //
     516             : // In case that |aValue| is rem unit, if |aStyleContext| is null, callers must
     517             : // specify a valid |aStyleFont| and |aUseProvidedRootEmSize| must be true so
     518             : // that we can get the length from |aStyleFont|.
     519        2514 : static nscoord CalcLengthWith(const nsCSSValue& aValue,
     520             :                               nscoord aFontSize,
     521             :                               const nsStyleFont* aStyleFont,
     522             :                               nsStyleContext* aStyleContext,
     523             :                               nsPresContext* aPresContext,
     524             :                               bool aUseProvidedRootEmSize,
     525             :                               // aUseUserFontSet should always be true
     526             :                               // except when called from
     527             :                               // CalcLengthWithInitialFont.
     528             :                               bool aUseUserFontSet,
     529             :                               RuleNodeCacheConditions& aConditions)
     530             : {
     531        2514 :   NS_ASSERTION(aValue.IsLengthUnit() || aValue.IsCalcUnit(),
     532             :                "not a length or calc unit");
     533        2514 :   NS_ASSERTION(aStyleFont || aStyleContext,
     534             :                "Must have style data");
     535        2514 :   NS_ASSERTION(aStyleContext || aUseProvidedRootEmSize,
     536             :                "Must have style context or specify aUseProvidedRootEmSize");
     537        2514 :   NS_ASSERTION(aPresContext, "Must have prescontext");
     538             : 
     539        2514 :   if (aValue.IsFixedLengthUnit()) {
     540           0 :     return aValue.GetFixedLength(aPresContext);
     541             :   }
     542        2514 :   if (aValue.IsPixelLengthUnit()) {
     543        2495 :     return aValue.GetPixelLength();
     544             :   }
     545          19 :   if (aValue.IsCalcUnit()) {
     546             :     // For properties for which lengths are the *only* units accepted in
     547             :     // calc(), we can handle calc() here and just compute a final
     548             :     // result.  We ensure that we don't get to this code for other
     549             :     // properties by not calling CalcLength in those cases:  SetCoord
     550             :     // only calls CalcLength for a calc when it is appropriate to do so.
     551             :     CalcLengthCalcOps ops(aFontSize, aStyleFont,
     552             :                           aStyleContext, aPresContext,
     553             :                           aUseProvidedRootEmSize, aUseUserFontSet,
     554           0 :                           aConditions);
     555           0 :     return css::ComputeCalc(aValue, ops);
     556             :   }
     557          19 :   switch (aValue.GetUnit()) {
     558             :     // nsPresContext::SetVisibleArea and
     559             :     // nsPresContext::MediaFeatureValuesChanged handle dynamic changes
     560             :     // of the basis for viewport units by rebuilding the rule tree and
     561             :     // style context tree.  Not caching them in the rule tree wouldn't
     562             :     // be sufficient to handle these changes because we also need a way
     563             :     // to get rid of cached values in the style context tree without any
     564             :     // changes in specified style.  We can either do this by not caching
     565             :     // in the rule tree and then throwing away the style context tree
     566             :     // for dynamic viewport size changes, or by allowing caching in the
     567             :     // rule tree and using the existing rebuild style data path that
     568             :     // throws away the style context and the rule tree.
     569             :     // Thus we do cache viewport units in the rule tree.  This allows us
     570             :     // to benefit from the performance advantages of the rule tree
     571             :     // (e.g., faster dynamic changes on other things, like transforms)
     572             :     // and allows us not to need an additional code path, in exchange
     573             :     // for an increased cost to dynamic changes to the viewport size
     574             :     // when viewport units are in use.
     575             :     case eCSSUnit_ViewportWidth: {
     576           0 :       nscoord viewportWidth = CalcViewportUnitsScale(aPresContext).width;
     577           0 :       return ScaleViewportCoordTrunc(aValue, viewportWidth);
     578             :     }
     579             :     case eCSSUnit_ViewportHeight: {
     580           0 :       nscoord viewportHeight = CalcViewportUnitsScale(aPresContext).height;
     581           0 :       return ScaleViewportCoordTrunc(aValue, viewportHeight);
     582             :     }
     583             :     case eCSSUnit_ViewportMin: {
     584           0 :       nsSize vuScale(CalcViewportUnitsScale(aPresContext));
     585           0 :       nscoord viewportMin = min(vuScale.width, vuScale.height);
     586           0 :       return ScaleViewportCoordTrunc(aValue, viewportMin);
     587             :     }
     588             :     case eCSSUnit_ViewportMax: {
     589           0 :       nsSize vuScale(CalcViewportUnitsScale(aPresContext));
     590           0 :       nscoord viewportMax = max(vuScale.width, vuScale.height);
     591           0 :       return ScaleViewportCoordTrunc(aValue, viewportMax);
     592             :     }
     593             :     // While we could deal with 'rem' units correctly by simply not
     594             :     // caching any data that uses them in the rule tree, it's valuable
     595             :     // to store them in the rule tree (for faster dynamic changes of
     596             :     // other things).  And since the font size of the root element
     597             :     // changes rarely, we instead handle dynamic changes to the root
     598             :     // element's font size by rebuilding all style data in
     599             :     // nsCSSFrameConstructor::RestyleElement.
     600             :     case eCSSUnit_RootEM: {
     601           0 :       aPresContext->SetUsesRootEMUnits(true);
     602             :       nscoord rootFontSize;
     603             : 
     604             :       // NOTE: Be very careful with |styleFont|, since we haven't added any
     605             :       // conditions to aConditions or set it to uncacheable yet, so we don't
     606             :       // want to introduce any dependencies on aStyleContext's data here.
     607             :       const nsStyleFont *styleFont =
     608           0 :         aStyleFont ? aStyleFont : aStyleContext->StyleFont();
     609             : 
     610           0 :       if (aUseProvidedRootEmSize) {
     611             :         // We should use the provided aFontSize as the reference length to
     612             :         // scale. This only happens when we are calculating font-size or
     613             :         // an equivalent (scriptminsize or CalcLengthWithInitialFont) on
     614             :         // the root element, in which case aFontSize is already the
     615             :         // value we want.
     616           0 :         if (aFontSize == -1) {
     617             :           // XXX Should this be styleFont->mSize instead to avoid taking
     618             :           // minfontsize prefs into account?
     619           0 :           aFontSize = styleFont->mFont.size;
     620             :         }
     621           0 :         rootFontSize = aFontSize;
     622           0 :       } else if (aStyleContext && !aStyleContext->GetParent()) {
     623             :         // This is the root element (XXX we don't really know this, but
     624             :         // nsRuleNode::SetFont makes the same assumption!), so we should
     625             :         // use StyleFont on this context to get the root element's
     626             :         // font size.
     627           0 :         rootFontSize = styleFont->mFont.size;
     628             :       } else {
     629             :         // This is not the root element or we are calculating something other
     630             :         // than font size, so rem is relative to the root element's font size.
     631             :         // Find the root style context by walking up the style context tree.
     632             :         // NOTE: We should not call ResolveStyleFor() against the root element
     633             :         // to obtain the root style here because it may lead to reentrant call
     634             :         // of nsStyleSet::GetContext().
     635           0 :         nsStyleContext* rootStyle = aStyleContext;
     636           0 :         while (rootStyle->GetParent()) {
     637           0 :           rootStyle = rootStyle->GetParent();
     638             :         }
     639           0 :         const nsStyleFont *rootStyleFont = rootStyle->StyleFont();
     640           0 :         rootFontSize = rootStyleFont->mFont.size;
     641             :       }
     642             : 
     643           0 :       return ScaleCoordRound(aValue, float(rootFontSize));
     644             :     }
     645             :     default:
     646             :       // Fall through to the code for units that can't be stored in the
     647             :       // rule tree because they depend on font data.
     648          19 :       break;
     649             :   }
     650             :   // Common code for units that depend on the element's font data and
     651             :   // thus can't be stored in the rule tree:
     652             :   const nsStyleFont *styleFont =
     653          19 :     aStyleFont ? aStyleFont : aStyleContext->StyleFont();
     654          19 :   if (aFontSize == -1) {
     655             :     // XXX Should this be styleFont->mSize instead to avoid taking minfontsize
     656             :     // prefs into account?
     657          19 :     aFontSize = styleFont->mFont.size;
     658             :   }
     659          19 :   switch (aValue.GetUnit()) {
     660             :     case eCSSUnit_EM: {
     661          11 :       if (aValue.GetFloatValue() == 0.0f) {
     662             :         // Don't call SetFontSizeDependency for '0em'.
     663           0 :         return 0;
     664             :       }
     665             :       // CSS2.1 specifies that this unit scales to the computed font
     666             :       // size, not the em-width in the font metrics, despite the name.
     667          11 :       aConditions.SetFontSizeDependency(aFontSize);
     668          11 :       return ScaleCoordRound(aValue, float(aFontSize));
     669             :     }
     670             :     case eCSSUnit_XHeight: {
     671           0 :       aPresContext->SetUsesExChUnits(true);
     672             :       RefPtr<nsFontMetrics> fm =
     673           0 :         nsRuleNode::GetMetricsFor(aPresContext, aStyleContext, styleFont,
     674           0 :                                   aFontSize, aUseUserFontSet);
     675           0 :       aConditions.SetUncacheable();
     676           0 :       return ScaleCoordRound(aValue, float(fm->XHeight()));
     677             :     }
     678             :     case eCSSUnit_Char: {
     679           8 :       aPresContext->SetUsesExChUnits(true);
     680             :       RefPtr<nsFontMetrics> fm =
     681          16 :         nsRuleNode::GetMetricsFor(aPresContext, aStyleContext, styleFont,
     682          16 :                                   aFontSize, aUseUserFontSet);
     683             :       gfxFloat zeroWidth =
     684             :         fm->GetThebesFontGroup()->GetFirstValidFont()->
     685           8 :           GetMetrics(fm->Orientation()).zeroOrAveCharWidth;
     686             : 
     687           8 :       aConditions.SetUncacheable();
     688           8 :       return ScaleCoordRound(aValue, ceil(aPresContext->AppUnitsPerDevPixel() *
     689           8 :                                           zeroWidth));
     690             :     }
     691             :     default:
     692           0 :       NS_NOTREACHED("unexpected unit");
     693           0 :       break;
     694             :   }
     695           0 :   return 0;
     696             : }
     697             : 
     698             : /* static */ nscoord
     699        2452 : nsRuleNode::CalcLength(const nsCSSValue& aValue,
     700             :                        nsStyleContext* aStyleContext,
     701             :                        nsPresContext* aPresContext,
     702             :                        RuleNodeCacheConditions& aConditions)
     703             : {
     704        2452 :   NS_ASSERTION(aStyleContext, "Must have style data");
     705             : 
     706             :   return CalcLengthWith(aValue, -1, nullptr,
     707             :                         aStyleContext, aPresContext,
     708        2452 :                         false, true, aConditions);
     709             : }
     710             : 
     711             : /* Inline helper function to redirect requests to CalcLength. */
     712        2424 : static inline nscoord CalcLength(const nsCSSValue& aValue,
     713             :                                  nsStyleContext* aStyleContext,
     714             :                                  nsPresContext* aPresContext,
     715             :                                  RuleNodeCacheConditions& aConditions)
     716             : {
     717             :   return nsRuleNode::CalcLength(aValue, aStyleContext,
     718        2424 :                                 aPresContext, aConditions);
     719             : }
     720             : 
     721             : /* static */ nscoord
     722          62 : nsRuleNode::CalcLengthWithInitialFont(nsPresContext* aPresContext,
     723             :                                       const nsCSSValue& aValue)
     724             : {
     725         124 :   nsStyleFont defaultFont(aPresContext); // FIXME: best language?
     726          62 :   RuleNodeCacheConditions conditions;
     727             :   return CalcLengthWith(aValue, -1, &defaultFont,
     728             :                         nullptr, aPresContext,
     729         124 :                         true, false, conditions);
     730             : }
     731             : 
     732             : struct LengthPercentPairCalcOps : public css::FloatCoeffsAlreadyNormalizedOps
     733             : {
     734             :   typedef nsRuleNode::ComputedCalc result_type;
     735             : 
     736         127 :   LengthPercentPairCalcOps(nsStyleContext* aContext,
     737             :                            nsPresContext* aPresContext,
     738             :                            RuleNodeCacheConditions& aConditions)
     739         127 :     : mContext(aContext),
     740             :       mPresContext(aPresContext),
     741             :       mConditions(aConditions),
     742         127 :       mHasPercent(false) {}
     743             : 
     744             :   nsStyleContext* mContext;
     745             :   nsPresContext* mPresContext;
     746             :   RuleNodeCacheConditions& mConditions;
     747             :   bool mHasPercent;
     748             : 
     749         220 :   result_type ComputeLeafValue(const nsCSSValue& aValue)
     750             :   {
     751         220 :     if (aValue.GetUnit() == eCSSUnit_Percent) {
     752           3 :       mHasPercent = true;
     753           3 :       return result_type(0, aValue.GetPercentValue());
     754             :     }
     755         434 :     return result_type(CalcLength(aValue, mContext, mPresContext,
     756             :                                   mConditions),
     757         217 :                        0.0f);
     758             :   }
     759             : 
     760             :   result_type
     761          93 :   MergeAdditive(nsCSSUnit aCalcFunction,
     762             :                 result_type aValue1, result_type aValue2)
     763             :   {
     764          93 :     if (aCalcFunction == eCSSUnit_Calc_Plus) {
     765         130 :       return result_type(NSCoordSaturatingAdd(aValue1.mLength,
     766             :                                               aValue2.mLength),
     767         130 :                          aValue1.mPercent + aValue2.mPercent);
     768             :     }
     769          28 :     MOZ_ASSERT(aCalcFunction == eCSSUnit_Calc_Minus,
     770             :                "min() and max() are not allowed in calc() on transform");
     771          56 :     return result_type(NSCoordSaturatingSubtract(aValue1.mLength,
     772             :                                                  aValue2.mLength, 0),
     773          56 :                        aValue1.mPercent - aValue2.mPercent);
     774             :   }
     775             : 
     776             :   result_type
     777          88 :   MergeMultiplicativeL(nsCSSUnit aCalcFunction,
     778             :                        float aValue1, result_type aValue2)
     779             :   {
     780          88 :     MOZ_ASSERT(aCalcFunction == eCSSUnit_Calc_Times_L,
     781             :                "unexpected unit");
     782         176 :     return result_type(NSCoordSaturatingMultiply(aValue2.mLength, aValue1),
     783         264 :                        aValue1 * aValue2.mPercent);
     784             :   }
     785             : 
     786             :   result_type
     787          13 :   MergeMultiplicativeR(nsCSSUnit aCalcFunction,
     788             :                        result_type aValue1, float aValue2)
     789             :   {
     790          13 :     MOZ_ASSERT(aCalcFunction == eCSSUnit_Calc_Times_R ||
     791             :                aCalcFunction == eCSSUnit_Calc_Divided,
     792             :                "unexpected unit");
     793          13 :     if (aCalcFunction == eCSSUnit_Calc_Divided) {
     794          13 :       aValue2 = 1.0f / aValue2;
     795             :     }
     796          26 :     return result_type(NSCoordSaturatingMultiply(aValue1.mLength, aValue2),
     797          39 :                        aValue1.mPercent * aValue2);
     798             :   }
     799             : 
     800             : };
     801             : 
     802             : static void
     803         127 : SpecifiedCalcToComputedCalc(const nsCSSValue& aValue, nsStyleCoord& aCoord,
     804             :                             nsStyleContext* aStyleContext,
     805             :                             RuleNodeCacheConditions& aConditions)
     806             : {
     807             :   LengthPercentPairCalcOps ops(aStyleContext, aStyleContext->PresContext(),
     808         127 :                                aConditions);
     809         127 :   nsRuleNode::ComputedCalc vals = ComputeCalc(aValue, ops);
     810             : 
     811         127 :   nsStyleCoord::Calc* calcObj = new nsStyleCoord::Calc;
     812             : 
     813         127 :   calcObj->mLength = vals.mLength;
     814         127 :   calcObj->mPercent = vals.mPercent;
     815         127 :   calcObj->mHasPercent = ops.mHasPercent;
     816             : 
     817         127 :   aCoord.SetCalcValue(calcObj);
     818         127 : }
     819             : 
     820             : /* static */ nsRuleNode::ComputedCalc
     821           0 : nsRuleNode::SpecifiedCalcToComputedCalc(const nsCSSValue& aValue,
     822             :                                         nsStyleContext* aStyleContext,
     823             :                                         nsPresContext* aPresContext,
     824             :                                         RuleNodeCacheConditions& aConditions)
     825             : {
     826             :   LengthPercentPairCalcOps ops(aStyleContext, aPresContext,
     827           0 :                                aConditions);
     828           0 :   return ComputeCalc(aValue, ops);
     829             : }
     830             : 
     831             : // This is our public API for handling calc() expressions that involve
     832             : // percentages.
     833             : /* static */ nscoord
     834         231 : nsRuleNode::ComputeComputedCalc(const nsStyleCoord& aValue,
     835             :                                 nscoord aPercentageBasis)
     836             : {
     837         231 :   nsStyleCoord::Calc* calc = aValue.GetCalcValue();
     838         231 :   return calc->mLength +
     839         231 :          NSToCoordFloorClamped(aPercentageBasis * calc->mPercent);
     840             : }
     841             : 
     842             : /* static */ nscoord
     843        8317 : nsRuleNode::ComputeCoordPercentCalc(const nsStyleCoord& aCoord,
     844             :                                     nscoord aPercentageBasis)
     845             : {
     846        8317 :   switch (aCoord.GetUnit()) {
     847             :     case eStyleUnit_Coord:
     848        8069 :       return aCoord.GetCoordValue();
     849             :     case eStyleUnit_Percent:
     850          20 :       return NSToCoordFloorClamped(aPercentageBasis * aCoord.GetPercentValue());
     851             :     case eStyleUnit_Calc:
     852         228 :       return ComputeComputedCalc(aCoord, aPercentageBasis);
     853             :     default:
     854           0 :       MOZ_ASSERT(false, "unexpected unit");
     855             :       return 0;
     856             :   }
     857             : }
     858             : 
     859             : /* Given an enumerated value that represents a box position, converts it to
     860             :  * a float representing the percentage of the box it corresponds to.  For
     861             :  * example, "center" becomes 0.5f.
     862             :  *
     863             :  * @param aEnumValue The enumerated value.
     864             :  * @return The float percent it corresponds to.
     865             :  */
     866             : static float
     867          18 : GetFloatFromBoxPosition(int32_t aEnumValue)
     868             : {
     869          18 :   switch (aEnumValue) {
     870             :   case NS_STYLE_IMAGELAYER_POSITION_LEFT:
     871             :   case NS_STYLE_IMAGELAYER_POSITION_TOP:
     872           3 :     return 0.0f;
     873             :   case NS_STYLE_IMAGELAYER_POSITION_RIGHT:
     874             :   case NS_STYLE_IMAGELAYER_POSITION_BOTTOM:
     875           2 :     return 1.0f;
     876             :   default:
     877           0 :     MOZ_FALLTHROUGH_ASSERT("unexpected box position value");
     878             :   case NS_STYLE_IMAGELAYER_POSITION_CENTER:
     879          13 :     return 0.5f;
     880             :   }
     881             : }
     882             : 
     883             : #define SETCOORD_NORMAL                 0x01   // N
     884             : #define SETCOORD_AUTO                   0x02   // A
     885             : #define SETCOORD_INHERIT                0x04   // H
     886             : #define SETCOORD_PERCENT                0x08   // P
     887             : #define SETCOORD_FACTOR                 0x10   // F
     888             : #define SETCOORD_LENGTH                 0x20   // L
     889             : #define SETCOORD_INTEGER                0x40   // I
     890             : #define SETCOORD_ENUMERATED             0x80   // E
     891             : #define SETCOORD_NONE                   0x100  // O
     892             : #define SETCOORD_INITIAL_ZERO           0x200
     893             : #define SETCOORD_INITIAL_AUTO           0x400
     894             : #define SETCOORD_INITIAL_NONE           0x800
     895             : #define SETCOORD_INITIAL_NORMAL         0x1000
     896             : #define SETCOORD_INITIAL_HALF           0x2000
     897             : #define SETCOORD_INITIAL_HUNDRED_PCT    0x00004000
     898             : #define SETCOORD_INITIAL_FACTOR_ONE     0x00008000
     899             : #define SETCOORD_INITIAL_FACTOR_ZERO    0x00010000
     900             : #define SETCOORD_CALC_LENGTH_ONLY       0x00020000
     901             : #define SETCOORD_CALC_CLAMP_NONNEGATIVE 0x00040000 // modifier for CALC_LENGTH_ONLY
     902             : #define SETCOORD_STORE_CALC             0x00080000
     903             : #define SETCOORD_BOX_POSITION           0x00100000 // exclusive with _ENUMERATED
     904             : #define SETCOORD_ANGLE                  0x00200000
     905             : #define SETCOORD_UNSET_INHERIT          0x00400000
     906             : #define SETCOORD_UNSET_INITIAL          0x00800000
     907             : 
     908             : #define SETCOORD_LP     (SETCOORD_LENGTH | SETCOORD_PERCENT)
     909             : #define SETCOORD_LH     (SETCOORD_LENGTH | SETCOORD_INHERIT)
     910             : #define SETCOORD_AH     (SETCOORD_AUTO | SETCOORD_INHERIT)
     911             : #define SETCOORD_LAH    (SETCOORD_AUTO | SETCOORD_LENGTH | SETCOORD_INHERIT)
     912             : #define SETCOORD_LPH    (SETCOORD_LP | SETCOORD_INHERIT)
     913             : #define SETCOORD_LPAH   (SETCOORD_LP | SETCOORD_AH)
     914             : #define SETCOORD_LPE    (SETCOORD_LP | SETCOORD_ENUMERATED)
     915             : #define SETCOORD_LPEH   (SETCOORD_LPE | SETCOORD_INHERIT)
     916             : #define SETCOORD_LPAEH  (SETCOORD_LPAH | SETCOORD_ENUMERATED)
     917             : #define SETCOORD_LPO    (SETCOORD_LP | SETCOORD_NONE)
     918             : #define SETCOORD_LPOH   (SETCOORD_LPH | SETCOORD_NONE)
     919             : #define SETCOORD_LPOEH  (SETCOORD_LPOH | SETCOORD_ENUMERATED)
     920             : #define SETCOORD_LE     (SETCOORD_LENGTH | SETCOORD_ENUMERATED)
     921             : #define SETCOORD_LEH    (SETCOORD_LE | SETCOORD_INHERIT)
     922             : #define SETCOORD_IA     (SETCOORD_INTEGER | SETCOORD_AUTO)
     923             : #define SETCOORD_LAE    (SETCOORD_LENGTH | SETCOORD_AUTO | SETCOORD_ENUMERATED)
     924             : 
     925             : // changes aCoord iff it returns true
     926       10782 : static bool SetCoord(const nsCSSValue& aValue, nsStyleCoord& aCoord,
     927             :                        const nsStyleCoord& aParentCoord,
     928             :                        int32_t aMask, GeckoStyleContext* aStyleContext,
     929             :                        nsPresContext* aPresContext,
     930             :                        RuleNodeCacheConditions& aConditions)
     931             : {
     932       10782 :   bool result = true;
     933       10782 :   if (aValue.GetUnit() == eCSSUnit_Null) {
     934        7659 :     result = false;
     935             :   }
     936        9082 :   else if ((((aMask & SETCOORD_LENGTH) != 0) &&
     937        6246 :             aValue.IsLengthUnit()) ||
     938        1200 :            (((aMask & SETCOORD_CALC_LENGTH_ONLY) != 0) &&
     939          56 :             aValue.IsCalcUnit())) {
     940             :     nscoord len = CalcLength(aValue, aStyleContext, aPresContext,
     941        1979 :                              aConditions);
     942        1979 :     if ((aMask & SETCOORD_CALC_CLAMP_NONNEGATIVE) && len < 0) {
     943           0 :       NS_ASSERTION(aValue.IsCalcUnit(),
     944             :                    "parser should have ensured no nonnegative lengths");
     945           0 :       len = 0;
     946             :     }
     947        1979 :     aCoord.SetCoordValue(len);
     948             :   }
     949        1935 :   else if (((aMask & SETCOORD_PERCENT) != 0) &&
     950         791 :            (aValue.GetUnit() == eCSSUnit_Percent)) {
     951         251 :     aCoord.SetPercentValue(aValue.GetPercentValue());
     952             :   }
     953         913 :   else if (((aMask & SETCOORD_INTEGER) != 0) &&
     954          20 :            (aValue.GetUnit() == eCSSUnit_Integer)) {
     955          15 :     aCoord.SetIntValue(aValue.GetIntValue(), eStyleUnit_Integer);
     956             :   }
     957         937 :   else if (((aMask & SETCOORD_ENUMERATED) != 0) &&
     958          59 :            (aValue.GetUnit() == eCSSUnit_Enumerated)) {
     959          14 :     aCoord.SetIntValue(aValue.GetIntValue(), eStyleUnit_Enumerated);
     960             :   }
     961         894 :   else if (((aMask & SETCOORD_BOX_POSITION) != 0) &&
     962          30 :            (aValue.GetUnit() == eCSSUnit_Enumerated)) {
     963           2 :     aCoord.SetPercentValue(GetFloatFromBoxPosition(aValue.GetIntValue()));
     964             :   }
     965        1220 :   else if (((aMask & SETCOORD_AUTO) != 0) &&
     966         358 :            (aValue.GetUnit() == eCSSUnit_Auto)) {
     967           5 :     aCoord.SetAutoValue();
     968             :   }
     969        2498 :   else if ((((aMask & SETCOORD_INHERIT) != 0) &&
     970        1714 :             aValue.GetUnit() == eCSSUnit_Inherit) ||
     971         710 :            (((aMask & SETCOORD_UNSET_INHERIT) != 0) &&
     972           7 :             aValue.GetUnit() == eCSSUnit_Unset)) {
     973         154 :     aCoord = aParentCoord;  // just inherit value from parent
     974         154 :     aConditions.SetUncacheable();
     975             :   }
     976         709 :   else if (((aMask & SETCOORD_NORMAL) != 0) &&
     977           6 :            (aValue.GetUnit() == eCSSUnit_Normal)) {
     978           6 :     aCoord.SetNormalValue();
     979             :   }
     980         778 :   else if (((aMask & SETCOORD_NONE) != 0) &&
     981          81 :            (aValue.GetUnit() == eCSSUnit_None)) {
     982          50 :     aCoord.SetNoneValue();
     983             :   }
     984        1152 :   else if (((aMask & SETCOORD_FACTOR) != 0) &&
     985         505 :            (aValue.GetUnit() == eCSSUnit_Number)) {
     986         505 :     aCoord.SetFactorValue(aValue.GetFloatValue());
     987             :   }
     988         269 :   else if (((aMask & SETCOORD_STORE_CALC) != 0) &&
     989         127 :            (aValue.IsCalcUnit())) {
     990             :     SpecifiedCalcToComputedCalc(aValue, aCoord, aStyleContext,
     991         127 :                                 aConditions);
     992             :   }
     993          30 :   else if (aValue.GetUnit() == eCSSUnit_Initial ||
     994          15 :            (aValue.GetUnit() == eCSSUnit_Unset &&
     995           0 :             ((aMask & SETCOORD_UNSET_INITIAL) != 0))) {
     996           0 :     if ((aMask & SETCOORD_INITIAL_AUTO) != 0) {
     997           0 :       aCoord.SetAutoValue();
     998             :     }
     999           0 :     else if ((aMask & SETCOORD_INITIAL_ZERO) != 0) {
    1000           0 :       aCoord.SetCoordValue(0);
    1001             :     }
    1002           0 :     else if ((aMask & SETCOORD_INITIAL_FACTOR_ZERO) != 0) {
    1003           0 :       aCoord.SetFactorValue(0.0f);
    1004             :     }
    1005           0 :     else if ((aMask & SETCOORD_INITIAL_NONE) != 0) {
    1006           0 :       aCoord.SetNoneValue();
    1007             :     }
    1008           0 :     else if ((aMask & SETCOORD_INITIAL_NORMAL) != 0) {
    1009           0 :       aCoord.SetNormalValue();
    1010             :     }
    1011           0 :     else if ((aMask & SETCOORD_INITIAL_HALF) != 0) {
    1012           0 :       aCoord.SetPercentValue(0.5f);
    1013             :     }
    1014           0 :     else if ((aMask & SETCOORD_INITIAL_HUNDRED_PCT) != 0) {
    1015           0 :       aCoord.SetPercentValue(1.0f);
    1016             :     }
    1017           0 :     else if ((aMask & SETCOORD_INITIAL_FACTOR_ONE) != 0) {
    1018           0 :       aCoord.SetFactorValue(1.0f);
    1019             :     }
    1020             :     else {
    1021           0 :       result = false;  // didn't set anything
    1022             :     }
    1023             :   }
    1024          30 :   else if ((aMask & SETCOORD_ANGLE) != 0 &&
    1025          15 :            (aValue.IsAngularUnit())) {
    1026             :     nsStyleUnit unit;
    1027           0 :     switch (aValue.GetUnit()) {
    1028           0 :       case eCSSUnit_Degree: unit = eStyleUnit_Degree; break;
    1029           0 :       case eCSSUnit_Grad:   unit = eStyleUnit_Grad; break;
    1030           0 :       case eCSSUnit_Radian: unit = eStyleUnit_Radian; break;
    1031           0 :       case eCSSUnit_Turn:   unit = eStyleUnit_Turn; break;
    1032           0 :       default: NS_NOTREACHED("unrecognized angular unit");
    1033           0 :         unit = eStyleUnit_Degree;
    1034             :     }
    1035           0 :     aCoord.SetAngleValue(aValue.GetAngleValue(), unit);
    1036             :   }
    1037             :   else {
    1038          15 :     result = false;  // didn't set anything
    1039             :   }
    1040       10782 :   return result;
    1041             : }
    1042             : 
    1043             : // This inline function offers a shortcut for SetCoord() by refusing to accept
    1044             : // SETCOORD_LENGTH, SETCOORD_INHERIT and SETCOORD_UNSET_* masks.
    1045           8 : static inline bool SetAbsCoord(const nsCSSValue& aValue,
    1046             :                                  nsStyleCoord& aCoord,
    1047             :                                  int32_t aMask)
    1048             : {
    1049           8 :   MOZ_ASSERT((aMask & (SETCOORD_LH | SETCOORD_UNSET_INHERIT |
    1050             :                        SETCOORD_UNSET_INITIAL)) == 0,
    1051             :              "does not handle SETCOORD_LENGTH, SETCOORD_INHERIT and "
    1052             :              "SETCOORD_UNSET_*");
    1053             : 
    1054             :   // The values of the following variables will never be used; so it does not
    1055             :   // matter what to set.
    1056          16 :   const nsStyleCoord dummyParentCoord;
    1057           8 :   GeckoStyleContext* dummyStyleContext = nullptr;
    1058           8 :   nsPresContext* dummyPresContext = nullptr;
    1059           8 :   RuleNodeCacheConditions dummyCacheKey;
    1060             : 
    1061             :   bool rv = SetCoord(aValue, aCoord, dummyParentCoord, aMask,
    1062             :                        dummyStyleContext, dummyPresContext,
    1063           8 :                        dummyCacheKey);
    1064           8 :   MOZ_ASSERT(dummyCacheKey.CacheableWithoutDependencies(),
    1065             :              "SetCoord() should not modify dummyCacheKey.");
    1066             : 
    1067          16 :   return rv;
    1068             : }
    1069             : 
    1070             : /* Given a specified value that might be a pair value, call SetCoord twice,
    1071             :  * either using each member of the pair, or using the unpaired value twice.
    1072             :  */
    1073             : static bool
    1074         748 : SetPairCoords(const nsCSSValue& aValue,
    1075             :               nsStyleCoord& aCoordX, nsStyleCoord& aCoordY,
    1076             :               const nsStyleCoord& aParentX, const nsStyleCoord& aParentY,
    1077             :               int32_t aMask, GeckoStyleContext* aStyleContext,
    1078             :               nsPresContext* aPresContext, RuleNodeCacheConditions& aConditions)
    1079             : {
    1080             :   const nsCSSValue& valX =
    1081         748 :     aValue.GetUnit() == eCSSUnit_Pair ? aValue.GetPairValue().mXValue : aValue;
    1082             :   const nsCSSValue& valY =
    1083         748 :     aValue.GetUnit() == eCSSUnit_Pair ? aValue.GetPairValue().mYValue : aValue;
    1084             : 
    1085             :   bool cX = SetCoord(valX, aCoordX, aParentX, aMask, aStyleContext,
    1086         748 :                        aPresContext, aConditions);
    1087        1496 :   mozilla::DebugOnly<bool> cY = SetCoord(valY, aCoordY, aParentY, aMask,
    1088        1496 :                        aStyleContext, aPresContext, aConditions);
    1089         748 :   MOZ_ASSERT(cX == cY, "changed one but not the other");
    1090        1496 :   return cX;
    1091             : }
    1092             : 
    1093         627 : static bool SetColor(const nsCSSValue& aValue, const nscolor aParentColor,
    1094             :                        nsPresContext* aPresContext, nsStyleContext *aContext,
    1095             :                        nscolor& aResult, RuleNodeCacheConditions& aConditions)
    1096             : {
    1097         627 :   bool    result = false;
    1098         627 :   nsCSSUnit unit = aValue.GetUnit();
    1099             : 
    1100         627 :   if (aValue.IsNumericColorUnit()) {
    1101         258 :     aResult = aValue.GetColorValue();
    1102         258 :     result = true;
    1103             :   }
    1104         369 :   else if (eCSSUnit_Ident == unit) {
    1105         266 :     nsAutoString  value;
    1106         133 :     aValue.GetStringValue(value);
    1107             :     nscolor rgba;
    1108         133 :     if (NS_ColorNameToRGB(value, &rgba)) {
    1109         133 :       aResult = rgba;
    1110         133 :       result = true;
    1111             :     }
    1112             :   }
    1113         236 :   else if (eCSSUnit_EnumColor == unit) {
    1114          81 :     int32_t intValue = aValue.GetIntValue();
    1115          81 :     if (0 <= intValue) {
    1116          78 :       LookAndFeel::ColorID colorID = (LookAndFeel::ColorID) intValue;
    1117         156 :       bool useStandinsForNativeColors = aPresContext &&
    1118         156 :                                         !aPresContext->IsChrome();
    1119             :       DebugOnly<nsresult> rv =
    1120         156 :         LookAndFeel::GetColor(colorID, useStandinsForNativeColors, &aResult);
    1121          78 :       MOZ_ASSERT(NS_SUCCEEDED(rv),
    1122             :                  "Unknown enum colors should have been rejected by parser");
    1123          78 :       result = true;
    1124             :     }
    1125             :     else {
    1126           3 :       aResult = NS_RGB(0, 0, 0);
    1127           3 :       result = false;
    1128           3 :       switch (intValue) {
    1129             :         case NS_COLOR_MOZ_HYPERLINKTEXT:
    1130           0 :           if (aPresContext) {
    1131           0 :             aResult = aPresContext->DefaultLinkColor();
    1132           0 :             result = true;
    1133             :           }
    1134           0 :           break;
    1135             :         case NS_COLOR_MOZ_VISITEDHYPERLINKTEXT:
    1136           0 :           if (aPresContext) {
    1137           0 :             aResult = aPresContext->DefaultVisitedLinkColor();
    1138           0 :             result = true;
    1139             :           }
    1140           0 :           break;
    1141             :         case NS_COLOR_MOZ_ACTIVEHYPERLINKTEXT:
    1142           0 :           if (aPresContext) {
    1143           0 :             aResult = aPresContext->DefaultActiveLinkColor();
    1144           0 :             result = true;
    1145             :           }
    1146           0 :           break;
    1147             :         case NS_COLOR_CURRENTCOLOR:
    1148             :           // The data computed from this can't be shared in the rule tree
    1149             :           // because they could be used on a node with a different color
    1150           3 :           aConditions.SetUncacheable();
    1151           3 :           if (aContext) {
    1152           3 :             aResult = aContext->StyleColor()->mColor;
    1153           3 :             result = true;
    1154             :           }
    1155           3 :           break;
    1156             :         case NS_COLOR_MOZ_DEFAULT_COLOR:
    1157           0 :           if (aPresContext) {
    1158           0 :             aResult = aPresContext->DefaultColor();
    1159           0 :             result = true;
    1160             :           }
    1161           0 :           break;
    1162             :         case NS_COLOR_MOZ_DEFAULT_BACKGROUND_COLOR:
    1163           0 :           if (aPresContext) {
    1164           0 :             aResult = aPresContext->DefaultBackgroundColor();
    1165           0 :             result = true;
    1166             :           }
    1167           0 :           break;
    1168             :         default:
    1169           0 :           NS_NOTREACHED("Should never have an unknown negative colorID.");
    1170           0 :           break;
    1171             :       }
    1172             :     }
    1173             :   }
    1174         155 :   else if (eCSSUnit_Inherit == unit) {
    1175           0 :     aResult = aParentColor;
    1176           0 :     result = true;
    1177           0 :     aConditions.SetUncacheable();
    1178             :   }
    1179         155 :   else if (eCSSUnit_Enumerated == unit &&
    1180           0 :            aValue.GetIntValue() == NS_STYLE_COLOR_INHERIT_FROM_BODY) {
    1181           0 :     NS_ASSERTION(aPresContext->CompatibilityMode() == eCompatibility_NavQuirks,
    1182             :                  "Should only get this value in quirks mode");
    1183             :     // We just grab the color from the prescontext, and rely on the fact that
    1184             :     // if the body color ever changes all its descendants will get new style
    1185             :     // contexts (but NOT necessarily new rulenodes).
    1186           0 :     aResult = aPresContext->BodyTextColor();
    1187           0 :     result = true;
    1188           0 :     aConditions.SetUncacheable();
    1189             :   }
    1190         627 :   return result;
    1191             : }
    1192             : 
    1193             : template<UnsetAction UnsetTo>
    1194             : static void
    1195        2649 : SetComplexColor(const nsCSSValue& aValue,
    1196             :                 const StyleComplexColor& aParentColor,
    1197             :                 const StyleComplexColor& aInitialColor,
    1198             :                 nsPresContext* aPresContext,
    1199             :                 StyleComplexColor& aResult,
    1200             :                 RuleNodeCacheConditions& aConditions)
    1201             : {
    1202        2649 :   nsCSSUnit unit = aValue.GetUnit();
    1203        2649 :   if (unit == eCSSUnit_Null) {
    1204        2199 :     return;
    1205             :   }
    1206         450 :   if (unit == eCSSUnit_Initial ||
    1207             :       (UnsetTo == eUnsetInitial && unit == eCSSUnit_Unset)) {
    1208           0 :     aResult = aInitialColor;
    1209         450 :   } else if (unit == eCSSUnit_Inherit ||
    1210             :              (UnsetTo == eUnsetInherit && unit == eCSSUnit_Unset)) {
    1211         143 :     aConditions.SetUncacheable();
    1212         143 :     aResult = aParentColor;
    1213         459 :   } else if (unit == eCSSUnit_EnumColor &&
    1214         152 :              aValue.GetIntValue() == NS_COLOR_CURRENTCOLOR) {
    1215          88 :     aResult = StyleComplexColor::CurrentColor();
    1216         219 :   } else if (unit == eCSSUnit_ComplexColor) {
    1217           0 :     aResult = aValue.GetStyleComplexColorValue();
    1218         219 :   } else if (unit == eCSSUnit_Auto) {
    1219           0 :     aResult = StyleComplexColor::Auto();
    1220             :   } else {
    1221             :     nscolor resultColor;
    1222         219 :     if (!SetColor(aValue, aParentColor.mColor, aPresContext,
    1223             :                   nullptr, resultColor, aConditions)) {
    1224           0 :       MOZ_ASSERT_UNREACHABLE("Unknown color value");
    1225             :       return;
    1226             :     }
    1227         219 :     aResult = StyleComplexColor::FromColor(resultColor);
    1228             :   }
    1229             : }
    1230             : 
    1231             : template<UnsetAction UnsetTo>
    1232             : static Maybe<nscoord>
    1233         748 : ComputeLineWidthValue(const nsCSSValue& aValue,
    1234             :                       const nscoord aParentCoord,
    1235             :                       const nscoord aInitialCoord,
    1236             :                       GeckoStyleContext* aStyleContext,
    1237             :                       nsPresContext* aPresContext,
    1238             :                       RuleNodeCacheConditions& aConditions)
    1239             : {
    1240         748 :   nsCSSUnit unit = aValue.GetUnit();
    1241         748 :   if (unit == eCSSUnit_Initial ||
    1242             :       (UnsetTo == eUnsetInitial && unit == eCSSUnit_Unset)) {
    1243           0 :     return Some(aInitialCoord);
    1244         748 :   } else if (unit == eCSSUnit_Inherit ||
    1245             :              (UnsetTo == eUnsetInherit && unit == eCSSUnit_Unset)) {
    1246          25 :     aConditions.SetUncacheable();
    1247          25 :     return Some(aParentCoord);
    1248         723 :   } else if (unit == eCSSUnit_Enumerated) {
    1249          58 :     NS_ASSERTION(aValue.GetIntValue() == NS_STYLE_BORDER_WIDTH_THIN ||
    1250             :                  aValue.GetIntValue() == NS_STYLE_BORDER_WIDTH_MEDIUM ||
    1251             :                  aValue.GetIntValue() == NS_STYLE_BORDER_WIDTH_THICK,
    1252             :                  "Unexpected line-width keyword!");
    1253          58 :     return Some(nsPresContext::GetBorderWidthForKeyword(aValue.GetIntValue()));
    1254        1106 :   } else if (aValue.IsLengthUnit() ||
    1255         441 :              aValue.IsCalcUnit()) {
    1256             :     nscoord len =
    1257         224 :       CalcLength(aValue, aStyleContext, aPresContext, aConditions);
    1258         224 :     if (len < 0) {
    1259           0 :       NS_ASSERTION(aValue.IsCalcUnit(),
    1260             :                    "Parser should have rejected negative length!");
    1261           0 :       len = 0;
    1262             :     }
    1263         224 :     return Some(len);
    1264             :   } else {
    1265         441 :     NS_ASSERTION(unit == eCSSUnit_Null,
    1266             :                  "Missing case handling for line-width computing!");
    1267         441 :     return Maybe<nscoord>(Nothing());
    1268             :   }
    1269             : }
    1270             : 
    1271          30 : static void SetGradientCoord(const nsCSSValue& aValue, nsPresContext* aPresContext,
    1272             :                              GeckoStyleContext* aContext, nsStyleCoord& aResult,
    1273             :                              RuleNodeCacheConditions& aConditions)
    1274             : {
    1275             :   // OK to pass bad aParentCoord since we're not passing SETCOORD_INHERIT
    1276          30 :   if (!SetCoord(aValue, aResult, nsStyleCoord(),
    1277             :                 SETCOORD_LPO | SETCOORD_BOX_POSITION | SETCOORD_STORE_CALC,
    1278             :                 aContext, aPresContext, aConditions)) {
    1279           0 :     NS_NOTREACHED("unexpected unit for gradient anchor point");
    1280           0 :     aResult.SetNoneValue();
    1281             :   }
    1282          30 : }
    1283             : 
    1284          15 : static void SetGradient(const nsCSSValue& aValue, nsPresContext* aPresContext,
    1285             :                         GeckoStyleContext* aContext, nsStyleGradient& aResult,
    1286             :                         RuleNodeCacheConditions& aConditions)
    1287             : {
    1288          15 :   MOZ_ASSERT(aValue.GetUnit() == eCSSUnit_Gradient,
    1289             :              "The given data is not a gradient");
    1290             : 
    1291          15 :   const nsCSSValueGradient* gradient = aValue.GetGradientValue();
    1292             : 
    1293          15 :   if (gradient->mIsExplicitSize) {
    1294           0 :     SetCoord(gradient->GetRadiusX(), aResult.mRadiusX, nsStyleCoord(),
    1295             :              SETCOORD_LP | SETCOORD_STORE_CALC,
    1296           0 :              aContext, aPresContext, aConditions);
    1297           0 :     if (gradient->GetRadiusY().GetUnit() != eCSSUnit_None) {
    1298           0 :       SetCoord(gradient->GetRadiusY(), aResult.mRadiusY, nsStyleCoord(),
    1299             :                SETCOORD_LP | SETCOORD_STORE_CALC,
    1300           0 :                aContext, aPresContext, aConditions);
    1301           0 :       aResult.mShape = NS_STYLE_GRADIENT_SHAPE_ELLIPTICAL;
    1302             :     } else {
    1303           0 :       aResult.mRadiusY = aResult.mRadiusX;
    1304           0 :       aResult.mShape = NS_STYLE_GRADIENT_SHAPE_CIRCULAR;
    1305             :     }
    1306           0 :     aResult.mSize = NS_STYLE_GRADIENT_SIZE_EXPLICIT_SIZE;
    1307          15 :   } else if (gradient->mIsRadial) {
    1308           0 :     if (gradient->GetRadialShape().GetUnit() == eCSSUnit_Enumerated) {
    1309           0 :       aResult.mShape = gradient->GetRadialShape().GetIntValue();
    1310             :     } else {
    1311           0 :       NS_ASSERTION(gradient->GetRadialShape().GetUnit() == eCSSUnit_None,
    1312             :                    "bad unit for radial shape");
    1313           0 :       aResult.mShape = NS_STYLE_GRADIENT_SHAPE_ELLIPTICAL;
    1314             :     }
    1315           0 :     if (gradient->GetRadialSize().GetUnit() == eCSSUnit_Enumerated) {
    1316           0 :       aResult.mSize = gradient->GetRadialSize().GetIntValue();
    1317             :     } else {
    1318           0 :       NS_ASSERTION(gradient->GetRadialSize().GetUnit() == eCSSUnit_None,
    1319             :                    "bad unit for radial shape");
    1320           0 :       aResult.mSize = NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER;
    1321             :     }
    1322             :   } else {
    1323          15 :     NS_ASSERTION(gradient->GetRadialShape().GetUnit() == eCSSUnit_None,
    1324             :                  "bad unit for linear shape");
    1325          15 :     NS_ASSERTION(gradient->GetRadialSize().GetUnit() == eCSSUnit_None,
    1326             :                  "bad unit for linear size");
    1327          15 :     aResult.mShape = NS_STYLE_GRADIENT_SHAPE_LINEAR;
    1328          15 :     aResult.mSize = NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER;
    1329             :   }
    1330             : 
    1331          15 :   aResult.mLegacySyntax = gradient->mIsLegacySyntax;
    1332          15 :   aResult.mMozLegacySyntax = gradient->mIsMozLegacySyntax;
    1333             : 
    1334             :   // bg-position
    1335          15 :   SetGradientCoord(gradient->mBgPos.mXValue, aPresContext, aContext,
    1336          15 :                    aResult.mBgPosX, aConditions);
    1337             : 
    1338          15 :   SetGradientCoord(gradient->mBgPos.mYValue, aPresContext, aContext,
    1339          15 :                    aResult.mBgPosY, aConditions);
    1340             : 
    1341          15 :   aResult.mRepeating = gradient->mIsRepeating;
    1342             : 
    1343             :   // angle
    1344          30 :   const nsStyleCoord dummyParentCoord;
    1345          15 :   if (!SetCoord(gradient->mAngle, aResult.mAngle, dummyParentCoord, SETCOORD_ANGLE,
    1346             :                 aContext, aPresContext, aConditions)) {
    1347          15 :     NS_ASSERTION(gradient->mAngle.GetUnit() == eCSSUnit_None,
    1348             :                  "bad unit for gradient angle");
    1349          15 :     aResult.mAngle.SetNoneValue();
    1350             :   }
    1351             : 
    1352             :   // stops
    1353          56 :   for (uint32_t i = 0; i < gradient->mStops.Length(); i++) {
    1354          82 :     nsStyleGradientStop stop;
    1355          41 :     const nsCSSValueGradientStop &valueStop = gradient->mStops[i];
    1356             : 
    1357          82 :     if (!SetCoord(valueStop.mLocation, stop.mLocation,
    1358          82 :                   nsStyleCoord(), SETCOORD_LPO | SETCOORD_STORE_CALC,
    1359             :                   aContext, aPresContext, aConditions)) {
    1360           0 :       NS_NOTREACHED("unexpected unit for gradient stop location");
    1361             :     }
    1362             : 
    1363          41 :     stop.mIsInterpolationHint = valueStop.mIsInterpolationHint;
    1364             : 
    1365             :     // inherit is not a valid color for stops, so we pass in a dummy
    1366             :     // parent color
    1367          41 :     NS_ASSERTION(valueStop.mColor.GetUnit() != eCSSUnit_Inherit,
    1368             :                  "inherit is not a valid color for gradient stops");
    1369          41 :     if (!valueStop.mIsInterpolationHint) {
    1370          41 :       SetColor(valueStop.mColor, NS_RGB(0, 0, 0), aPresContext,
    1371          41 :               aContext, stop.mColor, aConditions);
    1372             :     } else {
    1373             :       // Always initialize to the same color so we don't need to worry
    1374             :       // about comparisons.
    1375           0 :       stop.mColor = NS_RGB(0, 0, 0);
    1376             :     }
    1377             : 
    1378          41 :     aResult.mStops.AppendElement(stop);
    1379             :   }
    1380          15 : }
    1381             : 
    1382             : // -moz-image-rect(<uri>, <top>, <right>, <bottom>, <left>)
    1383           2 : static void SetStyleImageToImageRect(GeckoStyleContext* aStyleContext,
    1384             :                                      const nsCSSValue& aValue,
    1385             :                                      nsStyleImage& aResult)
    1386             : {
    1387           2 :   MOZ_ASSERT(aValue.GetUnit() == eCSSUnit_Function &&
    1388             :              aValue.EqualsFunction(eCSSKeyword__moz_image_rect),
    1389             :              "the value is not valid -moz-image-rect()");
    1390             : 
    1391           2 :   nsCSSValue::Array* arr = aValue.GetArrayValue();
    1392           2 :   MOZ_ASSERT(arr && arr->Count() == 6, "invalid number of arguments");
    1393             : 
    1394             :   // <uri>
    1395           2 :   if (arr->Item(1).GetUnit() == eCSSUnit_Image) {
    1396           2 :     nsPresContext* pc = aStyleContext->PresContext();
    1397           2 :     aResult.SetImageRequest(CreateStyleImageRequest(pc, arr->Item(1)));
    1398             :   } else {
    1399           0 :     NS_WARNING("nsCSSValue::Image::Image() failed?");
    1400             :   }
    1401             : 
    1402             :   // <top>, <right>, <bottom>, <left>
    1403           4 :   nsStyleSides cropRect;
    1404          10 :   NS_FOR_CSS_SIDES(side) {
    1405          16 :     nsStyleCoord coord;
    1406           8 :     const nsCSSValue& val = arr->Item(2 + side);
    1407             : 
    1408             : #ifdef DEBUG
    1409             :     bool unitOk =
    1410             : #endif
    1411           8 :       SetAbsCoord(val, coord, SETCOORD_FACTOR | SETCOORD_PERCENT);
    1412           8 :     MOZ_ASSERT(unitOk, "Incorrect data structure created by CSS parser");
    1413           8 :     cropRect.Set(side, coord);
    1414             :   }
    1415           2 :   aResult.SetCropRect(MakeUnique<nsStyleSides>(cropRect));
    1416           2 : }
    1417             : 
    1418         208 : static void SetStyleImage(GeckoStyleContext* aStyleContext,
    1419             :                           const nsCSSValue& aValue,
    1420             :                           nsStyleImage& aResult,
    1421             :                           RuleNodeCacheConditions& aConditions)
    1422             : {
    1423         208 :   if (aValue.GetUnit() == eCSSUnit_Null) {
    1424         100 :     return;
    1425             :   }
    1426             : 
    1427         108 :   aResult.SetNull();
    1428             : 
    1429         108 :   nsPresContext* presContext = aStyleContext->PresContext();
    1430         108 :   switch (aValue.GetUnit()) {
    1431             :     case eCSSUnit_Image:
    1432          22 :       aResult.SetImageRequest(CreateStyleImageRequest(presContext, aValue));
    1433          22 :       break;
    1434             :     case eCSSUnit_Function:
    1435           2 :       if (aValue.EqualsFunction(eCSSKeyword__moz_image_rect)) {
    1436           2 :         SetStyleImageToImageRect(aStyleContext, aValue, aResult);
    1437             :       } else {
    1438           0 :         NS_NOTREACHED("-moz-image-rect() is the only expected function");
    1439             :       }
    1440           2 :       break;
    1441             :     case eCSSUnit_Gradient:
    1442             :     {
    1443          15 :       nsStyleGradient* gradient = new nsStyleGradient();
    1444          15 :       SetGradient(aValue, presContext, aStyleContext, *gradient, aConditions);
    1445          15 :       aResult.SetGradientData(gradient);
    1446          15 :       break;
    1447             :     }
    1448             :     case eCSSUnit_Element:
    1449             :     {
    1450           0 :       nsCOMPtr<nsIAtom> atom = NS_Atomize(aValue.GetStringBufferValue());
    1451           0 :       aResult.SetElementId(atom.forget());
    1452           0 :       break;
    1453             :     }
    1454             :     case eCSSUnit_Initial:
    1455             :     case eCSSUnit_Unset:
    1456             :     case eCSSUnit_None:
    1457          68 :       break;
    1458             :     case eCSSUnit_URL:
    1459             :     {
    1460             : #ifdef DEBUG
    1461             :       // eCSSUnit_URL is expected only if
    1462             :       // 1. we have eCSSUnit_URL values for if-visited style contexts, which
    1463             :       //    we can safely treat like 'none'.
    1464             :       // 2. aValue is a local-ref URL, e.g. url(#foo).
    1465             :       // 3. aValue is a not a local-ref URL, but it refers to an element in
    1466             :       //    the current document. For example, the url of the current document
    1467             :       //    is "http://foo.html" and aValue is url(http://foo.html#foo).
    1468             :       //
    1469             :       // We skip image download in TryToStartImageLoadOnValue under #2 and #3,
    1470             :       // and that's part of reasons we get eCSSUnit_URL instead of
    1471             :       // eCSSUnit_Image here.
    1472             : 
    1473             :       // Check #2.
    1474           1 :       bool isLocalRef = aValue.GetURLStructValue()->IsLocalRef();
    1475             : 
    1476             :       // Check #3.
    1477           1 :       bool isEqualExceptRef = false;
    1478           1 :       if (!isLocalRef) {
    1479           0 :         nsIDocument* currentDoc = presContext->Document();
    1480           0 :         nsIURI* docURI = currentDoc->GetDocumentURI();
    1481           0 :         nsIURI* imageURI = aValue.GetURLValue();
    1482           0 :         imageURI->EqualsExceptRef(docURI, &isEqualExceptRef);
    1483             :       }
    1484             : 
    1485           1 :       MOZ_ASSERT(aStyleContext->IsStyleIfVisited() || isEqualExceptRef ||
    1486             :                  isLocalRef,
    1487             :                  "unexpected unit; maybe nsCSSValue::Image::Image() failed?");
    1488             : #endif
    1489           1 :       aResult.SetURLValue(do_AddRef(aValue.GetURLStructValue()));
    1490           1 :       break;
    1491             :     }
    1492             :     default:
    1493           0 :       MOZ_ASSERT_UNREACHABLE("Unexpected Unit type.");
    1494             :       break;
    1495             :   }
    1496             : }
    1497             : 
    1498             : struct SetEnumValueHelper
    1499             : {
    1500             :   template<typename FieldT>
    1501           0 :   static void SetIntegerValue(FieldT&, const nsCSSValue&)
    1502             :   {
    1503             :     // FIXME Is it possible to turn this assertion into a compilation error?
    1504           0 :     MOZ_ASSERT_UNREACHABLE("inappropriate unit");
    1505             :   }
    1506             : 
    1507             : #define DEFINE_ENUM_CLASS_SETTER(type_, min_, max_) \
    1508             :   static void SetEnumeratedValue(type_& aField, const nsCSSValue& aValue) \
    1509             :   { \
    1510             :     auto value = aValue.GetIntValue(); \
    1511             :     MOZ_ASSERT(value >= static_cast<decltype(value)>(type_::min_) && \
    1512             :                value <= static_cast<decltype(value)>(type_::max_), \
    1513             :                "inappropriate value"); \
    1514             :     aField = static_cast<type_>(value); \
    1515             :   }
    1516             : 
    1517          32 :   DEFINE_ENUM_CLASS_SETTER(StyleBoxAlign, Stretch, End)
    1518           0 :   DEFINE_ENUM_CLASS_SETTER(StyleBoxDecorationBreak, Slice, Clone)
    1519           0 :   DEFINE_ENUM_CLASS_SETTER(StyleBoxDirection, Normal, Reverse)
    1520          20 :   DEFINE_ENUM_CLASS_SETTER(StyleBoxOrient, Horizontal, Vertical)
    1521          37 :   DEFINE_ENUM_CLASS_SETTER(StyleBoxPack, Start, Justify)
    1522          12 :   DEFINE_ENUM_CLASS_SETTER(StyleBoxSizing, Content, Border)
    1523           0 :   DEFINE_ENUM_CLASS_SETTER(StyleClear, None, Both)
    1524           1 :   DEFINE_ENUM_CLASS_SETTER(StyleFillRule, Nonzero, Evenodd)
    1525          76 :   DEFINE_ENUM_CLASS_SETTER(StyleFloat, None, InlineEnd)
    1526           0 :   DEFINE_ENUM_CLASS_SETTER(StyleFloatEdge, ContentBox, MarginBox)
    1527           0 :   DEFINE_ENUM_CLASS_SETTER(StyleHyphens, None, Auto)
    1528           0 :   DEFINE_ENUM_CLASS_SETTER(StyleStackSizing, Ignore, IgnoreVertical)
    1529           0 :   DEFINE_ENUM_CLASS_SETTER(StyleTextJustify, None, InterCharacter)
    1530        1470 :   DEFINE_ENUM_CLASS_SETTER(StyleUserFocus, None, SelectMenu)
    1531           4 :   DEFINE_ENUM_CLASS_SETTER(StyleUserSelect, None, MozText)
    1532           0 :   DEFINE_ENUM_CLASS_SETTER(StyleUserInput, None, Auto)
    1533           6 :   DEFINE_ENUM_CLASS_SETTER(StyleUserModify, ReadOnly, WriteOnly)
    1534           2 :   DEFINE_ENUM_CLASS_SETTER(StyleWindowDragging, Default, NoDrag)
    1535           0 :   DEFINE_ENUM_CLASS_SETTER(StyleOrient, Inline, Vertical)
    1536           0 :   DEFINE_ENUM_CLASS_SETTER(StyleGeometryBox, BorderBox, ViewBox)
    1537          19 :   DEFINE_ENUM_CLASS_SETTER(StyleWhiteSpace, Normal, PreSpace)
    1538             : #ifdef MOZ_XUL
    1539         357 :   DEFINE_ENUM_CLASS_SETTER(StyleDisplay, None, MozPopup)
    1540             : #else
    1541             :   DEFINE_ENUM_CLASS_SETTER(StyleDisplay, None, InlineBox)
    1542             : #endif
    1543             : 
    1544             : #undef DEF_SET_ENUMERATED_VALUE
    1545             : };
    1546             : 
    1547             : template<typename FieldT>
    1548             : struct SetIntegerValueHelper
    1549             : {
    1550           4 :   static void SetIntegerValue(FieldT& aField, const nsCSSValue& aValue)
    1551             :   {
    1552           4 :     aField = aValue.GetIntValue();
    1553           4 :   }
    1554         844 :   static void SetEnumeratedValue(FieldT& aField, const nsCSSValue& aValue)
    1555             :   {
    1556         844 :     aField = aValue.GetIntValue();
    1557         844 :   }
    1558             : };
    1559             : 
    1560             : template<typename FieldT>
    1561             : struct SetValueHelper : Conditional<IsEnum<FieldT>::value,
    1562             :                                     SetEnumValueHelper,
    1563             :                                     SetIntegerValueHelper<FieldT>>::Type
    1564             : {
    1565             :   template<typename ValueT>
    1566         115 :   static void SetValue(FieldT& aField, const ValueT& aValue)
    1567             :   {
    1568         115 :     aField = aValue;
    1569         115 :   }
    1570           0 :   static void SetValue(FieldT&, unused_t)
    1571             :   {
    1572             :     // FIXME Is it possible to turn this assertion into a compilation error?
    1573           0 :     MOZ_ASSERT_UNREACHABLE("inappropriate unit");
    1574             :   }
    1575             : };
    1576             : 
    1577             : 
    1578             : // flags for SetValue - align values with SETCOORD_* constants
    1579             : // where possible
    1580             : 
    1581             : #define SETVAL_INTEGER                0x40   // I
    1582             : #define SETVAL_ENUMERATED             0x80   // E
    1583             : #define SETVAL_UNSET_INHERIT          0x00400000
    1584             : #define SETVAL_UNSET_INITIAL          0x00800000
    1585             : 
    1586             : // no caller cares whether aField was changed or not
    1587             : template<typename FieldT, typename InitialT,
    1588             :          typename AutoT, typename NoneT, typename NormalT, typename SysFontT>
    1589             : static void
    1590       27615 : SetValue(const nsCSSValue& aValue, FieldT& aField,
    1591             :          RuleNodeCacheConditions& aConditions, uint32_t aMask,
    1592             :          FieldT aParentValue,
    1593             :          InitialT aInitialValue,
    1594             :          AutoT aAutoValue,
    1595             :          NoneT aNoneValue,
    1596             :          NormalT aNormalValue,
    1597             :          SysFontT aSystemFontValue)
    1598             : {
    1599             :   typedef SetValueHelper<FieldT> Helper;
    1600             : 
    1601       27615 :   switch (aValue.GetUnit()) {
    1602             :   case eCSSUnit_Null:
    1603       23980 :     return;
    1604             : 
    1605             :     // every caller of SetValue provides inherit and initial
    1606             :     // alternatives, so we don't require them to say so in the mask
    1607             :   case eCSSUnit_Inherit:
    1608         636 :     aConditions.SetUncacheable();
    1609         636 :     aField = aParentValue;
    1610         636 :     return;
    1611             : 
    1612             :   case eCSSUnit_Initial:
    1613          61 :     Helper::SetValue(aField, aInitialValue);
    1614          61 :     return;
    1615             : 
    1616             :     // every caller provides one or other of these alternatives,
    1617             :     // but they have to say which
    1618             :   case eCSSUnit_Enumerated:
    1619        2880 :     if (aMask & SETVAL_ENUMERATED) {
    1620        2880 :       Helper::SetEnumeratedValue(aField, aValue);
    1621        2880 :       return;
    1622             :     }
    1623           0 :     break;
    1624             : 
    1625             :   case eCSSUnit_Integer:
    1626           4 :     if (aMask & SETVAL_INTEGER) {
    1627           4 :       Helper::SetIntegerValue(aField, aValue);
    1628           4 :       return;
    1629             :     }
    1630           0 :     break;
    1631             : 
    1632             :     // remaining possibilities in descending order of frequency of use
    1633             :   case eCSSUnit_Auto:
    1634           0 :     Helper::SetValue(aField, aAutoValue);
    1635           0 :     return;
    1636             : 
    1637             :   case eCSSUnit_None:
    1638           0 :     Helper::SetValue(aField, aNoneValue);
    1639           0 :     return;
    1640             : 
    1641             :   case eCSSUnit_Normal:
    1642           0 :     Helper::SetValue(aField, aNormalValue);
    1643           0 :     return;
    1644             : 
    1645             :   case eCSSUnit_System_Font:
    1646          54 :     Helper::SetValue(aField, aSystemFontValue);
    1647          54 :     return;
    1648             : 
    1649             :   case eCSSUnit_Unset:
    1650           0 :     if (aMask & SETVAL_UNSET_INHERIT) {
    1651           0 :       aConditions.SetUncacheable();
    1652           0 :       aField = aParentValue;
    1653           0 :       return;
    1654             :     }
    1655           0 :     if (aMask & SETVAL_UNSET_INITIAL) {
    1656           0 :       Helper::SetValue(aField, aInitialValue);
    1657           0 :       return;
    1658             :     }
    1659           0 :     break;
    1660             : 
    1661             :   default:
    1662           0 :     break;
    1663             :   }
    1664             : 
    1665           0 :   NS_NOTREACHED("SetValue: inappropriate unit");
    1666             : }
    1667             : 
    1668             : template <typename FieldT, typename T1>
    1669             : static void
    1670       26153 : SetValue(const nsCSSValue& aValue, FieldT& aField,
    1671             :          RuleNodeCacheConditions& aConditions, uint32_t aMask,
    1672             :          FieldT aParentValue, T1 aInitialValue)
    1673             : {
    1674       26153 :   SetValue(aValue, aField, aConditions, aMask, aParentValue,
    1675             :            aInitialValue, Unused, Unused, Unused, Unused);
    1676       26153 : }
    1677             : 
    1678             : // flags for SetFactor
    1679             : #define SETFCT_POSITIVE 0x01        // assert value is >= 0.0f
    1680             : #define SETFCT_OPACITY  0x02        // clamp value to [0.0f .. 1.0f]
    1681             : #define SETFCT_NONE     0x04        // allow _None (uses aInitialValue).
    1682             : #define SETFCT_UNSET_INHERIT  0x00400000
    1683             : #define SETFCT_UNSET_INITIAL  0x00800000
    1684             : 
    1685             : static void
    1686         968 : SetFactor(const nsCSSValue& aValue, float& aField, RuleNodeCacheConditions& aConditions,
    1687             :           float aParentValue, float aInitialValue, uint32_t aFlags = 0)
    1688             : {
    1689         968 :   switch (aValue.GetUnit()) {
    1690             :   case eCSSUnit_Null:
    1691         877 :     return;
    1692             : 
    1693             :   case eCSSUnit_Number:
    1694          85 :     aField = aValue.GetFloatValue();
    1695          85 :     if (aFlags & SETFCT_POSITIVE) {
    1696           0 :       NS_ASSERTION(aField >= 0.0f, "negative value for positive-only property");
    1697           0 :       if (aField < 0.0f)
    1698           0 :         aField = 0.0f;
    1699             :     }
    1700          85 :     if (aFlags & SETFCT_OPACITY) {
    1701          63 :       if (aField < 0.0f)
    1702           0 :         aField = 0.0f;
    1703          63 :       if (aField > 1.0f)
    1704           0 :         aField = 1.0f;
    1705             :     }
    1706          85 :     return;
    1707             : 
    1708             :   case eCSSUnit_Inherit:
    1709           6 :     aConditions.SetUncacheable();
    1710           6 :     aField = aParentValue;
    1711           6 :     return;
    1712             : 
    1713             :   case eCSSUnit_Initial:
    1714           0 :     aField = aInitialValue;
    1715           0 :     return;
    1716             : 
    1717             :   case eCSSUnit_None:
    1718           0 :     if (aFlags & SETFCT_NONE) {
    1719           0 :       aField = aInitialValue;
    1720           0 :       return;
    1721             :     }
    1722           0 :     break;
    1723             : 
    1724             :   case eCSSUnit_Unset:
    1725           0 :     if (aFlags & SETFCT_UNSET_INHERIT) {
    1726           0 :       aConditions.SetUncacheable();
    1727           0 :       aField = aParentValue;
    1728           0 :       return;
    1729             :     }
    1730           0 :     if (aFlags & SETFCT_UNSET_INITIAL) {
    1731           0 :       aField = aInitialValue;
    1732           0 :       return;
    1733             :     }
    1734           0 :     break;
    1735             : 
    1736             :   default:
    1737           0 :     break;
    1738             :   }
    1739             : 
    1740           0 :   NS_NOTREACHED("SetFactor: inappropriate unit");
    1741             : }
    1742             : 
    1743             : static void
    1744         680 : SetTransformValue(const nsCSSValue& aValue,
    1745             :                   RefPtr<nsCSSValueSharedList>& aField,
    1746             :                   RuleNodeCacheConditions& aConditions,
    1747             :                   nsCSSValueSharedList* const aParentValue)
    1748             : {
    1749             :   /* Convert the nsCSSValueList into an nsTArray<nsTransformFunction *>. */
    1750         680 :   switch (aValue.GetUnit()) {
    1751             :   case eCSSUnit_Null:
    1752         664 :     break;
    1753             : 
    1754             :   case eCSSUnit_Initial:
    1755             :   case eCSSUnit_Unset:
    1756             :   case eCSSUnit_None:
    1757           0 :     aField = nullptr;
    1758           0 :     break;
    1759             : 
    1760             :   case eCSSUnit_Inherit:
    1761           0 :     aField = aParentValue;
    1762           0 :     aConditions.SetUncacheable();
    1763           0 :     break;
    1764             : 
    1765             :   case eCSSUnit_SharedList: {
    1766          16 :     nsCSSValueSharedList* list = aValue.GetSharedListValue();
    1767          16 :     nsCSSValueList* head = list->mHead;
    1768          16 :     MOZ_ASSERT(head, "transform list must have at least one item");
    1769             :     // can get a _None in here from transform animation
    1770          16 :     if (head->mValue.GetUnit() == eCSSUnit_None) {
    1771           0 :       MOZ_ASSERT(head->mNext == nullptr, "none must be alone");
    1772           0 :       aField = nullptr;
    1773             :     } else {
    1774          16 :       aField = list;
    1775             :     }
    1776          16 :     break;
    1777             :   }
    1778             : 
    1779             :   default:
    1780           0 :     MOZ_ASSERT(false, "unrecognized transform unit");
    1781             :   }
    1782         680 : }
    1783             : 
    1784             : void*
    1785        2022 : nsRuleNode::operator new(size_t sz, nsPresContext* aPresContext)
    1786             : {
    1787             :   // Check the recycle list first.
    1788        2022 :   return aPresContext->PresShell()->AllocateByObjectID(eArenaObjectID_nsRuleNode, sz);
    1789             : }
    1790             : 
    1791             : // Overridden to prevent the global delete from being called, since the memory
    1792             : // came out of an nsIArena instead of the global delete operator's heap.
    1793             : void
    1794         946 : nsRuleNode::Destroy()
    1795             : {
    1796             :   // Destroy ourselves.
    1797         946 :   this->~nsRuleNode();
    1798             : 
    1799             :   // Don't let the memory be freed, since it will be recycled
    1800             :   // instead. Don't call the global operator delete.
    1801         946 :   mPresContext->PresShell()->FreeByObjectID(eArenaObjectID_nsRuleNode, this);
    1802         946 : }
    1803             : 
    1804             : already_AddRefed<nsRuleNode>
    1805          30 : nsRuleNode::CreateRootNode(nsPresContext* aPresContext)
    1806             : {
    1807             :   return do_AddRef(new (aPresContext)
    1808          30 :     nsRuleNode(aPresContext, nullptr, nullptr, SheetType::Unknown, false));
    1809             : }
    1810             : 
    1811        2022 : nsRuleNode::nsRuleNode(nsPresContext* aContext, nsRuleNode* aParent,
    1812             :                        nsIStyleRule* aRule, SheetType aLevel,
    1813        2022 :                        bool aIsImportant)
    1814             :   : mPresContext(aContext),
    1815             :     mParent(aParent),
    1816             :     mRule(aRule),
    1817             :     mNextSibling(nullptr),
    1818        4044 :     mDependentBits((uint32_t(aLevel) << NS_RULE_NODE_LEVEL_SHIFT) |
    1819        2022 :                    (aIsImportant ? NS_RULE_NODE_IS_IMPORTANT : 0)),
    1820        2022 :     mNoneBits(aParent ? aParent->mNoneBits & NS_RULE_NODE_HAS_ANIMATION_DATA :
    1821             :                         0),
    1822        6066 :     mRefCnt(0)
    1823             : {
    1824        2022 :   MOZ_ASSERT(aContext);
    1825        2022 :   MOZ_ASSERT(IsRoot() == !aRule,
    1826             :              "non-root rule nodes must have a rule");
    1827             : 
    1828        2022 :   mChildren.asVoid = nullptr;
    1829        2022 :   MOZ_COUNT_CTOR(nsRuleNode);
    1830             : 
    1831        2022 :   NS_ASSERTION(IsRoot() || GetLevel() == aLevel, "not enough bits");
    1832        2022 :   NS_ASSERTION(IsRoot() || IsImportantRule() == aIsImportant, "yikes");
    1833        2022 :   MOZ_ASSERT(aContext->StyleSet()->IsGecko(),
    1834             :              "ServoStyleSets should not have rule nodes");
    1835        2022 :   aContext->StyleSet()->AsGecko()->RuleNodeUnused(this, /* aMayGC = */ false);
    1836             : 
    1837             :   // nsStyleSet::GetContext depends on there being only one animation
    1838             :   // rule.
    1839        2022 :   MOZ_ASSERT(IsRoot() || GetLevel() != SheetType::Animation ||
    1840             :              mParent->IsRoot() ||
    1841             :              mParent->GetLevel() != SheetType::Animation,
    1842             :              "must be only one rule at animation level");
    1843        2022 : }
    1844             : 
    1845        1892 : nsRuleNode::~nsRuleNode()
    1846             : {
    1847         946 :   MOZ_ASSERT(!HaveChildren());
    1848         946 :   MOZ_COUNT_DTOR(nsRuleNode);
    1849         946 :   if (mParent) {
    1850         940 :     mParent->RemoveChild(this);
    1851             :   }
    1852             : 
    1853         946 :   if (mStyleData.mResetData || mStyleData.mInheritedData)
    1854         516 :     mStyleData.Destroy(mDependentBits, mPresContext);
    1855         946 : }
    1856             : 
    1857             : nsRuleNode*
    1858       11651 : nsRuleNode::Transition(nsIStyleRule* aRule, SheetType aLevel,
    1859             :                        bool aIsImportantRule)
    1860             : {
    1861             : #ifdef DEBUG
    1862             :   {
    1863       23302 :     RefPtr<css::Declaration> declaration(do_QueryObject(aRule));
    1864       11651 :     MOZ_ASSERT(!declaration || !declaration->IsMutable(),
    1865             :                "caller must call Declaration::SetImmutable first");
    1866             :   }
    1867             : #endif
    1868             : 
    1869       11651 :   nsRuleNode* next = nullptr;
    1870       11651 :   nsRuleNode::Key key(aRule, aLevel, aIsImportantRule);
    1871             : 
    1872       11651 :   if (HaveChildren() && !ChildrenAreHashed()) {
    1873        8754 :     int32_t numKids = 0;
    1874        8754 :     nsRuleNode* curr = ChildrenList();
    1875       69036 :     while (curr && curr->GetKey() != key) {
    1876       30141 :       curr = curr->mNextSibling;
    1877       30141 :       ++numKids;
    1878             :     }
    1879        8754 :     if (curr)
    1880        8118 :       next = curr;
    1881         636 :     else if (numKids >= kMaxChildrenInList)
    1882           2 :       ConvertChildrenToHash(numKids);
    1883             :   }
    1884             : 
    1885       11651 :   if (ChildrenAreHashed()) {
    1886             :     auto entry =
    1887        1605 :       static_cast<ChildrenHashEntry*>(ChildrenHash()->Add(&key, fallible));
    1888        1605 :     if (!entry) {
    1889           0 :       NS_WARNING("out of memory");
    1890           0 :       return this;
    1891             :     }
    1892        1605 :     if (entry->mRuleNode)
    1893        1541 :       next = entry->mRuleNode;
    1894             :     else {
    1895         128 :       next = entry->mRuleNode = new (mPresContext)
    1896          64 :         nsRuleNode(mPresContext, this, aRule, aLevel, aIsImportantRule);
    1897             :     }
    1898       10046 :   } else if (!next) {
    1899             :     // Create the new entry in our list.
    1900        3856 :     next = new (mPresContext)
    1901        1928 :       nsRuleNode(mPresContext, this, aRule, aLevel, aIsImportantRule);
    1902        1928 :     next->mNextSibling = ChildrenList();
    1903        1928 :     SetChildrenList(next);
    1904             :   }
    1905             : 
    1906       11651 :   return next;
    1907             : }
    1908             : 
    1909             : nsRuleNode*
    1910        1618 : nsRuleNode::RuleTree()
    1911             : {
    1912        1618 :   nsRuleNode* n = this;
    1913       15132 :   while (n->mParent) {
    1914        6757 :     n = n->mParent;
    1915             :   }
    1916        1618 :   return n;
    1917             : }
    1918             : 
    1919        2203 : void nsRuleNode::SetUsedDirectly()
    1920             : {
    1921        2203 :   mDependentBits |= NS_RULE_NODE_USED_DIRECTLY;
    1922             : 
    1923             :   // Maintain the invariant that any rule node that is used directly has
    1924             :   // all structs that live in the rule tree cached (which
    1925             :   // nsRuleNode::GetStyleData depends on for speed).
    1926        2203 :   if (mDependentBits & NS_STYLE_INHERIT_MASK) {
    1927       29700 :     for (nsStyleStructID sid = nsStyleStructID(0); sid < nsStyleStructID_Length;
    1928       28512 :          sid = nsStyleStructID(sid + 1)) {
    1929       28512 :       uint32_t bit = nsCachedStyleData::GetBitForSID(sid);
    1930       28512 :       if (mDependentBits & bit) {
    1931        6083 :         nsRuleNode *source = mParent;
    1932       24701 :         while ((source->mDependentBits & bit) && !source->IsUsedDirectly()) {
    1933        9309 :           source = source->mParent;
    1934             :         }
    1935        6083 :         void *data = source->mStyleData.GetStyleData(sid);
    1936        6083 :         NS_ASSERTION(data, "unexpected null struct");
    1937        6083 :         mStyleData.SetStyleData(sid, mPresContext, data);
    1938             :       }
    1939             :     }
    1940             :   }
    1941        2203 : }
    1942             : 
    1943             : void
    1944           2 : nsRuleNode::ConvertChildrenToHash(int32_t aNumKids)
    1945             : {
    1946           2 :   NS_ASSERTION(!ChildrenAreHashed() && HaveChildren(),
    1947             :                "must have a non-empty list of children");
    1948             :   PLDHashTable *hash = new PLDHashTable(&ChildrenHashOps,
    1949             :                                         sizeof(ChildrenHashEntry),
    1950           2 :                                         aNumKids);
    1951          66 :   for (nsRuleNode* curr = ChildrenList(); curr; curr = curr->mNextSibling) {
    1952          64 :     Key key = curr->GetKey();
    1953             :     // This will never fail because of the initial size we gave the table.
    1954             :     auto entry =
    1955          64 :       static_cast<ChildrenHashEntry*>(hash->Add(&key));
    1956          64 :     NS_ASSERTION(!entry->mRuleNode, "duplicate entries in list");
    1957          64 :     entry->mRuleNode = curr;
    1958             :   }
    1959           2 :   SetChildrenHash(hash);
    1960           2 : }
    1961             : 
    1962             : void
    1963         940 : nsRuleNode::RemoveChild(nsRuleNode* aNode)
    1964             : {
    1965         940 :   MOZ_ASSERT(HaveChildren());
    1966         940 :   if (ChildrenAreHashed()) {
    1967          64 :     PLDHashTable* children = ChildrenHash();
    1968          64 :     Key key = aNode->GetKey();
    1969          64 :     MOZ_ASSERT(children->Search(&key));
    1970          64 :     children->Remove(&key);
    1971          64 :     if (children->EntryCount() == 0) {
    1972           1 :       delete children;
    1973           1 :       mChildren.asVoid = nullptr;
    1974             :     }
    1975             :   } else {
    1976             :     // This linear traversal is unfortunate, but we do the same thing when
    1977             :     // adding nodes. The traversal is bounded by kMaxChildrenInList.
    1978         876 :     nsRuleNode** curr = &mChildren.asList;
    1979        2100 :     while (*curr != aNode) {
    1980         612 :       curr = &((*curr)->mNextSibling);
    1981         612 :       MOZ_ASSERT(*curr);
    1982             :     }
    1983         876 :     *curr = (*curr)->mNextSibling;
    1984             : 
    1985             :     // If there was one element in the list, this sets mChildren.asList
    1986             :     // to 0, and HaveChildren() will return false.
    1987             :   }
    1988         940 : }
    1989             : 
    1990             : inline void
    1991         897 : nsRuleNode::PropagateNoneBit(uint32_t aBit, nsRuleNode* aHighestNode)
    1992             : {
    1993         897 :   nsRuleNode* curr = this;
    1994        2369 :   for (;;) {
    1995        3266 :     NS_ASSERTION(!(curr->mNoneBits & aBit), "propagating too far");
    1996        3266 :     curr->mNoneBits |= aBit;
    1997        3266 :     if (curr == aHighestNode)
    1998         897 :       break;
    1999        2369 :     curr = curr->mParent;
    2000             :   }
    2001         897 : }
    2002             : 
    2003             : inline void
    2004        5627 : nsRuleNode::PropagateDependentBit(nsStyleStructID aSID, nsRuleNode* aHighestNode,
    2005             :                                   void* aStruct)
    2006             : {
    2007        5627 :   NS_ASSERTION(aStruct, "expected struct");
    2008             : 
    2009        5627 :   uint32_t bit = nsCachedStyleData::GetBitForSID(aSID);
    2010       18129 :   for (nsRuleNode* curr = this; curr != aHighestNode; curr = curr->mParent) {
    2011       13940 :     if (curr->mDependentBits & bit) {
    2012             : #ifdef DEBUG
    2013        8462 :       while (curr != aHighestNode) {
    2014        3512 :         NS_ASSERTION(curr->mDependentBits & bit, "bit not set");
    2015        3512 :         curr = curr->mParent;
    2016             :       }
    2017             : #endif
    2018        1438 :       break;
    2019             :     }
    2020             : 
    2021       12502 :     curr->mDependentBits |= bit;
    2022             : 
    2023       12502 :     if (curr->IsUsedDirectly()) {
    2024        5112 :       curr->mStyleData.SetStyleData(aSID, mPresContext, aStruct);
    2025             :     }
    2026             :   }
    2027        5627 : }
    2028             : 
    2029             : /* static */ void
    2030           0 : nsRuleNode::PropagateGrandancestorBit(GeckoStyleContext* aContext,
    2031             :                                       GeckoStyleContext* aContextInheritedFrom)
    2032             : {
    2033           0 :   MOZ_ASSERT(aContext);
    2034           0 :   MOZ_ASSERT(aContextInheritedFrom &&
    2035             :              aContextInheritedFrom != aContext,
    2036             :              "aContextInheritedFrom must be an ancestor of aContext");
    2037             : 
    2038           0 :   for (GeckoStyleContext* context = aContext->GetParent();
    2039           0 :        context != aContextInheritedFrom;
    2040           0 :        context = context->GetParent()) {
    2041           0 :     if (!context) {
    2042           0 :       MOZ_ASSERT(false, "aContextInheritedFrom must be an ancestor of "
    2043             :                         "aContext's parent");
    2044             :       break;
    2045             :     }
    2046           0 :     context->AddStyleBit(NS_STYLE_CHILD_USES_GRANDANCESTOR_STYLE);
    2047             :   }
    2048           0 : }
    2049             : 
    2050             : /*
    2051             :  * The following "Check" functions are used for determining what type of
    2052             :  * sharing can be used for the data on this rule node.  MORE HERE...
    2053             :  */
    2054             : 
    2055             : /*
    2056             :  * a callback function that that can revise the result of
    2057             :  * CheckSpecifiedProperties before finishing; aResult is the current
    2058             :  * result, and it returns the revised one.
    2059             :  */
    2060             : typedef nsRuleNode::RuleDetail
    2061             :   (* CheckCallbackFn)(const nsRuleData* aRuleData,
    2062             :                       nsRuleNode::RuleDetail aResult);
    2063             : 
    2064             : /**
    2065             :  * @param aValue the value being examined
    2066             :  * @param aSpecifiedCount to be incremented by one if the value is specified
    2067             :  * @param aInheritedCount to be incremented by one if the value is set to inherit
    2068             :  * @param aUnsetCount to be incremented by one if the value is set to unset
    2069             :  */
    2070             : inline void
    2071      459071 : ExamineCSSValue(const nsCSSValue& aValue,
    2072             :                 uint32_t& aSpecifiedCount,
    2073             :                 uint32_t& aInheritedCount,
    2074             :                 uint32_t& aUnsetCount)
    2075             : {
    2076      459071 :   if (aValue.GetUnit() != eCSSUnit_Null) {
    2077       25104 :     ++aSpecifiedCount;
    2078       25104 :     if (aValue.GetUnit() == eCSSUnit_Inherit) {
    2079        2608 :       ++aInheritedCount;
    2080       22496 :     } else if (aValue.GetUnit() == eCSSUnit_Unset) {
    2081           0 :       ++aUnsetCount;
    2082             :     }
    2083             :   }
    2084      459071 : }
    2085             : 
    2086             : static nsRuleNode::RuleDetail
    2087         640 : CheckFontCallback(const nsRuleData* aRuleData,
    2088             :                   nsRuleNode::RuleDetail aResult)
    2089             : {
    2090             :   // em, ex, percent, 'larger', and 'smaller' values on font-size depend
    2091             :   // on the parent context's font-size
    2092             :   // Likewise, 'lighter' and 'bolder' values of 'font-weight', and 'wider'
    2093             :   // and 'narrower' values of 'font-stretch' depend on the parent.
    2094         640 :   const nsCSSValue& size = *aRuleData->ValueForFontSize();
    2095         640 :   const nsCSSValue& weight = *aRuleData->ValueForFontWeight();
    2096        1920 :   if ((size.IsRelativeLengthUnit() && size.GetUnit() != eCSSUnit_RootEM) ||
    2097        1280 :       size.GetUnit() == eCSSUnit_Percent ||
    2098         640 :       (size.GetUnit() == eCSSUnit_Enumerated &&
    2099           0 :        (size.GetIntValue() == NS_STYLE_FONT_SIZE_SMALLER ||
    2100         640 :         size.GetIntValue() == NS_STYLE_FONT_SIZE_LARGER)) ||
    2101        1920 :       aRuleData->ValueForScriptLevel()->GetUnit() == eCSSUnit_Integer ||
    2102         640 :       (weight.GetUnit() == eCSSUnit_Enumerated &&
    2103           0 :        (weight.GetIntValue() == NS_STYLE_FONT_WEIGHT_BOLDER ||
    2104           0 :         weight.GetIntValue() == NS_STYLE_FONT_WEIGHT_LIGHTER))) {
    2105           0 :     NS_ASSERTION(aResult == nsRuleNode::eRulePartialReset ||
    2106             :                  aResult == nsRuleNode::eRuleFullReset ||
    2107             :                  aResult == nsRuleNode::eRulePartialMixed ||
    2108             :                  aResult == nsRuleNode::eRuleFullMixed,
    2109             :                  "we know we already have a reset-counted property");
    2110             :     // Promote reset to mixed since we have something that depends on
    2111             :     // the parent.  But never promote to inherited since that could
    2112             :     // cause inheritance of the exact value.
    2113           0 :     if (aResult == nsRuleNode::eRulePartialReset)
    2114           0 :       aResult = nsRuleNode::eRulePartialMixed;
    2115           0 :     else if (aResult == nsRuleNode::eRuleFullReset)
    2116           0 :       aResult = nsRuleNode::eRuleFullMixed;
    2117             :   }
    2118             : 
    2119         640 :   return aResult;
    2120             : }
    2121             : 
    2122             : static nsRuleNode::RuleDetail
    2123         279 : CheckColorCallback(const nsRuleData* aRuleData,
    2124             :                    nsRuleNode::RuleDetail aResult)
    2125             : {
    2126             :   // currentColor values for color require inheritance
    2127         279 :   const nsCSSValue* colorValue = aRuleData->ValueForColor();
    2128         289 :   if (colorValue->GetUnit() == eCSSUnit_EnumColor &&
    2129          10 :       colorValue->GetIntValue() == NS_COLOR_CURRENTCOLOR) {
    2130           0 :     NS_ASSERTION(aResult == nsRuleNode::eRuleFullReset,
    2131             :                  "we should already be counted as full-reset");
    2132           0 :     aResult = nsRuleNode::eRuleFullInherited;
    2133             :   }
    2134             : 
    2135         279 :   return aResult;
    2136             : }
    2137             : 
    2138             : static nsRuleNode::RuleDetail
    2139         950 : CheckTextCallback(const nsRuleData* aRuleData,
    2140             :                   nsRuleNode::RuleDetail aResult)
    2141             : {
    2142         950 :   const nsCSSValue* textAlignValue = aRuleData->ValueForTextAlign();
    2143         958 :   if (textAlignValue->GetUnit() == eCSSUnit_Enumerated &&
    2144           8 :       (textAlignValue->GetIntValue() ==
    2145           8 :         NS_STYLE_TEXT_ALIGN_MOZ_CENTER_OR_INHERIT ||
    2146           8 :        textAlignValue->GetIntValue() == NS_STYLE_TEXT_ALIGN_MATCH_PARENT)) {
    2147             :     // Promote reset to mixed since we have something that depends on
    2148             :     // the parent.
    2149           0 :     if (aResult == nsRuleNode::eRulePartialReset)
    2150           0 :       aResult = nsRuleNode::eRulePartialMixed;
    2151           0 :     else if (aResult == nsRuleNode::eRuleFullReset)
    2152           0 :       aResult = nsRuleNode::eRuleFullMixed;
    2153             :   }
    2154             : 
    2155         950 :   return aResult;
    2156             : }
    2157             : 
    2158             : static nsRuleNode::RuleDetail
    2159         576 : CheckVariablesCallback(const nsRuleData* aRuleData,
    2160             :                        nsRuleNode::RuleDetail aResult)
    2161             : {
    2162             :   // We don't actually have any properties on nsStyleVariables, so we do
    2163             :   // all of the RuleDetail calculation in here.
    2164         576 :   if (aRuleData->mVariables) {
    2165          72 :     return nsRuleNode::eRulePartialMixed;
    2166             :   }
    2167         504 :   return nsRuleNode::eRuleNone;
    2168             : }
    2169             : 
    2170             : #define FLAG_DATA_FOR_PROPERTY(name_, id_, method_, flags_, pref_,          \
    2171             :                                parsevariant_, kwtable_, stylestructoffset_, \
    2172             :                                animtype_)                                   \
    2173             :   flags_,
    2174             : 
    2175             : // The order here must match the enums in *CheckCounter in nsCSSProps.cpp.
    2176             : 
    2177             : static const uint32_t gFontFlags[] = {
    2178             : #define CSS_PROP_FONT FLAG_DATA_FOR_PROPERTY
    2179             : #include "nsCSSPropList.h"
    2180             : #undef CSS_PROP_FONT
    2181             : };
    2182             : 
    2183             : static const uint32_t gDisplayFlags[] = {
    2184             : #define CSS_PROP_DISPLAY FLAG_DATA_FOR_PROPERTY
    2185             : #include "nsCSSPropList.h"
    2186             : #undef CSS_PROP_DISPLAY
    2187             : };
    2188             : 
    2189             : static const uint32_t gVisibilityFlags[] = {
    2190             : #define CSS_PROP_VISIBILITY FLAG_DATA_FOR_PROPERTY
    2191             : #include "nsCSSPropList.h"
    2192             : #undef CSS_PROP_VISIBILITY
    2193             : };
    2194             : 
    2195             : static const uint32_t gMarginFlags[] = {
    2196             : #define CSS_PROP_MARGIN FLAG_DATA_FOR_PROPERTY
    2197             : #include "nsCSSPropList.h"
    2198             : #undef CSS_PROP_MARGIN
    2199             : };
    2200             : 
    2201             : static const uint32_t gBorderFlags[] = {
    2202             : #define CSS_PROP_BORDER FLAG_DATA_FOR_PROPERTY
    2203             : #include "nsCSSPropList.h"
    2204             : #undef CSS_PROP_BORDER
    2205             : };
    2206             : 
    2207             : static const uint32_t gPaddingFlags[] = {
    2208             : #define CSS_PROP_PADDING FLAG_DATA_FOR_PROPERTY
    2209             : #include "nsCSSPropList.h"
    2210             : #undef CSS_PROP_PADDING
    2211             : };
    2212             : 
    2213             : static const uint32_t gOutlineFlags[] = {
    2214             : #define CSS_PROP_OUTLINE FLAG_DATA_FOR_PROPERTY
    2215             : #include "nsCSSPropList.h"
    2216             : #undef CSS_PROP_OUTLINE
    2217             : };
    2218             : 
    2219             : static const uint32_t gListFlags[] = {
    2220             : #define CSS_PROP_LIST FLAG_DATA_FOR_PROPERTY
    2221             : #include "nsCSSPropList.h"
    2222             : #undef CSS_PROP_LIST
    2223             : };
    2224             : 
    2225             : static const uint32_t gColorFlags[] = {
    2226             : #define CSS_PROP_COLOR FLAG_DATA_FOR_PROPERTY
    2227             : #include "nsCSSPropList.h"
    2228             : #undef CSS_PROP_COLOR
    2229             : };
    2230             : 
    2231             : static const uint32_t gBackgroundFlags[] = {
    2232             : #define CSS_PROP_BACKGROUND FLAG_DATA_FOR_PROPERTY
    2233             : #include "nsCSSPropList.h"
    2234             : #undef CSS_PROP_BACKGROUND
    2235             : };
    2236             : 
    2237             : static const uint32_t gPositionFlags[] = {
    2238             : #define CSS_PROP_POSITION FLAG_DATA_FOR_PROPERTY
    2239             : #include "nsCSSPropList.h"
    2240             : #undef CSS_PROP_POSITION
    2241             : };
    2242             : 
    2243             : static const uint32_t gTableFlags[] = {
    2244             : #define CSS_PROP_TABLE FLAG_DATA_FOR_PROPERTY
    2245             : #include "nsCSSPropList.h"
    2246             : #undef CSS_PROP_TABLE
    2247             : };
    2248             : 
    2249             : static const uint32_t gTableBorderFlags[] = {
    2250             : #define CSS_PROP_TABLEBORDER FLAG_DATA_FOR_PROPERTY
    2251             : #include "nsCSSPropList.h"
    2252             : #undef CSS_PROP_TABLEBORDER
    2253             : };
    2254             : 
    2255             : static const uint32_t gContentFlags[] = {
    2256             : #define CSS_PROP_CONTENT FLAG_DATA_FOR_PROPERTY
    2257             : #include "nsCSSPropList.h"
    2258             : #undef CSS_PROP_CONTENT
    2259             : };
    2260             : 
    2261             : static const uint32_t gTextFlags[] = {
    2262             : #define CSS_PROP_TEXT FLAG_DATA_FOR_PROPERTY
    2263             : #include "nsCSSPropList.h"
    2264             : #undef CSS_PROP_TEXT
    2265             : };
    2266             : 
    2267             : static const uint32_t gTextResetFlags[] = {
    2268             : #define CSS_PROP_TEXTRESET FLAG_DATA_FOR_PROPERTY
    2269             : #include "nsCSSPropList.h"
    2270             : #undef CSS_PROP_TEXTRESET
    2271             : };
    2272             : 
    2273             : static const uint32_t gUserInterfaceFlags[] = {
    2274             : #define CSS_PROP_USERINTERFACE FLAG_DATA_FOR_PROPERTY
    2275             : #include "nsCSSPropList.h"
    2276             : #undef CSS_PROP_USERINTERFACE
    2277             : };
    2278             : 
    2279             : static const uint32_t gUIResetFlags[] = {
    2280             : #define CSS_PROP_UIRESET FLAG_DATA_FOR_PROPERTY
    2281             : #include "nsCSSPropList.h"
    2282             : #undef CSS_PROP_UIRESET
    2283             : };
    2284             : 
    2285             : static const uint32_t gXULFlags[] = {
    2286             : #define CSS_PROP_XUL FLAG_DATA_FOR_PROPERTY
    2287             : #include "nsCSSPropList.h"
    2288             : #undef CSS_PROP_XUL
    2289             : };
    2290             : 
    2291             : static const uint32_t gSVGFlags[] = {
    2292             : #define CSS_PROP_SVG FLAG_DATA_FOR_PROPERTY
    2293             : #include "nsCSSPropList.h"
    2294             : #undef CSS_PROP_SVG
    2295             : };
    2296             : 
    2297             : static const uint32_t gSVGResetFlags[] = {
    2298             : #define CSS_PROP_SVGRESET FLAG_DATA_FOR_PROPERTY
    2299             : #include "nsCSSPropList.h"
    2300             : #undef CSS_PROP_SVGRESET
    2301             : };
    2302             : 
    2303             : static const uint32_t gColumnFlags[] = {
    2304             : #define CSS_PROP_COLUMN FLAG_DATA_FOR_PROPERTY
    2305             : #include "nsCSSPropList.h"
    2306             : #undef CSS_PROP_COLUMN
    2307             : };
    2308             : 
    2309             : // There are no properties in nsStyleVariables, but we can't have a
    2310             : // zero length array.
    2311             : static const uint32_t gVariablesFlags[] = {
    2312             :   0,
    2313             : #define CSS_PROP_VARIABLES FLAG_DATA_FOR_PROPERTY
    2314             : #include "nsCSSPropList.h"
    2315             : #undef CSS_PROP_VARIABLES
    2316             : };
    2317             : static_assert(sizeof(gVariablesFlags) == sizeof(uint32_t),
    2318             :               "if nsStyleVariables has properties now you can remove the dummy "
    2319             :               "gVariablesFlags entry");
    2320             : 
    2321             : static const uint32_t gEffectsFlags[] = {
    2322             : #define CSS_PROP_EFFECTS FLAG_DATA_FOR_PROPERTY
    2323             : #include "nsCSSPropList.h"
    2324             : #undef CSS_PROP_EFFECTS
    2325             : };
    2326             : 
    2327             : #undef FLAG_DATA_FOR_PROPERTY
    2328             : 
    2329             : static const uint32_t* gFlagsByStruct[] = {
    2330             : 
    2331             : #define STYLE_STRUCT(name, checkdata_cb) \
    2332             :   g##name##Flags,
    2333             : #include "nsStyleStructList.h"
    2334             : #undef STYLE_STRUCT
    2335             : 
    2336             : };
    2337             : 
    2338             : static const CheckCallbackFn gCheckCallbacks[] = {
    2339             : 
    2340             : #define STYLE_STRUCT(name, checkdata_cb) \
    2341             :   checkdata_cb,
    2342             : #include "nsStyleStructList.h"
    2343             : #undef STYLE_STRUCT
    2344             : 
    2345             : };
    2346             : 
    2347             : #ifdef DEBUG
    2348             : static bool
    2349         640 : AreAllMathMLPropertiesUndefined(const nsRuleData* aRuleData)
    2350             : {
    2351             :   return
    2352        1280 :     aRuleData->ValueForScriptLevel()->GetUnit() == eCSSUnit_Null &&
    2353        1280 :     aRuleData->ValueForScriptSizeMultiplier()->GetUnit() == eCSSUnit_Null &&
    2354        1280 :     aRuleData->ValueForScriptMinSize()->GetUnit() == eCSSUnit_Null &&
    2355        1920 :     aRuleData->ValueForMathVariant()->GetUnit() == eCSSUnit_Null &&
    2356        1280 :     aRuleData->ValueForMathDisplay()->GetUnit() == eCSSUnit_Null;
    2357             : }
    2358             : #endif
    2359             : 
    2360             : inline nsRuleNode::RuleDetail
    2361       33232 : nsRuleNode::CheckSpecifiedProperties(const nsStyleStructID aSID,
    2362             :                                      const nsRuleData* aRuleData)
    2363             : {
    2364             :   // Build a count of the:
    2365       33232 :   uint32_t total = 0,      // total number of props in the struct
    2366       33232 :            specified = 0,  // number that were specified for this node
    2367       33232 :            inherited = 0,  // number that were 'inherit' (and not
    2368             :                            //   eCSSUnit_Inherit) for this node
    2369       33232 :            unset = 0;      // number that were 'unset'
    2370             : 
    2371             :   // See comment in nsRuleData.h above mValueOffsets.
    2372       33232 :   MOZ_ASSERT(aRuleData->mValueOffsets[aSID] == 0,
    2373             :              "we assume the value offset is zero instead of adding it");
    2374      492303 :   for (nsCSSValue *values = aRuleData->mValueStorage,
    2375       33232 :               *values_end = values + nsCSSProps::PropertyCountInStruct(aSID);
    2376      492303 :        values != values_end; ++values) {
    2377      459071 :     ++total;
    2378      459071 :     ExamineCSSValue(*values, specified, inherited, unset);
    2379             :   }
    2380             : 
    2381       33232 :   if (!nsCachedStyleData::IsReset(aSID)) {
    2382             :     // For inherited properties, 'unset' means the same as 'inherit'.
    2383       14084 :     inherited += unset;
    2384       14084 :     unset = 0;
    2385             :   }
    2386             : 
    2387             : #if 0
    2388             :   printf("CheckSpecifiedProperties: SID=%d total=%d spec=%d inh=%d.\n",
    2389             :          aSID, total, specified, inherited);
    2390             : #endif
    2391             : 
    2392       33232 :   NS_ASSERTION(aSID != eStyleStruct_Font ||
    2393             :                mPresContext->Document()->GetMathMLEnabled() ||
    2394             :                AreAllMathMLPropertiesUndefined(aRuleData),
    2395             :                "MathML style property was defined even though MathML is disabled");
    2396             : 
    2397             :   /*
    2398             :    * Return the most specific information we can: prefer None or Full
    2399             :    * over Partial, and Reset or Inherited over Mixed, since we can
    2400             :    * optimize based on the edge cases and not the in-between cases.
    2401             :    */
    2402             :   nsRuleNode::RuleDetail result;
    2403       33232 :   if (inherited == total)
    2404         648 :     result = eRuleFullInherited;
    2405       65168 :   else if (specified == total
    2406             :            // MathML defines 5 properties in Font that will never be set when
    2407             :            // MathML is not in use. Therefore if all but five
    2408             :            // properties have been set, and MathML is not enabled, we can treat
    2409             :            // this as fully specified. Code in nsMathMLElementFactory will
    2410             :            // rebuild the rule tree and style data when MathML is first enabled
    2411             :            // (see nsMathMLElement::BindToTree).
    2412       32584 :            || (aSID == eStyleStruct_Font && specified + 5 == total &&
    2413           0 :                !mPresContext->Document()->GetMathMLEnabled())
    2414             :           ) {
    2415         281 :     if (inherited == 0)
    2416         281 :       result = eRuleFullReset;
    2417             :     else
    2418           0 :       result = eRuleFullMixed;
    2419       32303 :   } else if (specified == 0)
    2420       22989 :     result = eRuleNone;
    2421        9314 :   else if (specified == inherited)
    2422         570 :     result = eRulePartialInherited;
    2423        8744 :   else if (inherited == 0)
    2424        8581 :     result = eRulePartialReset;
    2425             :   else
    2426         163 :     result = eRulePartialMixed;
    2427             : 
    2428       33232 :   CheckCallbackFn cb = gCheckCallbacks[aSID];
    2429       33232 :   if (cb) {
    2430        2445 :     result = (*cb)(aRuleData, result);
    2431             :   }
    2432             : 
    2433       33232 :   return result;
    2434             : }
    2435             : 
    2436             : // If we need to restrict which properties apply to the style context,
    2437             : // return the bit to check in nsCSSProp's flags table.  Otherwise,
    2438             : // return 0.
    2439             : inline uint32_t
    2440       11850 : GetPseudoRestriction(GeckoStyleContext *aContext)
    2441             : {
    2442             :   // This needs to match nsStyleSet::WalkRestrictionRule.
    2443       11850 :   uint32_t pseudoRestriction = 0;
    2444       11850 :   nsIAtom *pseudoType = aContext->GetPseudo();
    2445       11850 :   if (pseudoType) {
    2446        2149 :     if (pseudoType == nsCSSPseudoElements::firstLetter) {
    2447           0 :       pseudoRestriction = CSS_PROPERTY_APPLIES_TO_FIRST_LETTER;
    2448        2149 :     } else if (pseudoType == nsCSSPseudoElements::firstLine) {
    2449           0 :       pseudoRestriction = CSS_PROPERTY_APPLIES_TO_FIRST_LINE;
    2450        2149 :     } else if (pseudoType == nsCSSPseudoElements::placeholder) {
    2451          63 :       pseudoRestriction = CSS_PROPERTY_APPLIES_TO_PLACEHOLDER;
    2452             :     }
    2453             :   }
    2454       11850 :   return pseudoRestriction;
    2455             : }
    2456             : 
    2457             : static void
    2458          63 : UnsetPropertiesWithoutFlags(const nsStyleStructID aSID,
    2459             :                             nsRuleData* aRuleData,
    2460             :                             uint32_t aFlags)
    2461             : {
    2462          63 :   NS_ASSERTION(aFlags != 0, "aFlags must be nonzero");
    2463             : 
    2464          63 :   const uint32_t *flagData = gFlagsByStruct[aSID];
    2465             : 
    2466             :   // See comment in nsRuleData.h above mValueOffsets.
    2467          63 :   MOZ_ASSERT(aRuleData->mValueOffsets[aSID] == 0,
    2468             :              "we assume the value offset is zero instead of adding it");
    2469          63 :   nsCSSValue *values = aRuleData->mValueStorage;
    2470             : 
    2471        1053 :   for (size_t i = 0, i_end = nsCSSProps::PropertyCountInStruct(aSID);
    2472        1053 :        i != i_end; ++i) {
    2473         990 :     if ((flagData[i] & aFlags) != aFlags)
    2474         696 :       values[i].Reset();
    2475             :   }
    2476          63 : }
    2477             : 
    2478       11858 : AutoCSSValueArray::AutoCSSValueArray(void* aStorage, size_t aCount)
    2479             : {
    2480       11858 :   MOZ_ASSERT(size_t(aStorage) % NS_ALIGNMENT_OF(nsCSSValue) == 0,
    2481             :              "bad alignment from alloca");
    2482       11858 :   mCount = aCount;
    2483             :   // Don't use placement new[], since it might store extra data
    2484             :   // for the count (on Windows!).
    2485       11858 :   mArray = static_cast<nsCSSValue*>(aStorage);
    2486      171067 :   for (size_t i = 0; i < mCount; ++i) {
    2487      159209 :     new (KnownNotNull, mArray + i) nsCSSValue();
    2488             :   }
    2489       11858 : }
    2490             : 
    2491       23716 : AutoCSSValueArray::~AutoCSSValueArray()
    2492             : {
    2493      171067 :   for (size_t i = 0; i < mCount; ++i) {
    2494      159209 :     mArray[i].~nsCSSValue();
    2495             :   }
    2496       11858 : }
    2497             : 
    2498             : /* static */ bool
    2499       11551 : nsRuleNode::ResolveVariableReferences(const nsStyleStructID aSID,
    2500             :                                       nsRuleData* aRuleData,
    2501             :                                       GeckoStyleContext* aContext)
    2502             : {
    2503       11551 :   MOZ_ASSERT(aSID != eStyleStruct_Variables);
    2504       11551 :   MOZ_ASSERT(aRuleData->mSIDs & nsCachedStyleData::GetBitForSID(aSID));
    2505       11551 :   MOZ_ASSERT(aRuleData->mValueOffsets[aSID] == 0);
    2506             : 
    2507       23102 :   nsCSSParser parser;
    2508       11551 :   bool anyTokenStreams = false;
    2509             : 
    2510             :   // Look at each property in the nsRuleData for the given style struct.
    2511       11551 :   size_t nprops = nsCSSProps::PropertyCountInStruct(aSID);
    2512      170720 :   for (nsCSSValue* value = aRuleData->mValueStorage,
    2513       11551 :                   *values_end = aRuleData->mValueStorage + nprops;
    2514      170720 :        value != values_end; value++) {
    2515      159169 :     if (value->GetUnit() != eCSSUnit_TokenStream) {
    2516      158286 :       continue;
    2517             :     }
    2518             : 
    2519             :     const CSSVariableValues* variables =
    2520         883 :       &aContext->StyleVariables()->mVariables;
    2521         883 :     nsCSSValueTokenStream* tokenStream = value->GetTokenStreamValue();
    2522             : 
    2523         883 :     MOZ_ASSERT(tokenStream->mLevel != SheetType::Count,
    2524             :                "Token stream should have a defined level");
    2525             : 
    2526        1766 :     AutoRestore<SheetType> saveLevel(aRuleData->mLevel);
    2527         883 :     aRuleData->mLevel = tokenStream->mLevel;
    2528             : 
    2529             :     // Note that ParsePropertyWithVariableReferences relies on the fact
    2530             :     // that the nsCSSValue in aRuleData for the property we are re-parsing
    2531             :     // is still the token stream value.  When
    2532             :     // ParsePropertyWithVariableReferences calls
    2533             :     // nsCSSExpandedDataBlock::MapRuleInfoInto, that function will add
    2534             :     // the ImageValue that is created into the token stream object's
    2535             :     // mImageValues table; see the comment above mImageValues for why.
    2536             : 
    2537             :     // XXX Should pass in sheet here (see bug 952338).
    2538         883 :     parser.ParsePropertyWithVariableReferences(
    2539             :         tokenStream->mPropertyID, tokenStream->mShorthandPropertyID,
    2540             :         tokenStream->mTokenStream, variables, aRuleData,
    2541             :         tokenStream->mSheetURI, tokenStream->mBaseURI,
    2542             :         tokenStream->mSheetPrincipal, nullptr,
    2543         883 :         tokenStream->mLineNumber, tokenStream->mLineOffset);
    2544         883 :     aRuleData->mConditions.SetUncacheable();
    2545         883 :     anyTokenStreams = true;
    2546             :   }
    2547             : 
    2548       23102 :   return anyTokenStreams;
    2549             : }
    2550             : 
    2551             : const void*
    2552       11850 : nsRuleNode::WalkRuleTree(const nsStyleStructID aSID,
    2553             :                          GeckoStyleContext* aContext)
    2554             : {
    2555             :   // use placement new[] on the result of alloca() to allocate a
    2556             :   // variable-sized stack array, including execution of constructors,
    2557             :   // and use an RAII class to run the destructors too.
    2558       11850 :   size_t nprops = nsCSSProps::PropertyCountInStruct(aSID);
    2559       11850 :   void* dataStorage = alloca(nprops * sizeof(nsCSSValue));
    2560       23700 :   AutoCSSValueArray dataArray(dataStorage, nprops);
    2561             : 
    2562             :   nsRuleData ruleData(nsCachedStyleData::GetBitForSID(aSID),
    2563       23700 :                       dataArray.get(), mPresContext, aContext);
    2564       11850 :   ruleData.mValueOffsets[aSID] = 0;
    2565             : 
    2566             :   // We start at the most specific rule in the tree.
    2567       11850 :   void* startStruct = nullptr;
    2568             : 
    2569       11850 :   nsRuleNode* ruleNode = this;
    2570       11850 :   nsRuleNode* highestNode = nullptr; // The highest node in the rule tree
    2571             :                                     // that has the same properties
    2572             :                                     // specified for struct |aSID| as
    2573             :                                     // |this| does.
    2574       11850 :   nsRuleNode* rootNode = this; // After the loop below, this will be the
    2575             :                                // highest node that we've walked without
    2576             :                                // finding cached data on the rule tree.
    2577             :                                // If we don't find any cached data, it
    2578             :                                // will be the root.  (XXX misnamed)
    2579       11850 :   RuleDetail detail = eRuleNone;
    2580       11850 :   uint32_t bit = nsCachedStyleData::GetBitForSID(aSID);
    2581             : 
    2582       77024 :   while (ruleNode) {
    2583             :     // See if this rule node has cached the fact that the remaining
    2584             :     // nodes along this path specify no data whatsoever.
    2585       43802 :     if (ruleNode->mNoneBits & bit)
    2586        5224 :       break;
    2587             : 
    2588             :     // If the dependent bit is set on a rule node for this struct, that
    2589             :     // means its rule won't have any information to add, so skip it.
    2590             :     // NOTE: If we exit the loop because of the !IsUsedDirectly() check,
    2591             :     // then we're guaranteed to break immediately afterwards due to a
    2592             :     // non-null startStruct.
    2593       46246 :     while ((ruleNode->mDependentBits & bit) && !ruleNode->IsUsedDirectly()) {
    2594        3834 :       NS_ASSERTION(ruleNode->mStyleData.GetStyleData(aSID) == nullptr,
    2595             :                    "dependent bit with cached data makes no sense");
    2596             :       // Climb up to the next rule in the tree (a less specific rule).
    2597        3834 :       rootNode = ruleNode;
    2598        3834 :       ruleNode = ruleNode->mParent;
    2599        3834 :       NS_ASSERTION(!(ruleNode->mNoneBits & bit), "can't have both bits set");
    2600             :     }
    2601             : 
    2602             :     // Check for cached data after the inner loop above -- otherwise
    2603             :     // we'll miss it.
    2604       38578 :     startStruct = ruleNode->mStyleData.GetStyleData(aSID);
    2605       38578 :     if (startStruct)
    2606        5705 :       break; // We found a rule with fully specified data.  We don't
    2607             :              // need to go up the tree any further, since the remainder
    2608             :              // of this branch has already been computed.
    2609             : 
    2610             :     // Ask the rule to fill in the properties that it specifies.
    2611       32873 :     nsIStyleRule *rule = ruleNode->mRule;
    2612       32873 :     if (rule) {
    2613       32238 :       ruleData.mLevel = ruleNode->GetLevel();
    2614       32238 :       ruleData.mIsImportantRule = ruleNode->IsImportantRule();
    2615       32238 :       rule->MapRuleInfoInto(&ruleData);
    2616             :     }
    2617             : 
    2618             :     // Now we check to see how many properties have been specified by
    2619             :     // the rules we've examined so far.
    2620       32873 :     RuleDetail oldDetail = detail;
    2621       32873 :     detail = CheckSpecifiedProperties(aSID, &ruleData);
    2622             : 
    2623       32873 :     if (oldDetail == eRuleNone && detail != eRuleNone)
    2624        3847 :       highestNode = ruleNode;
    2625             : 
    2626       32873 :     if (detail == eRuleFullReset ||
    2627       32653 :         detail == eRuleFullMixed ||
    2628             :         detail == eRuleFullInherited)
    2629             :       break; // We don't need to examine any more rules.  All properties
    2630             :              // have been fully specified.
    2631             : 
    2632             :     // Climb up to the next rule in the tree (a less specific rule).
    2633       32587 :     rootNode = ruleNode;
    2634       32587 :     ruleNode = ruleNode->mParent;
    2635             :   }
    2636             : 
    2637       11850 :   bool recomputeDetail = false;
    2638             : 
    2639             :   // If we are computing a style struct other than nsStyleVariables, and
    2640             :   // ruleData has any properties with variable references (nsCSSValues of
    2641             :   // type eCSSUnit_TokenStream), then we need to resolve these.
    2642       11850 :   if (aSID != eStyleStruct_Variables) {
    2643             :     // A property's value might have became 'inherit' after resolving
    2644             :     // variable references.  (This happens when an inherited property
    2645             :     // fails to parse its resolved value.)  We need to recompute
    2646             :     // |detail| in case this happened.
    2647       11551 :     recomputeDetail = ResolveVariableReferences(aSID, &ruleData, aContext);
    2648             :   }
    2649             : 
    2650             :   // If needed, unset the properties that don't have a flag that allows
    2651             :   // them to be set for this style context.  (For example, only some
    2652             :   // properties apply to :first-line and :first-letter.)
    2653       11850 :   uint32_t pseudoRestriction = GetPseudoRestriction(aContext);
    2654       11850 :   if (pseudoRestriction) {
    2655          63 :     UnsetPropertiesWithoutFlags(aSID, &ruleData, pseudoRestriction);
    2656             : 
    2657             :     // We need to recompute |detail| based on the restrictions we just applied.
    2658             :     // We can adjust |detail| arbitrarily because of the restriction
    2659             :     // rule added in nsStyleSet::WalkRestrictionRule.
    2660          63 :     recomputeDetail = true;
    2661             :   }
    2662             : 
    2663       11850 :   if (recomputeDetail) {
    2664         359 :     detail = CheckSpecifiedProperties(aSID, &ruleData);
    2665             :   }
    2666             : 
    2667       11850 :   NS_ASSERTION(!startStruct || (detail != eRuleFullReset &&
    2668             :                                 detail != eRuleFullMixed &&
    2669             :                                 detail != eRuleFullInherited),
    2670             :                "can't have start struct and be fully specified");
    2671             : 
    2672       11850 :   bool isReset = nsCachedStyleData::IsReset(aSID);
    2673       11850 :   if (!highestNode)
    2674        8003 :     highestNode = rootNode;
    2675             : 
    2676       11850 :   MOZ_ASSERT(!(aSID == eStyleStruct_Variables && startStruct),
    2677             :              "if we start caching Variables structs in the rule tree, then "
    2678             :              "not forcing detail to eRulePartialMixed just below is no "
    2679             :              "longer valid");
    2680             : 
    2681       11850 :   if (detail == eRuleNone && isReset) {
    2682             :     // We specified absolutely no rule information for a reset struct, and we
    2683             :     // may or may not have found a parent rule in the tree that specified all
    2684             :     // the rule information.  Regardless, we don't need to use any cache
    2685             :     // conditions if we cache this struct in the rule tree.
    2686             :     //
    2687             :     // Normally ruleData.mConditions would already indicate that the struct
    2688             :     // is cacheable without conditions if detail is eRuleNone, but because
    2689             :     // of the UnsetPropertiesWithoutFlags call above, we may have encountered
    2690             :     // some rules with dependencies, which we then cleared out of ruleData.
    2691             :     //
    2692             :     // ruleData.mConditions could also indicate we are not cacheable at all,
    2693             :     // such as when AnimValuesStyleRule prevents us from caching structs
    2694             :     // when attempting to apply animations to pseudos.
    2695             :     //
    2696             :     // So if we we are uncacheable, we leave it, but if we are cacheable
    2697             :     // with dependencies, we convert that to cacheable without dependencies.
    2698        4512 :     if (ruleData.mConditions.CacheableWithDependencies()) {
    2699           0 :       MOZ_ASSERT(pseudoRestriction,
    2700             :                  "should only be cacheable with dependencies if we had a "
    2701             :                  "pseudo restriction");
    2702           0 :       ruleData.mConditions.Clear();
    2703             :     } else {
    2704             :       // XXXheycam We shouldn't have `|| GetLevel() == SheetType::Transition`
    2705             :       // in the assertion condition, but rule nodes created by
    2706             :       // ResolveStyleByAddingRules don't call SetIsAnimationRule().
    2707        4512 :       MOZ_ASSERT(ruleData.mConditions.CacheableWithoutDependencies() ||
    2708             :                  ((HasAnimationData() ||
    2709             :                    GetLevel() == SheetType::Transition) &&
    2710             :                   aContext->GetParent() &&
    2711             :                   aContext->GetParent()->HasPseudoElementData()),
    2712             :                  "should only be uncacheable if we had an animation rule "
    2713             :                  "and we're inside a pseudo");
    2714             :     }
    2715             :   }
    2716             : 
    2717       11850 :   if (!ruleData.mConditions.CacheableWithoutDependencies() &&
    2718             :       aSID != eStyleStruct_Variables) {
    2719             :     // Treat as though some data is specified to avoid the optimizations and
    2720             :     // force data computation.
    2721             :     //
    2722             :     // We don't need to do this for Variables structs since we know those are
    2723             :     // never cached in the rule tree, and it avoids wasteful computation of a
    2724             :     // new Variables struct when we have no additional variable declarations,
    2725             :     // which otherwise could happen when there is an AnimValuesStyleRule
    2726             :     // (which calls SetUncacheable for style contexts with pseudo data).
    2727         358 :     detail = eRulePartialMixed;
    2728             :   }
    2729             : 
    2730       11850 :   if (detail == eRuleNone && startStruct) {
    2731             :     // We specified absolutely no rule information, but a parent rule in the tree
    2732             :     // specified all the rule information.  We set a bit along the branch from our
    2733             :     // node in the tree to the node that specified the data that tells nodes on that
    2734             :     // branch that they never need to examine their rules for this particular struct type
    2735             :     // ever again.
    2736        4216 :     PropagateDependentBit(aSID, ruleNode, startStruct);
    2737             :     // For inherited structs, mark the struct (which will be set on
    2738             :     // the context by our caller) as not being owned by the context.
    2739        4216 :     if (!isReset) {
    2740           3 :       aContext->AddStyleBit(nsCachedStyleData::GetBitForSID(aSID));
    2741        4213 :     } else if (HasAnimationData()) {
    2742             :       // If we have animation data, the struct should be cached on the style
    2743             :       // context so that we can peek the struct.
    2744             :       // See comment in AnimValuesStyleRule::MapRuleInfoInto.
    2745          76 :       StoreStyleOnContext(aContext, aSID, startStruct);
    2746             :     }
    2747             : 
    2748        4216 :     return startStruct;
    2749             :   }
    2750        7634 :   if ((!startStruct && !isReset &&
    2751        1913 :        (detail == eRuleNone || detail == eRulePartialInherited)) ||
    2752             :       detail == eRuleFullInherited) {
    2753             :     // We specified no non-inherited information and neither did any of
    2754             :     // our parent rules.
    2755             : 
    2756             :     // We set a bit along the branch from the highest node (ruleNode)
    2757             :     // down to our node (this) indicating that no non-inherited data was
    2758             :     // specified.  This bit is guaranteed to be set already on the path
    2759             :     // from the highest node to the root node in the case where
    2760             :     // (detail == eRuleNone), which is the most common case here.
    2761             :     // We must check |!isReset| because the Compute*Data functions for
    2762             :     // reset structs wouldn't handle none bits correctly.
    2763        3559 :     if (highestNode != this && !isReset)
    2764         897 :       PropagateNoneBit(bit, highestNode);
    2765             : 
    2766             :     // All information must necessarily be inherited from our parent style context.
    2767             :     // In the absence of any computed data in the rule tree and with
    2768             :     // no rules specified that didn't have values of 'inherit', we should check our parent.
    2769        3559 :     GeckoStyleContext* parentContext = aContext->GetParent();
    2770        3559 :     if (isReset) {
    2771             :       /* Reset structs don't inherit from first-line. */
    2772             :       /* See similar code in COMPUTE_START_RESET */
    2773         122 :       while (parentContext &&
    2774          61 :              parentContext->GetPseudo() == nsCSSPseudoElements::firstLine) {
    2775           0 :         parentContext = parentContext->GetParent();
    2776             :       }
    2777          61 :       if (parentContext && parentContext != aContext->GetParent()) {
    2778           0 :         PropagateGrandancestorBit(aContext, parentContext);
    2779             :       }
    2780             :     }
    2781        3559 :     if (parentContext) {
    2782             :       // We have a parent, and so we should just inherit from the parent.
    2783             :       // Set the inherit bits on our context.  These bits tell the style context that
    2784             :       // it never has to go back to the rule tree for data.  Instead the style context tree
    2785             :       // should be walked to find the data.
    2786        3145 :       const void* parentStruct = parentContext->StyleData(aSID);
    2787        3145 :       aContext->AddStyleBit(bit); // makes const_cast OK.
    2788        3145 :       aContext->SetStyle(aSID, const_cast<void*>(parentStruct));
    2789        3145 :       if (isReset) {
    2790          61 :         parentContext->AddStyleBit(NS_STYLE_HAS_CHILD_THAT_USES_RESET_STYLE);
    2791             :       }
    2792        3145 :       return parentStruct;
    2793             :     }
    2794             :     else
    2795             :       // We are the root.  In the case of fonts, the default values just
    2796             :       // come from the pres context.
    2797         414 :       return SetDefaultOnRoot(aSID, aContext);
    2798             :   }
    2799             : 
    2800             :   typedef const void* (nsRuleNode::*ComputeFunc)(void*, const nsRuleData*,
    2801             :                                                  GeckoStyleContext*, nsRuleNode*,
    2802             :                                                  RuleDetail,
    2803             :                                                  const RuleNodeCacheConditions);
    2804             :   static const ComputeFunc sComputeFuncs[] = {
    2805             : #define STYLE_STRUCT(name, checkdata_cb) &nsRuleNode::Compute##name##Data,
    2806             : #include "nsStyleStructList.h"
    2807             : #undef STYLE_STRUCT
    2808             :   };
    2809             : 
    2810             :   // We need to compute the data from the information that the rules specified.
    2811       12225 :   return (this->*sComputeFuncs[aSID])(startStruct, &ruleData, aContext,
    2812             :                                       highestNode, detail,
    2813       12225 :                                       ruleData.mConditions);
    2814             : }
    2815             : 
    2816             : const void*
    2817         414 : nsRuleNode::SetDefaultOnRoot(const nsStyleStructID aSID, GeckoStyleContext* aContext)
    2818             : {
    2819         414 :   switch (aSID) {
    2820             :     case eStyleStruct_Font:
    2821             :     {
    2822           8 :       nsStyleFont* fontData = new (mPresContext) nsStyleFont(mPresContext);
    2823           8 :       nscoord minimumFontSize = mPresContext->MinFontSize(fontData->mLanguage);
    2824             : 
    2825           8 :       if (minimumFontSize > 0 && !mPresContext->IsChrome()) {
    2826           0 :         fontData->mFont.size = std::max(fontData->mSize, minimumFontSize);
    2827             :       }
    2828             :       else {
    2829           8 :         fontData->mFont.size = fontData->mSize;
    2830             :       }
    2831           8 :       aContext->SetStyle(eStyleStruct_Font, fontData);
    2832           8 :       return fontData;
    2833             :     }
    2834             :     case eStyleStruct_Display:
    2835             :     {
    2836           0 :       nsStyleDisplay* disp = new (mPresContext) nsStyleDisplay(mPresContext);
    2837           0 :       aContext->SetStyle(eStyleStruct_Display, disp);
    2838           0 :       return disp;
    2839             :     }
    2840             :     case eStyleStruct_Visibility:
    2841             :     {
    2842         129 :       nsStyleVisibility* vis = new (mPresContext) nsStyleVisibility(mPresContext);
    2843         129 :       aContext->SetStyle(eStyleStruct_Visibility, vis);
    2844         129 :       return vis;
    2845             :     }
    2846             :     case eStyleStruct_Text:
    2847             :     {
    2848          52 :       nsStyleText* text = new (mPresContext) nsStyleText(mPresContext);
    2849          52 :       aContext->SetStyle(eStyleStruct_Text, text);
    2850          52 :       return text;
    2851             :     }
    2852             :     case eStyleStruct_TextReset:
    2853             :     {
    2854           0 :       nsStyleTextReset* text = new (mPresContext) nsStyleTextReset(mPresContext);
    2855           0 :       aContext->SetStyle(eStyleStruct_TextReset, text);
    2856           0 :       return text;
    2857             :     }
    2858             :     case eStyleStruct_Color:
    2859             :     {
    2860          25 :       nsStyleColor* color = new (mPresContext) nsStyleColor(mPresContext);
    2861          25 :       aContext->SetStyle(eStyleStruct_Color, color);
    2862          25 :       return color;
    2863             :     }
    2864             :     case eStyleStruct_Background:
    2865             :     {
    2866           0 :       nsStyleBackground* bg = new (mPresContext) nsStyleBackground(mPresContext);
    2867           0 :       aContext->SetStyle(eStyleStruct_Background, bg);
    2868           0 :       return bg;
    2869             :     }
    2870             :     case eStyleStruct_Margin:
    2871             :     {
    2872           0 :       nsStyleMargin* margin = new (mPresContext) nsStyleMargin(mPresContext);
    2873           0 :       aContext->SetStyle(eStyleStruct_Margin, margin);
    2874           0 :       return margin;
    2875             :     }
    2876             :     case eStyleStruct_Border:
    2877             :     {
    2878           0 :       nsStyleBorder* border = new (mPresContext) nsStyleBorder(mPresContext);
    2879           0 :       aContext->SetStyle(eStyleStruct_Border, border);
    2880           0 :       return border;
    2881             :     }
    2882             :     case eStyleStruct_Padding:
    2883             :     {
    2884           0 :       nsStylePadding* padding = new (mPresContext) nsStylePadding(mPresContext);
    2885           0 :       aContext->SetStyle(eStyleStruct_Padding, padding);
    2886           0 :       return padding;
    2887             :     }
    2888             :     case eStyleStruct_Outline:
    2889             :     {
    2890           0 :       nsStyleOutline* outline = new (mPresContext) nsStyleOutline(mPresContext);
    2891           0 :       aContext->SetStyle(eStyleStruct_Outline, outline);
    2892           0 :       return outline;
    2893             :     }
    2894             :     case eStyleStruct_List:
    2895             :     {
    2896           3 :       nsStyleList* list = new (mPresContext) nsStyleList(mPresContext);
    2897           3 :       aContext->SetStyle(eStyleStruct_List, list);
    2898           3 :       return list;
    2899             :     }
    2900             :     case eStyleStruct_Position:
    2901             :     {
    2902           0 :       nsStylePosition* pos = new (mPresContext) nsStylePosition(mPresContext);
    2903           0 :       aContext->SetStyle(eStyleStruct_Position, pos);
    2904           0 :       return pos;
    2905             :     }
    2906             :     case eStyleStruct_Table:
    2907             :     {
    2908           0 :       nsStyleTable* table = new (mPresContext) nsStyleTable(mPresContext);
    2909           0 :       aContext->SetStyle(eStyleStruct_Table, table);
    2910           0 :       return table;
    2911             :     }
    2912             :     case eStyleStruct_TableBorder:
    2913             :     {
    2914           0 :       nsStyleTableBorder* table = new (mPresContext) nsStyleTableBorder(mPresContext);
    2915           0 :       aContext->SetStyle(eStyleStruct_TableBorder, table);
    2916           0 :       return table;
    2917             :     }
    2918             :     case eStyleStruct_Content:
    2919             :     {
    2920           0 :       nsStyleContent* content = new (mPresContext) nsStyleContent(mPresContext);
    2921           0 :       aContext->SetStyle(eStyleStruct_Content, content);
    2922           0 :       return content;
    2923             :     }
    2924             :     case eStyleStruct_UserInterface:
    2925             :     {
    2926         174 :       nsStyleUserInterface* ui = new (mPresContext) nsStyleUserInterface(mPresContext);
    2927         174 :       aContext->SetStyle(eStyleStruct_UserInterface, ui);
    2928         174 :       return ui;
    2929             :     }
    2930             :     case eStyleStruct_UIReset:
    2931             :     {
    2932           0 :       nsStyleUIReset* ui = new (mPresContext) nsStyleUIReset(mPresContext);
    2933           0 :       aContext->SetStyle(eStyleStruct_UIReset, ui);
    2934           0 :       return ui;
    2935             :     }
    2936             :     case eStyleStruct_XUL:
    2937             :     {
    2938           0 :       nsStyleXUL* xul = new (mPresContext) nsStyleXUL(mPresContext);
    2939           0 :       aContext->SetStyle(eStyleStruct_XUL, xul);
    2940           0 :       return xul;
    2941             :     }
    2942             :     case eStyleStruct_Column:
    2943             :     {
    2944           0 :       nsStyleColumn* column = new (mPresContext) nsStyleColumn(mPresContext);
    2945           0 :       aContext->SetStyle(eStyleStruct_Column, column);
    2946           0 :       return column;
    2947             :     }
    2948             :     case eStyleStruct_SVG:
    2949             :     {
    2950          23 :       nsStyleSVG* svg = new (mPresContext) nsStyleSVG(mPresContext);
    2951          23 :       aContext->SetStyle(eStyleStruct_SVG, svg);
    2952          23 :       return svg;
    2953             :     }
    2954             :     case eStyleStruct_SVGReset:
    2955             :     {
    2956           0 :       nsStyleSVGReset* svgReset = new (mPresContext) nsStyleSVGReset(mPresContext);
    2957           0 :       aContext->SetStyle(eStyleStruct_SVGReset, svgReset);
    2958           0 :       return svgReset;
    2959             :     }
    2960             :     case eStyleStruct_Variables:
    2961             :     {
    2962           0 :       nsStyleVariables* vars = new (mPresContext) nsStyleVariables(mPresContext);
    2963           0 :       aContext->SetStyle(eStyleStruct_Variables, vars);
    2964           0 :       return vars;
    2965             :     }
    2966             :     case eStyleStruct_Effects:
    2967             :     {
    2968           0 :       nsStyleEffects* effects = new (mPresContext) nsStyleEffects(mPresContext);
    2969           0 :       aContext->SetStyle(eStyleStruct_Effects, effects);
    2970           0 :       return effects;
    2971             :     }
    2972             :     default:
    2973             :       /*
    2974             :        * unhandled case: nsStyleStructID_Length.
    2975             :        * last item of nsStyleStructID, to know its length.
    2976             :        */
    2977           0 :       MOZ_ASSERT(false, "unexpected SID");
    2978             :       return nullptr;
    2979             :   }
    2980             :   return nullptr;
    2981             : }
    2982             : 
    2983             : /**
    2984             :  * Begin an nsRuleNode::Compute*Data function for an inherited struct.
    2985             :  *
    2986             :  * @param type_ The nsStyle* type this function computes.
    2987             :  * @param data_ Variable (declared here) holding the result of this
    2988             :  *              function.
    2989             :  * @param parentdata_ Variable (declared here) holding the parent style
    2990             :  *                    context's data for this struct.
    2991             :  */
    2992             : #define COMPUTE_START_INHERITED(type_, data_, parentdata_)                    \
    2993             :   NS_ASSERTION(aRuleDetail != eRuleFullInherited,                             \
    2994             :                "should not have bothered calling Compute*Data");              \
    2995             :                                                                               \
    2996             :   GeckoStyleContext* parentContext = aContext->GetParent();                   \
    2997             :                                                                               \
    2998             :   nsStyle##type_* data_ = nullptr;                                            \
    2999             :   mozilla::Maybe<nsStyle##type_> maybeFakeParentData;                         \
    3000             :   const nsStyle##type_* parentdata_ = nullptr;                                \
    3001             :   RuleNodeCacheConditions conditions = aConditions;                           \
    3002             :                                                                               \
    3003             :   /* If |conditions.Cacheable()| might be true by the time we're done, we */  \
    3004             :   /* can't call parentContext->Style##type_() since it could recur into */    \
    3005             :   /* setting the same struct on the same rule node, causing a leak. */        \
    3006             :   if (aRuleDetail != eRuleFullReset &&                                        \
    3007             :       (!aStartStruct || (aRuleDetail != eRulePartialReset &&                  \
    3008             :                          aRuleDetail != eRuleNone))) {                        \
    3009             :     if (parentContext) {                                                      \
    3010             :       parentdata_ = parentContext->Style##type_();                            \
    3011             :     } else {                                                                  \
    3012             :       maybeFakeParentData.emplace(mPresContext);                              \
    3013             :       parentdata_ = maybeFakeParentData.ptr();                                \
    3014             :     }                                                                         \
    3015             :   }                                                                           \
    3016             :   if (eStyleStruct_##type_ == eStyleStruct_Variables)                         \
    3017             :     /* no need to copy construct an nsStyleVariables, as we will copy */      \
    3018             :     /* inherited variables (and call SetUncacheable()) in */                  \
    3019             :     /* ComputeVariablesData */                                                \
    3020             :     data_ = new (mPresContext) nsStyle##type_(mPresContext);                  \
    3021             :   else if (aStartStruct)                                                      \
    3022             :     /* We only need to compute the delta between this computed data and */    \
    3023             :     /* our computed data. */                                                  \
    3024             :     data_ = new (mPresContext)                                                \
    3025             :             nsStyle##type_(*static_cast<nsStyle##type_*>(aStartStruct));      \
    3026             :   else {                                                                      \
    3027             :     if (aRuleDetail != eRuleFullMixed && aRuleDetail != eRuleFullReset) {     \
    3028             :       /* No question. We will have to inherit. Go ahead and init */           \
    3029             :       /* with inherited vals from parent. */                                  \
    3030             :       conditions.SetUncacheable();                                            \
    3031             :       if (parentdata_)                                                        \
    3032             :         data_ = new (mPresContext) nsStyle##type_(*parentdata_);              \
    3033             :       else                                                                    \
    3034             :         data_ = new (mPresContext) nsStyle##type_(mPresContext);              \
    3035             :     }                                                                         \
    3036             :     else                                                                      \
    3037             :       data_ = new (mPresContext) nsStyle##type_(mPresContext);                \
    3038             :   }                                                                           \
    3039             :                                                                               \
    3040             :   if (!parentdata_)                                                           \
    3041             :     parentdata_ = data_;
    3042             : 
    3043             : /**
    3044             :  * Begin an nsRuleNode::Compute*Data function for a reset struct.
    3045             :  *
    3046             :  * @param type_ The nsStyle* type this function computes.
    3047             :  * @param data_ Variable (declared here) holding the result of this
    3048             :  *              function.
    3049             :  * @param parentdata_ Variable (declared here) holding the parent style
    3050             :  *                    context's data for this struct.
    3051             :  */
    3052             : #define COMPUTE_START_RESET(type_, data_, parentdata_)                        \
    3053             :   NS_ASSERTION(aRuleDetail != eRuleFullInherited,                             \
    3054             :                "should not have bothered calling Compute*Data");              \
    3055             :                                                                               \
    3056             :   GeckoStyleContext* parentContext = aContext->GetParent();                   \
    3057             :   /* Reset structs don't inherit from first-line */                           \
    3058             :   /* See similar code in WalkRuleTree */                                      \
    3059             :   while (parentContext &&                                                     \
    3060             :          parentContext->GetPseudo() == nsCSSPseudoElements::firstLine) {      \
    3061             :     parentContext = parentContext->GetParent();                               \
    3062             :   }                                                                           \
    3063             :                                                                               \
    3064             :   nsStyle##type_* data_;                                                      \
    3065             :   if (aStartStruct)                                                           \
    3066             :     /* We only need to compute the delta between this computed data and */    \
    3067             :     /* our computed data. */                                                  \
    3068             :     data_ = new (mPresContext)                                                \
    3069             :             nsStyle##type_(*static_cast<nsStyle##type_*>(aStartStruct));      \
    3070             :   else                                                                        \
    3071             :     data_ = new (mPresContext) nsStyle##type_(mPresContext);                  \
    3072             :                                                                               \
    3073             :   /* If |conditions.Cacheable()| might be true by the time we're done, we */  \
    3074             :   /* can't call parentContext->Style##type_() since it could recur into */    \
    3075             :   /* setting the same struct on the same rule node, causing a leak. */        \
    3076             :   mozilla::Maybe<nsStyle##type_> maybeFakeParentData;                         \
    3077             :   const nsStyle##type_* parentdata_ = data_;                                  \
    3078             :   if (aRuleDetail != eRuleFullReset &&                                        \
    3079             :       aRuleDetail != eRulePartialReset &&                                     \
    3080             :       aRuleDetail != eRuleNone) {                                             \
    3081             :     if (parentContext) {                                                      \
    3082             :       parentdata_ = parentContext->Style##type_();                            \
    3083             :     } else {                                                                  \
    3084             :       maybeFakeParentData.emplace(mPresContext);                              \
    3085             :       parentdata_ = maybeFakeParentData.ptr();                                \
    3086             :     }                                                                         \
    3087             :   }                                                                           \
    3088             :   RuleNodeCacheConditions conditions = aConditions;
    3089             : 
    3090             : /**
    3091             :  * End an nsRuleNode::Compute*Data function for an inherited struct.
    3092             :  *
    3093             :  * @param type_ The nsStyle* type this function computes.
    3094             :  * @param data_ Variable holding the result of this function.
    3095             :  */
    3096             : #define COMPUTE_END_INHERITED(type_, data_)                                   \
    3097             :   NS_POSTCONDITION(!conditions.CacheableWithoutDependencies() ||              \
    3098             :                    aRuleDetail == eRuleFullReset ||                           \
    3099             :                    (aStartStruct && aRuleDetail == eRulePartialReset),        \
    3100             :                    "conditions.CacheableWithoutDependencies() must be false " \
    3101             :                    "for inherited structs unless all properties have been "   \
    3102             :                    "specified with values other than inherit");               \
    3103             :   if (conditions.CacheableWithoutDependencies()) {                            \
    3104             :     /* We were fully specified and can therefore be cached right on the */    \
    3105             :     /* rule node. */                                                          \
    3106             :     if (!aHighestNode->mStyleData.mInheritedData) {                           \
    3107             :       aHighestNode->mStyleData.mInheritedData =                               \
    3108             :         new (mPresContext) nsInheritedStyleData;                              \
    3109             :     }                                                                         \
    3110             :     NS_ASSERTION(!aHighestNode->mStyleData.mInheritedData->                   \
    3111             :                    mStyleStructs[eStyleStruct_##type_],                       \
    3112             :                  "Going to leak style data");                                 \
    3113             :     aHighestNode->mStyleData.mInheritedData->                                 \
    3114             :       mStyleStructs[eStyleStruct_##type_] = data_;                            \
    3115             :     /* Propagate the bit down. */                                             \
    3116             :     PropagateDependentBit(eStyleStruct_##type_, aHighestNode, data_);         \
    3117             :     /* Tell the style context that it doesn't own the data */                 \
    3118             :     aContext->AddStyleBit(NS_STYLE_INHERIT_BIT(type_));                       \
    3119             :   }                                                                           \
    3120             :   /* For inherited structs, our caller will cache the data on the */          \
    3121             :   /* style context */                                                         \
    3122             :                                                                               \
    3123             :   return data_;
    3124             : 
    3125             : /**
    3126             :  * End an nsRuleNode::Compute*Data function for a reset struct.
    3127             :  *
    3128             :  * @param type_ The nsStyle* type this function computes.
    3129             :  * @param data_ Variable holding the result of this function.
    3130             :  */
    3131             : #define COMPUTE_END_RESET(type_, data_)                                       \
    3132             :   NS_POSTCONDITION(!conditions.CacheableWithoutDependencies() ||              \
    3133             :                    aRuleDetail == eRuleNone ||                                \
    3134             :                    aRuleDetail == eRulePartialReset ||                        \
    3135             :                    aRuleDetail == eRuleFullReset,                             \
    3136             :                    "conditions.CacheableWithoutDependencies() must be false " \
    3137             :                    "for reset structs if any properties were specified as "   \
    3138             :                    "inherit");                                                \
    3139             :   if (conditions.CacheableWithoutDependencies()) {                            \
    3140             :     /* We were fully specified and can therefore be cached right on the */    \
    3141             :     /* rule node. */                                                          \
    3142             :     if (!aHighestNode->mStyleData.mResetData) {                               \
    3143             :       aHighestNode->mStyleData.mResetData =                                   \
    3144             :         new (mPresContext) nsConditionalResetStyleData;                       \
    3145             :     }                                                                         \
    3146             :     NS_ASSERTION(!aHighestNode->mStyleData.mResetData->                       \
    3147             :                    GetStyleData(eStyleStruct_##type_),                        \
    3148             :                  "Going to leak style data");                                 \
    3149             :     aHighestNode->mStyleData.mResetData->                                     \
    3150             :       SetStyleData(eStyleStruct_##type_, data_);                              \
    3151             :     /* Propagate the bit down. */                                             \
    3152             :     PropagateDependentBit(eStyleStruct_##type_, aHighestNode, data_);         \
    3153             :     if (HasAnimationData()) {                                                 \
    3154             :       /* If we have animation data, the struct should be cached on the */     \
    3155             :       /* style context so that we can peek the struct. */                     \
    3156             :       /* See comment in AnimValuesStyleRule::MapRuleInfoInto. */              \
    3157             :       StoreStyleOnContext(aContext, eStyleStruct_##type_, data_);             \
    3158             :     }                                                                         \
    3159             :   } else if (conditions.Cacheable()) {                                        \
    3160             :     if (!mStyleData.mResetData) {                                             \
    3161             :       mStyleData.mResetData = new (mPresContext) nsConditionalResetStyleData; \
    3162             :     }                                                                         \
    3163             :     mStyleData.mResetData->                                                   \
    3164             :       SetStyleData(eStyleStruct_##type_, mPresContext, data_, conditions);    \
    3165             :     /* Tell the style context that it doesn't own the data */                 \
    3166             :     aContext->AddStyleBit(NS_STYLE_INHERIT_BIT(type_));                       \
    3167             :     aContext->SetStyle(eStyleStruct_##type_, data_);                          \
    3168             :   } else {                                                                    \
    3169             :     /* We can't be cached in the rule node.  We have to be put right */       \
    3170             :     /* on the style context. */                                               \
    3171             :     aContext->SetStyle(eStyleStruct_##type_, data_);                          \
    3172             :     if (aContext->GetParent()) {                                              \
    3173             :       /* This is pessimistic; we could be uncacheable because we had a */     \
    3174             :       /* relative font-weight, for example, which does not need to defeat */  \
    3175             :       /* the restyle optimizations in RestyleManager.cpp that look at */      \
    3176             :       /* NS_STYLE_HAS_CHILD_THAT_USES_RESET_STYLE. */                         \
    3177             :       aContext->GetParent()->                                                 \
    3178             :         AddStyleBit(NS_STYLE_HAS_CHILD_THAT_USES_RESET_STYLE);                \
    3179             :     }                                                                         \
    3180             :   }                                                                           \
    3181             :                                                                               \
    3182             :   return data_;
    3183             : 
    3184             : // This function figures out how much scaling should be suppressed to
    3185             : // satisfy scriptminsize. This is our attempt to implement
    3186             : // http://www.w3.org/TR/MathML2/chapter3.html#id.3.3.4.2.2
    3187             : // This is called after mScriptLevel, mScriptMinSize and mScriptSizeMultiplier
    3188             : // have been set in aFont.
    3189             : //
    3190             : // Here are the invariants we enforce:
    3191             : // 1) A decrease in size must not reduce the size below minscriptsize.
    3192             : // 2) An increase in size must not increase the size above the size we would
    3193             : // have if minscriptsize had not been applied anywhere.
    3194             : // 3) The scriptlevel-induced size change must between 1.0 and the parent's
    3195             : // scriptsizemultiplier^(new script level - old script level), as close to the
    3196             : // latter as possible subject to constraints 1 and 2.
    3197             : static nscoord
    3198          12 : ComputeScriptLevelSize(const nsStyleFont* aFont, const nsStyleFont* aParentFont,
    3199             :                        nsPresContext* aPresContext, nscoord* aUnconstrainedSize)
    3200             : {
    3201             :   int32_t scriptLevelChange =
    3202          12 :     aFont->mScriptLevel - aParentFont->mScriptLevel;
    3203          12 :   if (scriptLevelChange == 0) {
    3204          12 :     *aUnconstrainedSize = aParentFont->mScriptUnconstrainedSize;
    3205             :     // Constraint #3 says that we cannot change size, and #1 and #2 are always
    3206             :     // satisfied with no change. It's important this be fast because it covers
    3207             :     // all non-MathML content.
    3208          12 :     return aParentFont->mSize;
    3209             :   }
    3210             : 
    3211             :   // Compute actual value of minScriptSize
    3212           0 :   nscoord minScriptSize = aParentFont->mScriptMinSize;
    3213           0 :   if (aFont->mAllowZoom) {
    3214           0 :     minScriptSize = nsStyleFont::ZoomText(aPresContext, minScriptSize);
    3215             :   }
    3216             : 
    3217             :   double scriptLevelScale =
    3218           0 :     pow(aParentFont->mScriptSizeMultiplier, scriptLevelChange);
    3219             :   // Compute the size we would have had if minscriptsize had never been
    3220             :   // applied, also prevent overflow (bug 413274)
    3221           0 :   *aUnconstrainedSize =
    3222           0 :     NSToCoordRoundWithClamp(aParentFont->mScriptUnconstrainedSize*scriptLevelScale);
    3223             :   // Compute the size we could get via scriptlevel change
    3224             :   nscoord scriptLevelSize =
    3225           0 :     NSToCoordRoundWithClamp(aParentFont->mSize*scriptLevelScale);
    3226           0 :   if (scriptLevelScale <= 1.0) {
    3227           0 :     if (aParentFont->mSize <= minScriptSize) {
    3228             :       // We can't decrease the font size at all, so just stick to no change
    3229             :       // (authors are allowed to explicitly set the font size smaller than
    3230             :       // minscriptsize)
    3231           0 :       return aParentFont->mSize;
    3232             :     }
    3233             :     // We can decrease, so apply constraint #1
    3234           0 :     return std::max(minScriptSize, scriptLevelSize);
    3235             :   } else {
    3236             :     // scriptminsize can only make sizes larger than the unconstrained size
    3237           0 :     NS_ASSERTION(*aUnconstrainedSize <= scriptLevelSize, "How can this ever happen?");
    3238             :     // Apply constraint #2
    3239           0 :     return std::min(scriptLevelSize, std::max(*aUnconstrainedSize, minScriptSize));
    3240             :   }
    3241             : }
    3242             : 
    3243             : 
    3244             : /* static */ nscoord
    3245           0 : nsRuleNode::CalcFontPointSize(int32_t aHTMLSize, int32_t aBasePointSize,
    3246             :                               nsPresContext* aPresContext,
    3247             :                               nsFontSizeType aFontSizeType)
    3248             : {
    3249             : #define sFontSizeTableMin  9
    3250             : #define sFontSizeTableMax 16
    3251             : 
    3252             : // This table seems to be the one used by MacIE5. We hope its adoption in Mozilla
    3253             : // and eventually in WinIE5.5 will help to establish a standard rendering across
    3254             : // platforms and browsers. For now, it is used only in Strict mode. More can be read
    3255             : // in the document written by Todd Farhner at:
    3256             : // http://style.verso.com/font_size_intervals/altintervals.html
    3257             : //
    3258             :   static int32_t sStrictFontSizeTable[sFontSizeTableMax - sFontSizeTableMin + 1][8] =
    3259             :   {
    3260             :       { 9,    9,     9,     9,    11,    14,    18,    27},
    3261             :       { 9,    9,     9,    10,    12,    15,    20,    30},
    3262             :       { 9,    9,    10,    11,    13,    17,    22,    33},
    3263             :       { 9,    9,    10,    12,    14,    18,    24,    36},
    3264             :       { 9,   10,    12,    13,    16,    20,    26,    39},
    3265             :       { 9,   10,    12,    14,    17,    21,    28,    42},
    3266             :       { 9,   10,    13,    15,    18,    23,    30,    45},
    3267             :       { 9,   10,    13,    16,    18,    24,    32,    48}
    3268             :   };
    3269             : // HTML       1      2      3      4      5      6      7
    3270             : // CSS  xxs   xs     s      m      l     xl     xxl
    3271             : //                          |
    3272             : //                      user pref
    3273             : //
    3274             : //------------------------------------------------------------
    3275             : //
    3276             : // This table gives us compatibility with WinNav4 for the default fonts only.
    3277             : // In WinNav4, the default fonts were:
    3278             : //
    3279             : //     Times/12pt ==   Times/16px at 96ppi
    3280             : //   Courier/10pt == Courier/13px at 96ppi
    3281             : //
    3282             : // The 2 lines below marked "anchored" have the exact pixel sizes used by
    3283             : // WinNav4 for Times/12pt and Courier/10pt at 96ppi. As you can see, the
    3284             : // HTML size 3 (user pref) for those 2 anchored lines is 13px and 16px.
    3285             : //
    3286             : // All values other than the anchored values were filled in by hand, never
    3287             : // going below 9px, and maintaining a "diagonal" relationship. See for
    3288             : // example the 13s -- they follow a diagonal line through the table.
    3289             : //
    3290             :   static int32_t sQuirksFontSizeTable[sFontSizeTableMax - sFontSizeTableMin + 1][8] =
    3291             :   {
    3292             :       { 9,    9,     9,     9,    11,    14,    18,    28 },
    3293             :       { 9,    9,     9,    10,    12,    15,    20,    31 },
    3294             :       { 9,    9,     9,    11,    13,    17,    22,    34 },
    3295             :       { 9,    9,    10,    12,    14,    18,    24,    37 },
    3296             :       { 9,    9,    10,    13,    16,    20,    26,    40 }, // anchored (13)
    3297             :       { 9,    9,    11,    14,    17,    21,    28,    42 },
    3298             :       { 9,   10,    12,    15,    17,    23,    30,    45 },
    3299             :       { 9,   10,    13,    16,    18,    24,    32,    48 }  // anchored (16)
    3300             :   };
    3301             : // HTML       1      2      3      4      5      6      7
    3302             : // CSS  xxs   xs     s      m      l     xl     xxl
    3303             : //                          |
    3304             : //                      user pref
    3305             : 
    3306             : #if 0
    3307             : //
    3308             : // These are the exact pixel values used by WinIE5 at 96ppi.
    3309             : //
    3310             :       { ?,    8,    11,    12,    13,    16,    21,    32 }, // smallest
    3311             :       { ?,    9,    12,    13,    16,    21,    27,    40 }, // smaller
    3312             :       { ?,   10,    13,    16,    18,    24,    32,    48 }, // medium
    3313             :       { ?,   13,    16,    19,    21,    27,    37,    ?? }, // larger
    3314             :       { ?,   16,    19,    21,    24,    32,    43,    ?? }  // largest
    3315             : //
    3316             : // HTML       1      2      3      4      5      6      7
    3317             : // CSS  ?     ?      ?      ?      ?      ?      ?      ?
    3318             : //
    3319             : // (CSS not tested yet.)
    3320             : //
    3321             : #endif
    3322             : 
    3323             :   static int32_t sFontSizeFactors[8] = { 60,75,89,100,120,150,200,300 };
    3324             : 
    3325             :   static int32_t sCSSColumns[7]  = {0, 1, 2, 3, 4, 5, 6}; // xxs...xxl
    3326             :   static int32_t sHTMLColumns[7] = {1, 2, 3, 4, 5, 6, 7}; // 1...7
    3327             : 
    3328             :   double dFontSize;
    3329             : 
    3330           0 :   if (aFontSizeType == eFontSize_HTML) {
    3331           0 :     aHTMLSize--;    // input as 1-7
    3332             :   }
    3333             : 
    3334           0 :   if (aHTMLSize < 0)
    3335           0 :     aHTMLSize = 0;
    3336           0 :   else if (aHTMLSize > 6)
    3337           0 :     aHTMLSize = 6;
    3338             : 
    3339             :   int32_t* column;
    3340           0 :   switch (aFontSizeType)
    3341             :   {
    3342           0 :     case eFontSize_HTML: column = sHTMLColumns; break;
    3343           0 :     case eFontSize_CSS:  column = sCSSColumns;  break;
    3344             :   }
    3345             : 
    3346             :   // Make special call specifically for fonts (needed PrintPreview)
    3347           0 :   int32_t fontSize = nsPresContext::AppUnitsToIntCSSPixels(aBasePointSize);
    3348             : 
    3349           0 :   if ((fontSize >= sFontSizeTableMin) && (fontSize <= sFontSizeTableMax))
    3350             :   {
    3351           0 :     int32_t row = fontSize - sFontSizeTableMin;
    3352             : 
    3353           0 :     if (aPresContext->CompatibilityMode() == eCompatibility_NavQuirks) {
    3354           0 :       dFontSize = nsPresContext::CSSPixelsToAppUnits(sQuirksFontSizeTable[row][column[aHTMLSize]]);
    3355             :     } else {
    3356           0 :       dFontSize = nsPresContext::CSSPixelsToAppUnits(sStrictFontSizeTable[row][column[aHTMLSize]]);
    3357           0 :     }
    3358             :   }
    3359             :   else
    3360             :   {
    3361           0 :     int32_t factor = sFontSizeFactors[column[aHTMLSize]];
    3362           0 :     dFontSize = (factor * aBasePointSize) / 100;
    3363             :   }
    3364             : 
    3365             : 
    3366           0 :   if (1.0 < dFontSize) {
    3367           0 :     return (nscoord)dFontSize;
    3368             :   }
    3369           0 :   return (nscoord)1;
    3370             : }
    3371             : 
    3372             : struct SetFontSizeCalcOps : public css::BasicCoordCalcOps,
    3373             :                             public css::FloatCoeffsAlreadyNormalizedOps
    3374             : {
    3375             :   // Declare that we have floats as coefficients so that we unambiguously
    3376             :   // resolve coeff_type (BasicCoordCalcOps and FloatCoeffsAlreadyNormalizedOps
    3377             :   // both have |typedef float coeff_type|).
    3378             :   typedef float coeff_type;
    3379             : 
    3380             :   // The parameters beyond aValue that we need for CalcLengthWith.
    3381             :   const nscoord mParentSize;
    3382             :   const nsStyleFont* const mParentFont;
    3383             :   nsPresContext* const mPresContext;
    3384             :   GeckoStyleContext* const mStyleContext;
    3385             :   const bool mAtRoot;
    3386             :   RuleNodeCacheConditions& mConditions;
    3387             : 
    3388           0 :   SetFontSizeCalcOps(nscoord aParentSize, const nsStyleFont* aParentFont,
    3389             :                      nsPresContext* aPresContext,
    3390             :                      GeckoStyleContext* aStyleContext,
    3391             :                      bool aAtRoot,
    3392             :                      RuleNodeCacheConditions& aConditions)
    3393           0 :     : mParentSize(aParentSize),
    3394             :       mParentFont(aParentFont),
    3395             :       mPresContext(aPresContext),
    3396             :       mStyleContext(aStyleContext),
    3397             :       mAtRoot(aAtRoot),
    3398           0 :       mConditions(aConditions)
    3399             :   {
    3400           0 :   }
    3401             : 
    3402           0 :   result_type ComputeLeafValue(const nsCSSValue& aValue)
    3403             :   {
    3404             :     nscoord size;
    3405           0 :     if (aValue.IsLengthUnit()) {
    3406             :       // Note that font-based length units use the parent's size
    3407             :       // unadjusted for scriptlevel changes. A scriptlevel change
    3408             :       // between us and the parent is simply ignored.
    3409           0 :       size = CalcLengthWith(aValue, mParentSize,
    3410           0 :                             mParentFont,
    3411           0 :                             mStyleContext, mPresContext, mAtRoot,
    3412           0 :                             true, mConditions);
    3413           0 :       if (!aValue.IsRelativeLengthUnit() && mParentFont->mAllowZoom) {
    3414           0 :         size = nsStyleFont::ZoomText(mPresContext, size);
    3415             :       }
    3416             :     }
    3417           0 :     else if (eCSSUnit_Percent == aValue.GetUnit()) {
    3418           0 :       mConditions.SetUncacheable();
    3419             :       // Note that % units use the parent's size unadjusted for scriptlevel
    3420             :       // changes. A scriptlevel change between us and the parent is simply
    3421             :       // ignored.
    3422             :       // aValue.GetPercentValue() may be negative for, e.g., calc(-50%)
    3423           0 :       size = NSCoordSaturatingMultiply(mParentSize, aValue.GetPercentValue());
    3424             :     } else {
    3425           0 :       MOZ_ASSERT(false, "unexpected value");
    3426             :       size = mParentSize;
    3427             :     }
    3428             : 
    3429           0 :     return size;
    3430             :   }
    3431             : };
    3432             : 
    3433             : /* static */ void
    3434          12 : nsRuleNode::SetFontSize(nsPresContext* aPresContext,
    3435             :                         GeckoStyleContext* aContext,
    3436             :                         const nsRuleData* aRuleData,
    3437             :                         const nsStyleFont* aFont,
    3438             :                         const nsStyleFont* aParentFont,
    3439             :                         nscoord* aSize,
    3440             :                         const nsFont& aSystemFont,
    3441             :                         nscoord aParentSize,
    3442             :                         nscoord aScriptLevelAdjustedParentSize,
    3443             :                         bool aUsedStartStruct,
    3444             :                         bool aAtRoot,
    3445             :                         RuleNodeCacheConditions& aConditions)
    3446             : {
    3447             :   // If false, means that *aSize has not been zoomed.  If true, means that
    3448             :   // *aSize has been zoomed iff aParentFont->mAllowZoom is true.
    3449          12 :   bool sizeIsZoomedAccordingToParent = false;
    3450             : 
    3451             :   int32_t baseSize = (int32_t) aPresContext->
    3452          12 :     GetDefaultFont(aFont->mGenericID, aFont->mLanguage)->size;
    3453          12 :   const nsCSSValue* sizeValue = aRuleData->ValueForFontSize();
    3454          12 :   if (eCSSUnit_Enumerated == sizeValue->GetUnit()) {
    3455           0 :     int32_t value = sizeValue->GetIntValue();
    3456             : 
    3457           0 :     if ((NS_STYLE_FONT_SIZE_XXSMALL <= value) &&
    3458             :         (value <= NS_STYLE_FONT_SIZE_XXLARGE)) {
    3459           0 :       *aSize = CalcFontPointSize(value, baseSize,
    3460           0 :                        aPresContext, eFontSize_CSS);
    3461             :     }
    3462           0 :     else if (NS_STYLE_FONT_SIZE_XXXLARGE == value) {
    3463             :       // <font size="7"> is not specified in CSS, so we don't use eFontSize_CSS.
    3464           0 :       *aSize = CalcFontPointSize(value, baseSize, aPresContext);
    3465             :     }
    3466           0 :     else if (NS_STYLE_FONT_SIZE_LARGER  == value ||
    3467             :              NS_STYLE_FONT_SIZE_SMALLER == value) {
    3468           0 :       aConditions.SetUncacheable();
    3469             : 
    3470             :       // Un-zoom so we use the tables correctly.  We'll then rezoom due
    3471             :       // to the |zoom = true| above.
    3472             :       // Note that relative units here use the parent's size unadjusted
    3473             :       // for scriptlevel changes. A scriptlevel change between us and the parent
    3474             :       // is simply ignored.
    3475           0 :       nscoord parentSize = aParentSize;
    3476           0 :       if (aParentFont->mAllowZoom) {
    3477           0 :         parentSize = nsStyleFont::UnZoomText(aPresContext, parentSize);
    3478             :       }
    3479             : 
    3480           0 :       float factor = (NS_STYLE_FONT_SIZE_LARGER == value) ? 1.2f : (1.0f / 1.2f);
    3481             : 
    3482           0 :       *aSize = parentSize * factor;
    3483             : 
    3484             :     } else {
    3485           0 :       NS_NOTREACHED("unexpected value");
    3486             :     }
    3487             :   }
    3488          36 :   else if (sizeValue->IsLengthUnit() ||
    3489          24 :            sizeValue->GetUnit() == eCSSUnit_Percent ||
    3490          12 :            sizeValue->IsCalcUnit()) {
    3491             :     SetFontSizeCalcOps ops(aParentSize, aParentFont,
    3492             :                            aPresContext, aContext,
    3493             :                            aAtRoot,
    3494           0 :                            aConditions);
    3495           0 :     *aSize = css::ComputeCalc(*sizeValue, ops);
    3496           0 :     if (*aSize < 0) {
    3497           0 :       MOZ_ASSERT(sizeValue->IsCalcUnit(),
    3498             :                  "negative lengths and percents should be rejected by parser");
    3499           0 :       *aSize = 0;
    3500             :     }
    3501             :     // The calc ops will always zoom its result according to the value
    3502             :     // of aParentFont->mAllowZoom.
    3503           0 :     sizeIsZoomedAccordingToParent = true;
    3504             :   }
    3505          12 :   else if (eCSSUnit_System_Font == sizeValue->GetUnit()) {
    3506             :     // this becomes our cascading size
    3507           6 :     *aSize = aSystemFont.size;
    3508             :   }
    3509           6 :   else if (eCSSUnit_Inherit == sizeValue->GetUnit() ||
    3510           0 :            eCSSUnit_Unset == sizeValue->GetUnit()) {
    3511           6 :     aConditions.SetUncacheable();
    3512             :     // We apply scriptlevel change for this case, because the default is
    3513             :     // to inherit and we don't want explicit "inherit" to differ from the
    3514             :     // default.
    3515           6 :     *aSize = aScriptLevelAdjustedParentSize;
    3516           6 :     sizeIsZoomedAccordingToParent = true;
    3517             :   }
    3518           0 :   else if (eCSSUnit_Initial == sizeValue->GetUnit()) {
    3519             :     // The initial value is 'medium', which has magical sizing based on
    3520             :     // the generic font family, so do that here too.
    3521           0 :     *aSize = baseSize;
    3522             :   } else {
    3523           0 :     NS_ASSERTION(eCSSUnit_Null == sizeValue->GetUnit(),
    3524             :                  "What kind of font-size value is this?");
    3525             :     // if aUsedStartStruct is true, then every single property in the
    3526             :     // font struct is being set all at once. This means scriptlevel is not
    3527             :     // going to have any influence on the font size; there is no need to
    3528             :     // do anything here.
    3529           0 :     if (!aUsedStartStruct && aParentSize != aScriptLevelAdjustedParentSize) {
    3530             :       // There was no rule affecting the size but the size has been
    3531             :       // affected by the parent's size via scriptlevel change. So we cannot
    3532             :       // store the data in the rule tree.
    3533           0 :       aConditions.SetUncacheable();
    3534           0 :       *aSize = aScriptLevelAdjustedParentSize;
    3535           0 :       sizeIsZoomedAccordingToParent = true;
    3536             :     } else {
    3537           0 :       return;
    3538             :     }
    3539             :   }
    3540             : 
    3541             :   // We want to zoom the cascaded size so that em-based measurements,
    3542             :   // line-heights, etc., work.
    3543          18 :   bool currentlyZoomed = sizeIsZoomedAccordingToParent &&
    3544          18 :                          aParentFont->mAllowZoom;
    3545          12 :   if (!currentlyZoomed && aFont->mAllowZoom) {
    3546           6 :     *aSize = nsStyleFont::ZoomText(aPresContext, *aSize);
    3547           6 :   } else if (currentlyZoomed && !aFont->mAllowZoom) {
    3548           0 :     *aSize = nsStyleFont::UnZoomText(aPresContext, *aSize);
    3549             :   }
    3550             : }
    3551             : 
    3552           0 : static int8_t ClampTo8Bit(int32_t aValue) {
    3553           0 :   if (aValue < -128)
    3554           0 :     return -128;
    3555           0 :   if (aValue > 127)
    3556           0 :     return 127;
    3557           0 :   return int8_t(aValue);
    3558             : }
    3559             : 
    3560             : /* static */ void
    3561           6 : nsRuleNode::ComputeSystemFont(nsFont* aSystemFont, LookAndFeel::FontID aFontID,
    3562             :                               const nsPresContext* aPresContext,
    3563             :                               const nsFont* aDefaultVariableFont)
    3564             : {
    3565          12 :   gfxFontStyle fontStyle;
    3566             :   float devPerCSS =
    3567          12 :     (float)nsPresContext::AppUnitsPerCSSPixel() /
    3568          12 :     aPresContext->DeviceContext()->AppUnitsPerDevPixelAtUnitFullZoom();
    3569          12 :   nsAutoString systemFontName;
    3570           6 :   if (LookAndFeel::GetFont(aFontID, systemFontName, fontStyle, devPerCSS)) {
    3571           6 :     systemFontName.Trim("\"'");
    3572           6 :     aSystemFont->fontlist = FontFamilyList(systemFontName, eUnquotedName);
    3573           6 :     aSystemFont->fontlist.SetDefaultFontType(eFamily_none);
    3574           6 :     aSystemFont->style = fontStyle.style;
    3575           6 :     aSystemFont->systemFont = fontStyle.systemFont;
    3576           6 :     aSystemFont->weight = fontStyle.weight;
    3577           6 :     aSystemFont->stretch = fontStyle.stretch;
    3578           6 :     aSystemFont->size =
    3579           6 :       NSFloatPixelsToAppUnits(fontStyle.size,
    3580             :                               aPresContext->DeviceContext()->
    3581           6 :                                 AppUnitsPerDevPixelAtUnitFullZoom());
    3582             :     //aSystemFont->langGroup = fontStyle.langGroup;
    3583           6 :     aSystemFont->sizeAdjust = fontStyle.sizeAdjust;
    3584             : 
    3585             : #ifdef XP_WIN
    3586             :     // XXXldb This platform-specific stuff should be in the
    3587             :     // LookAndFeel implementation, not here.
    3588             :     // XXXzw Should we even still *have* this code?  It looks to be making
    3589             :     // old, probably obsolete assumptions.
    3590             : 
    3591             :     if (aFontID == LookAndFeel::eFont_Field ||
    3592             :         aFontID == LookAndFeel::eFont_Button ||
    3593             :         aFontID == LookAndFeel::eFont_List) {
    3594             :       // As far as I can tell the system default fonts and sizes
    3595             :       // on MS-Windows for Buttons, Listboxes/Comboxes and Text Fields are
    3596             :       // all pre-determined and cannot be changed by either the control panel
    3597             :       // or programmatically.
    3598             :       // Fields (text fields)
    3599             :       // Button and Selects (listboxes/comboboxes)
    3600             :       //    We use whatever font is defined by the system. Which it appears
    3601             :       //    (and the assumption is) it is always a proportional font. Then we
    3602             :       //    always use 2 points smaller than what the browser has defined as
    3603             :       //    the default proportional font.
    3604             :       // Assumption: system defined font is proportional
    3605             :       aSystemFont->size =
    3606             :         std::max(aDefaultVariableFont->size -
    3607             :                  nsPresContext::CSSPointsToAppUnits(2), 0);
    3608             :     }
    3609             : #endif
    3610             :   }
    3611           6 : }
    3612             : 
    3613             : /* static */ void
    3614          12 : nsRuleNode::SetFont(nsPresContext* aPresContext, GeckoStyleContext* aContext,
    3615             :                     uint8_t aGenericFontID, const nsRuleData* aRuleData,
    3616             :                     const nsStyleFont* aParentFont,
    3617             :                     nsStyleFont* aFont, bool aUsedStartStruct,
    3618             :                     RuleNodeCacheConditions& aConditions)
    3619             : {
    3620          12 :   bool atRoot = !aContext->GetParent();
    3621             : 
    3622             :   // -x-text-zoom: none, inherit, initial
    3623             :   bool allowZoom;
    3624          12 :   const nsCSSValue* textZoomValue = aRuleData->ValueForTextZoom();
    3625          12 :   if (eCSSUnit_Null != textZoomValue->GetUnit()) {
    3626           0 :     if (eCSSUnit_Inherit == textZoomValue->GetUnit()) {
    3627           0 :       allowZoom = aParentFont->mAllowZoom;
    3628           0 :     } else if (eCSSUnit_None == textZoomValue->GetUnit()) {
    3629           0 :       allowZoom = false;
    3630             :     } else {
    3631           0 :       MOZ_ASSERT(eCSSUnit_Initial == textZoomValue->GetUnit(),
    3632             :                  "unexpected unit");
    3633           0 :       allowZoom = true;
    3634             :     }
    3635           0 :     aFont->EnableZoom(aPresContext, allowZoom);
    3636             :   }
    3637             : 
    3638             :   // mLanguage must be set before before any of the CalcLengthWith calls
    3639             :   // (direct calls or calls via SetFontSize) for the cases where |aParentFont|
    3640             :   // is the same as |aFont|.
    3641             :   //
    3642             :   // -x-lang: string, inherit
    3643             :   // This is not a real CSS property, it is an HTML attribute mapped to CSS.
    3644          12 :   const nsCSSValue* langValue = aRuleData->ValueForLang();
    3645          12 :   if (eCSSUnit_AtomIdent == langValue->GetUnit()) {
    3646           0 :     aFont->mLanguage = langValue->GetAtomValue();
    3647           0 :     aFont->mExplicitLanguage = true;
    3648             :   }
    3649             : 
    3650             :   const nsFont* defaultVariableFont =
    3651          12 :     aPresContext->GetDefaultFont(kPresContext_DefaultVariableFont_ID,
    3652          12 :                                  aFont->mLanguage);
    3653             : 
    3654             :   // -moz-system-font: enum (never inherit!)
    3655             :   static_assert(
    3656             :     NS_STYLE_FONT_CAPTION        == LookAndFeel::eFont_Caption &&
    3657             :     NS_STYLE_FONT_ICON           == LookAndFeel::eFont_Icon &&
    3658             :     NS_STYLE_FONT_MENU           == LookAndFeel::eFont_Menu &&
    3659             :     NS_STYLE_FONT_MESSAGE_BOX    == LookAndFeel::eFont_MessageBox &&
    3660             :     NS_STYLE_FONT_SMALL_CAPTION  == LookAndFeel::eFont_SmallCaption &&
    3661             :     NS_STYLE_FONT_STATUS_BAR     == LookAndFeel::eFont_StatusBar &&
    3662             :     NS_STYLE_FONT_WINDOW         == LookAndFeel::eFont_Window &&
    3663             :     NS_STYLE_FONT_DOCUMENT       == LookAndFeel::eFont_Document &&
    3664             :     NS_STYLE_FONT_WORKSPACE      == LookAndFeel::eFont_Workspace &&
    3665             :     NS_STYLE_FONT_DESKTOP        == LookAndFeel::eFont_Desktop &&
    3666             :     NS_STYLE_FONT_INFO           == LookAndFeel::eFont_Info &&
    3667             :     NS_STYLE_FONT_DIALOG         == LookAndFeel::eFont_Dialog &&
    3668             :     NS_STYLE_FONT_BUTTON         == LookAndFeel::eFont_Button &&
    3669             :     NS_STYLE_FONT_PULL_DOWN_MENU == LookAndFeel::eFont_PullDownMenu &&
    3670             :     NS_STYLE_FONT_LIST           == LookAndFeel::eFont_List &&
    3671             :     NS_STYLE_FONT_FIELD          == LookAndFeel::eFont_Field,
    3672             :     "LookAndFeel.h system-font constants out of sync with nsStyleConsts.h");
    3673             : 
    3674             :   // Fall back to defaultVariableFont.
    3675          24 :   nsFont systemFont = *defaultVariableFont;
    3676          12 :   const nsCSSValue* systemFontValue = aRuleData->ValueForSystemFont();
    3677          12 :   if (eCSSUnit_Enumerated == systemFontValue->GetUnit()) {
    3678             :     LookAndFeel::FontID fontID =
    3679           6 :       (LookAndFeel::FontID)systemFontValue->GetIntValue();
    3680           6 :     ComputeSystemFont(&systemFont, fontID, aPresContext, defaultVariableFont);
    3681             :   }
    3682             : 
    3683             :   // font-family: font family list, enum, inherit
    3684          12 :   const nsCSSValue* familyValue = aRuleData->ValueForFontFamily();
    3685          12 :   NS_ASSERTION(eCSSUnit_Enumerated != familyValue->GetUnit(),
    3686             :                "system fonts should not be in mFamily anymore");
    3687          12 :   if (eCSSUnit_FontFamilyList == familyValue->GetUnit()) {
    3688             :     // set the correct font if we are using DocumentFonts OR we are overriding for XUL
    3689             :     // MJA: bug 31816
    3690           0 :     nsRuleNode::FixupNoneGeneric(&aFont->mFont, aPresContext,
    3691           0 :                                  aGenericFontID, defaultVariableFont);
    3692             : 
    3693           0 :     aFont->mFont.systemFont = false;
    3694             :     // Technically this is redundant with the code below, but it's good
    3695             :     // to have since we'll still want it once we get rid of
    3696             :     // SetGenericFont (bug 380915).
    3697           0 :     aFont->mGenericID = aGenericFontID;
    3698             :   }
    3699          12 :   else if (eCSSUnit_System_Font == familyValue->GetUnit()) {
    3700           6 :     aFont->mFont.fontlist = systemFont.fontlist;
    3701           6 :     aFont->mFont.systemFont = true;
    3702           6 :     aFont->mGenericID = kGenericFont_NONE;
    3703             :   }
    3704           6 :   else if (eCSSUnit_Inherit == familyValue->GetUnit() ||
    3705           0 :            eCSSUnit_Unset == familyValue->GetUnit()) {
    3706           6 :     aConditions.SetUncacheable();
    3707           6 :     aFont->mFont.fontlist = aParentFont->mFont.fontlist;
    3708           6 :     aFont->mFont.systemFont = aParentFont->mFont.systemFont;
    3709           6 :     aFont->mGenericID = aParentFont->mGenericID;
    3710             :   }
    3711           0 :   else if (eCSSUnit_Initial == familyValue->GetUnit()) {
    3712           0 :     aFont->mFont.fontlist = defaultVariableFont->fontlist;
    3713           0 :     aFont->mFont.systemFont = defaultVariableFont->systemFont;
    3714           0 :     aFont->mGenericID = kGenericFont_NONE;
    3715             :   }
    3716             : 
    3717             :   // When we're in the loop in SetGenericFont, we must ensure that we
    3718             :   // always keep aFont->mFlags set to the correct generic.  But we have
    3719             :   // to be careful not to touch it when we're called directly from
    3720             :   // ComputeFontData, because we could have a start struct.
    3721          12 :   if (aGenericFontID != kGenericFont_NONE) {
    3722           0 :     aFont->mGenericID = aGenericFontID;
    3723             :   }
    3724             : 
    3725             :   // -moz-math-variant: enum, inherit, initial
    3726          12 :   SetValue(*aRuleData->ValueForMathVariant(), aFont->mMathVariant,
    3727             :            aConditions,
    3728             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    3729          24 :            aParentFont->mMathVariant, NS_MATHML_MATHVARIANT_NONE);
    3730             : 
    3731             :   // -moz-math-display: enum, inherit, initial
    3732          12 :   SetValue(*aRuleData->ValueForMathDisplay(), aFont->mMathDisplay,
    3733             :            aConditions,
    3734             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    3735          24 :            aParentFont->mMathDisplay, NS_MATHML_DISPLAYSTYLE_INLINE);
    3736             : 
    3737             :   // font-smoothing: enum, inherit, initial
    3738          24 :   SetValue(*aRuleData->ValueForOsxFontSmoothing(),
    3739             :            aFont->mFont.smoothing, aConditions,
    3740             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    3741          12 :            aParentFont->mFont.smoothing,
    3742          24 :            defaultVariableFont->smoothing);
    3743             : 
    3744             :   // font-style: enum, inherit, initial, -moz-system-font
    3745          12 :   if (aFont->mMathVariant != NS_MATHML_MATHVARIANT_NONE) {
    3746             :     // -moz-math-variant overrides font-style
    3747           0 :     aFont->mFont.style = NS_FONT_STYLE_NORMAL;
    3748             :   } else {
    3749          36 :     SetValue(*aRuleData->ValueForFontStyle(),
    3750             :              aFont->mFont.style, aConditions,
    3751             :              SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    3752          12 :              aParentFont->mFont.style,
    3753          12 :              defaultVariableFont->style,
    3754          24 :              Unused, Unused, Unused, systemFont.style);
    3755             :   }
    3756             : 
    3757             :   // font-weight: int, enum, inherit, initial, -moz-system-font
    3758             :   // special handling for enum
    3759          12 :   const nsCSSValue* weightValue = aRuleData->ValueForFontWeight();
    3760          12 :   if (aFont->mMathVariant != NS_MATHML_MATHVARIANT_NONE) {
    3761             :     // -moz-math-variant overrides font-weight
    3762           0 :     aFont->mFont.weight = NS_FONT_WEIGHT_NORMAL;
    3763          12 :   } else if (eCSSUnit_Enumerated == weightValue->GetUnit()) {
    3764           0 :     int32_t value = weightValue->GetIntValue();
    3765           0 :     switch (value) {
    3766             :       case NS_STYLE_FONT_WEIGHT_NORMAL:
    3767             :       case NS_STYLE_FONT_WEIGHT_BOLD:
    3768           0 :         aFont->mFont.weight = value;
    3769           0 :         break;
    3770             :       case NS_STYLE_FONT_WEIGHT_BOLDER: {
    3771           0 :         aConditions.SetUncacheable();
    3772           0 :         int32_t inheritedValue = aParentFont->mFont.weight;
    3773           0 :         if (inheritedValue <= 300) {
    3774           0 :           aFont->mFont.weight = 400;
    3775           0 :         } else if (inheritedValue <= 500) {
    3776           0 :           aFont->mFont.weight = 700;
    3777             :         } else {
    3778           0 :           aFont->mFont.weight = 900;
    3779             :         }
    3780           0 :         break;
    3781             :       }
    3782             :       case NS_STYLE_FONT_WEIGHT_LIGHTER: {
    3783           0 :         aConditions.SetUncacheable();
    3784           0 :         int32_t inheritedValue = aParentFont->mFont.weight;
    3785           0 :         if (inheritedValue < 600) {
    3786           0 :           aFont->mFont.weight = 100;
    3787           0 :         } else if (inheritedValue < 800) {
    3788           0 :           aFont->mFont.weight = 400;
    3789             :         } else {
    3790           0 :           aFont->mFont.weight = 700;
    3791             :         }
    3792           0 :         break;
    3793             :       }
    3794             :     }
    3795             :   } else
    3796          36 :     SetValue(*weightValue, aFont->mFont.weight, aConditions,
    3797             :              SETVAL_INTEGER | SETVAL_UNSET_INHERIT,
    3798          12 :              aParentFont->mFont.weight,
    3799          12 :              defaultVariableFont->weight,
    3800          24 :              Unused, Unused, Unused, systemFont.weight);
    3801             : 
    3802             :   // font-stretch: enum, inherit, initial, -moz-system-font
    3803          36 :   SetValue(*aRuleData->ValueForFontStretch(),
    3804             :            aFont->mFont.stretch, aConditions,
    3805             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    3806          12 :            aParentFont->mFont.stretch,
    3807          12 :            defaultVariableFont->stretch,
    3808          24 :            Unused, Unused, Unused, systemFont.stretch);
    3809             : 
    3810             :   // Compute scriptlevel, scriptminsize and scriptsizemultiplier now so
    3811             :   // they're available for font-size computation.
    3812             : 
    3813             :   // -moz-script-min-size: length
    3814          12 :   const nsCSSValue* scriptMinSizeValue = aRuleData->ValueForScriptMinSize();
    3815          12 :   if (scriptMinSizeValue->IsLengthUnit()) {
    3816             :     // scriptminsize in font units (em, ex) has to be interpreted relative
    3817             :     // to the parent font, or the size definitions are circular and we
    3818             :     //
    3819           0 :     aFont->mScriptMinSize =
    3820           0 :       CalcLengthWith(*scriptMinSizeValue, aParentFont->mSize,
    3821             :                      aParentFont,
    3822             :                      aContext, aPresContext, atRoot, true /* aUseUserFontSet */,
    3823             :                      aConditions);
    3824             :   }
    3825             : 
    3826             :   // -moz-script-size-multiplier: factor, inherit, initial
    3827          12 :   SetFactor(*aRuleData->ValueForScriptSizeMultiplier(),
    3828             :             aFont->mScriptSizeMultiplier,
    3829          12 :             aConditions, aParentFont->mScriptSizeMultiplier,
    3830             :             NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER,
    3831          12 :             SETFCT_POSITIVE | SETFCT_UNSET_INHERIT);
    3832             : 
    3833             :   // -moz-script-level: integer, number, inherit
    3834          12 :   const nsCSSValue* scriptLevelValue = aRuleData->ValueForScriptLevel();
    3835          12 :   if (eCSSUnit_Integer == scriptLevelValue->GetUnit()) {
    3836             :     // "relative"
    3837           0 :     aConditions.SetUncacheable();
    3838           0 :     aFont->mScriptLevel = ClampTo8Bit(aParentFont->mScriptLevel + scriptLevelValue->GetIntValue());
    3839             :   }
    3840          12 :   else if (eCSSUnit_Number == scriptLevelValue->GetUnit()) {
    3841             :     // "absolute"
    3842           0 :     aFont->mScriptLevel = ClampTo8Bit(int32_t(scriptLevelValue->GetFloatValue()));
    3843             :   }
    3844          12 :   else if (eCSSUnit_Auto == scriptLevelValue->GetUnit()) {
    3845             :     // auto
    3846           0 :     aConditions.SetUncacheable();
    3847           0 :     aFont->mScriptLevel = ClampTo8Bit(aParentFont->mScriptLevel +
    3848           0 :                                       (aParentFont->mMathDisplay ==
    3849           0 :                                        NS_MATHML_DISPLAYSTYLE_INLINE ? 1 : 0));
    3850             :   }
    3851          24 :   else if (eCSSUnit_Inherit == scriptLevelValue->GetUnit() ||
    3852          12 :            eCSSUnit_Unset == scriptLevelValue->GetUnit()) {
    3853           0 :     aConditions.SetUncacheable();
    3854           0 :     aFont->mScriptLevel = aParentFont->mScriptLevel;
    3855             :   }
    3856          12 :   else if (eCSSUnit_Initial == scriptLevelValue->GetUnit()) {
    3857           0 :     aFont->mScriptLevel = 0;
    3858             :   }
    3859             : 
    3860             :   // font-kerning: none, enum, inherit, initial, -moz-system-font
    3861          36 :   SetValue(*aRuleData->ValueForFontKerning(),
    3862             :            aFont->mFont.kerning, aConditions,
    3863             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    3864          12 :            aParentFont->mFont.kerning,
    3865          12 :            defaultVariableFont->kerning,
    3866          24 :            Unused, Unused, Unused, systemFont.kerning);
    3867             : 
    3868             :   // font-synthesis: none, enum (bit field), inherit, initial
    3869          24 :   SetValue(*aRuleData->ValueForFontSynthesis(),
    3870             :            aFont->mFont.synthesis, aConditions,
    3871             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    3872          12 :            aParentFont->mFont.synthesis,
    3873          12 :            defaultVariableFont->synthesis,
    3874          12 :            Unused, /* none */ 0, Unused, Unused);
    3875             : 
    3876             :   // font-variant-alternates: normal, enum (bit field) + functions, inherit,
    3877             :   //                          initial, -moz-system-font
    3878             :   const nsCSSValue* variantAlternatesValue =
    3879          12 :     aRuleData->ValueForFontVariantAlternates();
    3880          12 :   int32_t variantAlternates = 0;
    3881             : 
    3882          12 :   switch (variantAlternatesValue->GetUnit()) {
    3883             :   case eCSSUnit_Inherit:
    3884             :   case eCSSUnit_Unset:
    3885           6 :     aFont->mFont.CopyAlternates(aParentFont->mFont);
    3886           6 :     aConditions.SetUncacheable();
    3887           6 :     break;
    3888             : 
    3889             :   case eCSSUnit_Initial:
    3890             :   case eCSSUnit_Normal:
    3891           0 :     aFont->mFont.variantAlternates = 0;
    3892           0 :     aFont->mFont.alternateValues.Clear();
    3893           0 :     aFont->mFont.featureValueLookup = nullptr;
    3894           0 :     break;
    3895             : 
    3896             :   case eCSSUnit_Pair:
    3897           0 :     NS_ASSERTION(variantAlternatesValue->GetPairValue().mXValue.GetUnit() ==
    3898             :                    eCSSUnit_Enumerated, "strange unit for variantAlternates");
    3899             :     variantAlternates =
    3900           0 :       variantAlternatesValue->GetPairValue().mXValue.GetIntValue();
    3901           0 :     aFont->mFont.variantAlternates = variantAlternates;
    3902             : 
    3903           0 :     if (variantAlternates & NS_FONT_VARIANT_ALTERNATES_FUNCTIONAL_MASK) {
    3904             :       // fetch the feature lookup object from the styleset
    3905           0 :       MOZ_ASSERT(aPresContext->StyleSet()->IsGecko(),
    3906             :                  "ServoStyleSets should not have rule nodes");
    3907             :       aFont->mFont.featureValueLookup =
    3908           0 :         aPresContext->StyleSet()->AsGecko()->GetFontFeatureValuesLookup();
    3909             : 
    3910           0 :       NS_ASSERTION(variantAlternatesValue->GetPairValue().mYValue.GetUnit() ==
    3911             :                    eCSSUnit_List, "function list not a list value");
    3912           0 :       nsStyleUtil::ComputeFunctionalAlternates(
    3913           0 :         variantAlternatesValue->GetPairValue().mYValue.GetListValue(),
    3914           0 :         aFont->mFont.alternateValues);
    3915             :     }
    3916           0 :     break;
    3917             : 
    3918             :   default:
    3919           6 :     break;
    3920             :   }
    3921             : 
    3922             :   // font-variant-caps: normal, enum, inherit, initial, -moz-system-font
    3923          36 :   SetValue(*aRuleData->ValueForFontVariantCaps(),
    3924             :            aFont->mFont.variantCaps, aConditions,
    3925             :            SETVAL_ENUMERATED |SETVAL_UNSET_INHERIT,
    3926          12 :            aParentFont->mFont.variantCaps,
    3927          12 :            defaultVariableFont->variantCaps,
    3928          24 :            Unused, Unused, /* normal */ 0, systemFont.variantCaps);
    3929             : 
    3930             :   // font-variant-east-asian: normal, enum (bit field), inherit, initial,
    3931             :   //                          -moz-system-font
    3932          36 :   SetValue(*aRuleData->ValueForFontVariantEastAsian(),
    3933             :            aFont->mFont.variantEastAsian, aConditions,
    3934             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    3935          12 :            aParentFont->mFont.variantEastAsian,
    3936          12 :            defaultVariableFont->variantEastAsian,
    3937          24 :            Unused, Unused, /* normal */ 0, systemFont.variantEastAsian);
    3938             : 
    3939             :   // font-variant-ligatures: normal, none, enum (bit field), inherit, initial,
    3940             :   //                         -moz-system-font
    3941          36 :   SetValue(*aRuleData->ValueForFontVariantLigatures(),
    3942             :            aFont->mFont.variantLigatures, aConditions,
    3943             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    3944          12 :            aParentFont->mFont.variantLigatures,
    3945          12 :            defaultVariableFont->variantLigatures,
    3946             :            Unused, NS_FONT_VARIANT_LIGATURES_NONE, /* normal */ 0,
    3947          24 :            systemFont.variantLigatures);
    3948             : 
    3949             :   // font-variant-numeric: normal, enum (bit field), inherit, initial,
    3950             :   //                       -moz-system-font
    3951          36 :   SetValue(*aRuleData->ValueForFontVariantNumeric(),
    3952             :            aFont->mFont.variantNumeric, aConditions,
    3953             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    3954          12 :            aParentFont->mFont.variantNumeric,
    3955          12 :            defaultVariableFont->variantNumeric,
    3956          24 :            Unused, Unused, /* normal */ 0, systemFont.variantNumeric);
    3957             : 
    3958             :   // font-variant-position: normal, enum, inherit, initial,
    3959             :   //                        -moz-system-font
    3960          36 :   SetValue(*aRuleData->ValueForFontVariantPosition(),
    3961             :            aFont->mFont.variantPosition, aConditions,
    3962             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    3963          12 :            aParentFont->mFont.variantPosition,
    3964          12 :            defaultVariableFont->variantPosition,
    3965          24 :            Unused, Unused, /* normal */ 0, systemFont.variantPosition);
    3966             : 
    3967             :   // font-feature-settings
    3968             :   const nsCSSValue* featureSettingsValue =
    3969          12 :     aRuleData->ValueForFontFeatureSettings();
    3970             : 
    3971          12 :   switch (featureSettingsValue->GetUnit()) {
    3972             :     case eCSSUnit_Null:
    3973           0 :       break;
    3974             : 
    3975             :     case eCSSUnit_Normal:
    3976             :     case eCSSUnit_Initial:
    3977           0 :       aFont->mFont.fontFeatureSettings.Clear();
    3978           0 :       break;
    3979             : 
    3980             :     case eCSSUnit_Inherit:
    3981             :     case eCSSUnit_Unset:
    3982           6 :       aConditions.SetUncacheable();
    3983           6 :       aFont->mFont.fontFeatureSettings = aParentFont->mFont.fontFeatureSettings;
    3984           6 :       break;
    3985             : 
    3986             :     case eCSSUnit_System_Font:
    3987           6 :       aFont->mFont.fontFeatureSettings = systemFont.fontFeatureSettings;
    3988           6 :       break;
    3989             : 
    3990             :     case eCSSUnit_PairList:
    3991             :     case eCSSUnit_PairListDep:
    3992           0 :       ComputeFontFeatures(featureSettingsValue->GetPairListValue(),
    3993           0 :                           aFont->mFont.fontFeatureSettings);
    3994           0 :       break;
    3995             : 
    3996             :     default:
    3997           0 :       MOZ_ASSERT(false, "unexpected value unit");
    3998             :       break;
    3999             :   }
    4000             : 
    4001             :   // font-variation-settings
    4002             :   const nsCSSValue* variationSettingsValue =
    4003          12 :     aRuleData->ValueForFontVariationSettings();
    4004             : 
    4005          12 :   switch (variationSettingsValue->GetUnit()) {
    4006             :     case eCSSUnit_Null:
    4007          12 :       break;
    4008             : 
    4009             :     case eCSSUnit_Normal:
    4010             :     case eCSSUnit_Initial:
    4011           0 :       aFont->mFont.fontVariationSettings.Clear();
    4012           0 :       break;
    4013             : 
    4014             :     case eCSSUnit_Inherit:
    4015             :     case eCSSUnit_Unset:
    4016           0 :       aConditions.SetUncacheable();
    4017             :       aFont->mFont.fontVariationSettings =
    4018           0 :         aParentFont->mFont.fontVariationSettings;
    4019           0 :       break;
    4020             : 
    4021             :     case eCSSUnit_System_Font:
    4022           0 :       aFont->mFont.fontVariationSettings = systemFont.fontVariationSettings;
    4023           0 :       break;
    4024             : 
    4025             :     case eCSSUnit_PairList:
    4026             :     case eCSSUnit_PairListDep:
    4027           0 :       ComputeFontVariations(variationSettingsValue->GetPairListValue(),
    4028           0 :                             aFont->mFont.fontVariationSettings);
    4029           0 :       break;
    4030             : 
    4031             :     default:
    4032           0 :       MOZ_ASSERT(false, "unexpected value unit");
    4033             :       break;
    4034             :   }
    4035             : 
    4036             :   // font-language-override
    4037             :   const nsCSSValue* languageOverrideValue =
    4038          12 :     aRuleData->ValueForFontLanguageOverride();
    4039          18 :   if (eCSSUnit_Inherit == languageOverrideValue->GetUnit() ||
    4040           6 :       eCSSUnit_Unset == languageOverrideValue->GetUnit()) {
    4041           6 :     aConditions.SetUncacheable();
    4042           6 :     aFont->mFont.languageOverride = aParentFont->mFont.languageOverride;
    4043          12 :   } else if (eCSSUnit_Normal == languageOverrideValue->GetUnit() ||
    4044           6 :              eCSSUnit_Initial == languageOverrideValue->GetUnit()) {
    4045           0 :     aFont->mFont.languageOverride = NO_FONT_LANGUAGE_OVERRIDE;
    4046           6 :   } else if (eCSSUnit_System_Font == languageOverrideValue->GetUnit()) {
    4047           6 :     aFont->mFont.languageOverride = systemFont.languageOverride;
    4048           0 :   } else if (eCSSUnit_String == languageOverrideValue->GetUnit()) {
    4049           0 :     nsAutoString lang;
    4050           0 :     languageOverrideValue->GetStringValue(lang);
    4051           0 :     aFont->mFont.languageOverride = ParseFontLanguageOverride(lang);
    4052             :   }
    4053             : 
    4054             :   // -moz-min-font-size-ratio: percent, inherit
    4055          12 :   const nsCSSValue* minFontSizeRatio = aRuleData->ValueForMinFontSizeRatio();
    4056          12 :   switch (minFontSizeRatio->GetUnit()) {
    4057             :     case eCSSUnit_Null:
    4058          12 :       break;
    4059             :     case eCSSUnit_Unset:
    4060             :     case eCSSUnit_Inherit:
    4061           0 :       aFont->mMinFontSizeRatio = aParentFont->mMinFontSizeRatio;
    4062           0 :       aConditions.SetUncacheable();
    4063           0 :       break;
    4064             :     case eCSSUnit_Initial:
    4065           0 :       aFont->mMinFontSizeRatio = 100; // 100%
    4066           0 :       break;
    4067             :     case eCSSUnit_Percent: {
    4068             :       // While percentages are parsed as floating point numbers, we
    4069             :       // only store an integer in the range [0, 255] since that's all
    4070             :       // we need for now.
    4071           0 :       float percent = minFontSizeRatio->GetPercentValue() * 100;
    4072           0 :       if (percent < 0) {
    4073           0 :         percent = 0;
    4074           0 :       } else if (percent > 255) {
    4075           0 :         percent = 255;
    4076             :       }
    4077           0 :       aFont->mMinFontSizeRatio = uint8_t(percent);
    4078           0 :       break;
    4079             :     }
    4080             :     default:
    4081           0 :       MOZ_ASSERT_UNREACHABLE("Unknown unit for -moz-min-font-size-ratio");
    4082             :   }
    4083             : 
    4084             :   nscoord scriptLevelAdjustedUnconstrainedParentSize;
    4085             : 
    4086             :   // font-size: enum, length, percent, inherit
    4087             :   nscoord scriptLevelAdjustedParentSize =
    4088             :     ComputeScriptLevelSize(aFont, aParentFont, aPresContext,
    4089          12 :                            &scriptLevelAdjustedUnconstrainedParentSize);
    4090          12 :   NS_ASSERTION(!aUsedStartStruct || aFont->mScriptUnconstrainedSize == aFont->mSize,
    4091             :                "If we have a start struct, we should have reset everything coming in here");
    4092             : 
    4093             :   // Compute whether we're affected by scriptMinSize *before* calling
    4094             :   // SetFontSize, since aParentFont might be the same as aFont.  If it
    4095             :   // is, calling SetFontSize might throw off our calculation.
    4096             :   bool affectedByScriptMinSize =
    4097          24 :     aParentFont->mSize != aParentFont->mScriptUnconstrainedSize ||
    4098          12 :     scriptLevelAdjustedParentSize !=
    4099          12 :       scriptLevelAdjustedUnconstrainedParentSize;
    4100             : 
    4101          24 :   SetFontSize(aPresContext, aContext,
    4102             :               aRuleData, aFont, aParentFont,
    4103             :               &aFont->mSize,
    4104          12 :               systemFont, aParentFont->mSize, scriptLevelAdjustedParentSize,
    4105          12 :               aUsedStartStruct, atRoot, aConditions);
    4106          12 :   if (!aPresContext->Document()->GetMathMLEnabled()) {
    4107          12 :     MOZ_ASSERT(!affectedByScriptMinSize);
    4108             :     // If MathML is not enabled, we don't need to mark this node as
    4109             :     // uncacheable.  If it becomes enabled, code in
    4110             :     // nsMathMLElementFactory will rebuild the rule tree and style data
    4111             :     // when MathML is first enabled (see nsMathMLElement::BindToTree).
    4112          12 :     aFont->mScriptUnconstrainedSize = aFont->mSize;
    4113           0 :   } else if (!affectedByScriptMinSize) {
    4114             :     // Fast path: we have not been affected by scriptminsize so we don't
    4115             :     // need to call SetFontSize again to compute the
    4116             :     // scriptminsize-unconstrained size. This is OK even if we have a
    4117             :     // start struct, because if we have a start struct then 'font-size'
    4118             :     // was specified and so scriptminsize has no effect.
    4119           0 :     aFont->mScriptUnconstrainedSize = aFont->mSize;
    4120             :     // It's possible we could, in the future, have a different parent,
    4121             :     // which would lead to a different affectedByScriptMinSize.
    4122           0 :     aConditions.SetUncacheable();
    4123             :   } else {
    4124             :     // see previous else-if
    4125           0 :     aConditions.SetUncacheable();
    4126             : 
    4127             :     // Use a separate conditions object because it might get a
    4128             :     // *different* font-size dependency.  We can ignore it because we've
    4129             :     // already called SetUncacheable.
    4130           0 :     RuleNodeCacheConditions unconstrainedConditions;
    4131             : 
    4132           0 :     SetFontSize(aPresContext, aContext,
    4133             :                 aRuleData, aFont, aParentFont,
    4134             :                 &aFont->mScriptUnconstrainedSize,
    4135           0 :                 systemFont, aParentFont->mScriptUnconstrainedSize,
    4136             :                 scriptLevelAdjustedUnconstrainedParentSize,
    4137           0 :                 aUsedStartStruct, atRoot, unconstrainedConditions);
    4138             :   }
    4139          12 :   NS_ASSERTION(aFont->mScriptUnconstrainedSize <= aFont->mSize,
    4140             :                "scriptminsize should never be making things bigger");
    4141             : 
    4142          12 :   nsRuleNode::ApplyMinFontSize(aFont, aPresContext,
    4143          12 :                                aPresContext->MinFontSize(aFont->mLanguage));
    4144             : 
    4145             :   // font-size-adjust: number, none, inherit, initial, -moz-system-font
    4146          12 :   const nsCSSValue* sizeAdjustValue = aRuleData->ValueForFontSizeAdjust();
    4147          12 :   if (eCSSUnit_System_Font == sizeAdjustValue->GetUnit()) {
    4148           6 :     aFont->mFont.sizeAdjust = systemFont.sizeAdjust;
    4149             :   } else
    4150           6 :     SetFactor(*sizeAdjustValue, aFont->mFont.sizeAdjust,
    4151           6 :               aConditions, aParentFont->mFont.sizeAdjust, -1.0f,
    4152           6 :               SETFCT_NONE | SETFCT_UNSET_INHERIT);
    4153          12 : }
    4154             : 
    4155             : static inline void
    4156           0 : AssertValidFontTag(const nsString& aString)
    4157             : {
    4158             :   // To be valid as a font feature tag, a string MUST be:
    4159           0 :   MOZ_ASSERT(aString.Length() == 4 &&              // (1) exactly 4 chars long
    4160             :              NS_IsAscii(aString.BeginReading()) && // (2) entirely ASCII
    4161             :              isprint(aString[0]) &&                // (3) all printable chars
    4162             :              isprint(aString[1]) &&
    4163             :              isprint(aString[2]) &&
    4164             :              isprint(aString[3]));
    4165           0 : }
    4166             : 
    4167             : /* static */ void
    4168           0 : nsRuleNode::ComputeFontFeatures(const nsCSSValuePairList *aFeaturesList,
    4169             :                                 nsTArray<gfxFontFeature>& aFeatureSettings)
    4170             : {
    4171           0 :   aFeatureSettings.Clear();
    4172           0 :   for (const nsCSSValuePairList* p = aFeaturesList; p; p = p->mNext) {
    4173             :     gfxFontFeature feat;
    4174             : 
    4175           0 :     MOZ_ASSERT(aFeaturesList->mXValue.GetUnit() == eCSSUnit_String,
    4176             :                "unexpected value unit");
    4177             : 
    4178             :     // tag is a 4-byte ASCII sequence
    4179           0 :     nsAutoString tag;
    4180           0 :     p->mXValue.GetStringValue(tag);
    4181           0 :     AssertValidFontTag(tag);
    4182           0 :     if (tag.Length() != 4) {
    4183           0 :       continue;
    4184             :     }
    4185             :     // parsing validates that these are ASCII chars
    4186             :     // tags are always big-endian
    4187           0 :     feat.mTag = (tag[0] << 24) | (tag[1] << 16) | (tag[2] << 8)  | tag[3];
    4188             : 
    4189             :     // value
    4190           0 :     NS_ASSERTION(p->mYValue.GetUnit() == eCSSUnit_Integer,
    4191             :                  "should have found an integer unit");
    4192           0 :     feat.mValue = p->mYValue.GetIntValue();
    4193             : 
    4194           0 :     aFeatureSettings.AppendElement(feat);
    4195             :   }
    4196           0 : }
    4197             : 
    4198             : /* static */ void
    4199           0 : nsRuleNode::ComputeFontVariations(const nsCSSValuePairList* aVariationsList,
    4200             :                                   nsTArray<gfxFontVariation>& aVariationSettings)
    4201             : {
    4202           0 :   aVariationSettings.Clear();
    4203           0 :   for (const nsCSSValuePairList* p = aVariationsList; p; p = p->mNext) {
    4204             :     gfxFontVariation var;
    4205             : 
    4206           0 :     MOZ_ASSERT(aVariationsList->mXValue.GetUnit() == eCSSUnit_String,
    4207             :                "unexpected value unit");
    4208             : 
    4209             :     // tag is a 4-byte ASCII sequence
    4210           0 :     nsAutoString tag;
    4211           0 :     p->mXValue.GetStringValue(tag);
    4212           0 :     AssertValidFontTag(tag);
    4213           0 :     if (tag.Length() != 4) {
    4214           0 :       continue;
    4215             :     }
    4216             :     // parsing validates that these are ASCII chars
    4217             :     // tags are always big-endian
    4218           0 :     var.mTag = (tag[0] << 24) | (tag[1] << 16) | (tag[2] << 8)  | tag[3];
    4219             : 
    4220             :     // value
    4221           0 :     NS_ASSERTION(p->mYValue.GetUnit() == eCSSUnit_Number,
    4222             :                  "should have found a number unit");
    4223           0 :     var.mValue = p->mYValue.GetFloatValue();
    4224             : 
    4225           0 :     aVariationSettings.AppendElement(var);
    4226             :   }
    4227           0 : }
    4228             : 
    4229             : // This should die (bug 380915).
    4230             : //
    4231             : // SetGenericFont:
    4232             : //  - backtrack to an ancestor with the same generic font name (possibly
    4233             : //    up to the root where default values come from the presentation context)
    4234             : //  - re-apply cascading rules from there without caching intermediate values
    4235             : /* static */ void
    4236           0 : nsRuleNode::SetGenericFont(nsPresContext* aPresContext,
    4237             :                            GeckoStyleContext* aContext,
    4238             :                            uint8_t aGenericFontID,
    4239             :                            nsStyleFont* aFont)
    4240             : {
    4241             :   // walk up the contexts until a context with the desired generic font
    4242           0 :   AutoTArray<GeckoStyleContext*, 8> contextPath;
    4243           0 :   contextPath.AppendElement(aContext);
    4244           0 :   GeckoStyleContext* higherContext = aContext->GetParent();
    4245           0 :   while (higherContext) {
    4246           0 :     if (higherContext->StyleFont()->mGenericID == aGenericFontID) {
    4247             :       // done walking up the higher contexts
    4248           0 :       break;
    4249             :     }
    4250           0 :     contextPath.AppendElement(higherContext);
    4251           0 :     higherContext = higherContext->GetParent();
    4252             :   }
    4253             : 
    4254             :   // re-apply the cascading rules, starting from the higher context
    4255             : 
    4256             :   // If we stopped earlier because we reached the root of the style tree,
    4257             :   // we will start with the default generic font from the presentation
    4258             :   // context. Otherwise we start with the higher context.
    4259             :   const nsFont* defaultFont =
    4260           0 :     aPresContext->GetDefaultFont(aGenericFontID, aFont->mLanguage);
    4261           0 :   nsStyleFont parentFont(*defaultFont, aPresContext);
    4262           0 :   if (higherContext) {
    4263           0 :     const nsStyleFont* tmpFont = higherContext->StyleFont();
    4264           0 :     parentFont = *tmpFont;
    4265             :   }
    4266           0 :   *aFont = parentFont;
    4267             : 
    4268           0 :   uint32_t fontBit = nsCachedStyleData::GetBitForSID(eStyleStruct_Font);
    4269             : 
    4270             :   // use placement new[] on the result of alloca() to allocate a
    4271             :   // variable-sized stack array, including execution of constructors,
    4272             :   // and use an RAII class to run the destructors too.
    4273           0 :   size_t nprops = nsCSSProps::PropertyCountInStruct(eStyleStruct_Font);
    4274           0 :   void* dataStorage = alloca(nprops * sizeof(nsCSSValue));
    4275             : 
    4276           0 :   for (int32_t i = contextPath.Length() - 1; i >= 0; --i) {
    4277           0 :     GeckoStyleContext* context = contextPath[i];
    4278           0 :     AutoCSSValueArray dataArray(dataStorage, nprops);
    4279             : 
    4280             :     nsRuleData ruleData(NS_STYLE_INHERIT_BIT(Font), dataArray.get(),
    4281           0 :                         aPresContext, context);
    4282           0 :     ruleData.mValueOffsets[eStyleStruct_Font] = 0;
    4283             : 
    4284             :     // Trimmed down version of ::WalkRuleTree() to re-apply the style rules
    4285             :     // Note that we *do* need to do this for our own data, since what is
    4286             :     // in |fontData| in ComputeFontData is only for the rules below
    4287             :     // aStartStruct.
    4288           0 :     for (nsRuleNode* ruleNode = context->RuleNode(); ruleNode;
    4289             :          ruleNode = ruleNode->GetParent()) {
    4290           0 :       if (ruleNode->mNoneBits & fontBit)
    4291             :         // no more font rules on this branch, get out
    4292           0 :         break;
    4293             : 
    4294           0 :       nsIStyleRule *rule = ruleNode->GetRule();
    4295           0 :       if (rule) {
    4296           0 :         ruleData.mLevel = ruleNode->GetLevel();
    4297           0 :         ruleData.mIsImportantRule = ruleNode->IsImportantRule();
    4298           0 :         rule->MapRuleInfoInto(&ruleData);
    4299             :       }
    4300             :     }
    4301             : 
    4302             :     // Compute the delta from the information that the rules specified
    4303             : 
    4304             :     // Avoid unnecessary operations in SetFont().  But we care if it's
    4305             :     // the final value that we're computing.
    4306           0 :     if (i != 0)
    4307           0 :       ruleData.ValueForFontFamily()->Reset();
    4308             : 
    4309           0 :     ResolveVariableReferences(eStyleStruct_Font, &ruleData, aContext);
    4310             : 
    4311           0 :     RuleNodeCacheConditions dummy;
    4312           0 :     nsRuleNode::SetFont(aPresContext, context,
    4313             :                         aGenericFontID, &ruleData, &parentFont, aFont,
    4314           0 :                         false, dummy);
    4315             : 
    4316           0 :     parentFont = *aFont;
    4317             :   }
    4318             : 
    4319           0 :   if (higherContext && contextPath.Length() > 1) {
    4320             :     // contextPath is a list of all ancestor style contexts, so it must have
    4321             :     // at least two elements for it to result in a dependency on grandancestor
    4322             :     // styles.
    4323           0 :     PropagateGrandancestorBit(aContext, higherContext);
    4324             :   }
    4325           0 : }
    4326             : 
    4327             : const void*
    4328          12 : nsRuleNode::ComputeFontData(void* aStartStruct,
    4329             :                             const nsRuleData* aRuleData,
    4330             :                             GeckoStyleContext* aContext,
    4331             :                             nsRuleNode* aHighestNode,
    4332             :                             const RuleDetail aRuleDetail,
    4333             :                             const RuleNodeCacheConditions aConditions)
    4334             : {
    4335          24 :   COMPUTE_START_INHERITED(Font, font, parentFont)
    4336             : 
    4337             :   // NOTE:  The |aRuleDetail| passed in is a little bit conservative due
    4338             :   // to the -moz-system-font property.  We really don't need to consider
    4339             :   // it here in determining whether to cache in the rule tree.  However,
    4340             :   // we do need to consider it in WalkRuleTree when deciding whether to
    4341             :   // walk further up the tree.  So this means that when the font struct
    4342             :   // is fully specified using *longhand* properties (excluding
    4343             :   // -moz-system-font), we won't cache in the rule tree even though we
    4344             :   // could.  However, it's pretty unlikely authors will do that
    4345             :   // (although there is a pretty good chance they'll fully specify it
    4346             :   // using the 'font' shorthand).
    4347             : 
    4348             :   // Figure out if we are a generic font
    4349          12 :   uint8_t generic = kGenericFont_NONE;
    4350             :   // XXXldb What if we would have had a string if we hadn't been doing
    4351             :   // the optimization with a non-null aStartStruct?
    4352          12 :   const nsCSSValue* familyValue = aRuleData->ValueForFontFamily();
    4353          12 :   if (eCSSUnit_FontFamilyList == familyValue->GetUnit()) {
    4354           0 :     const FontFamilyList* fontlist = familyValue->GetFontFamilyListValue();
    4355           0 :     FontFamilyList& fl = font->mFont.fontlist;
    4356           0 :     fl = *fontlist;
    4357             : 
    4358             :     // extract the first generic in the fontlist, if exists
    4359           0 :     FontFamilyType fontType = fontlist->FirstGeneric();
    4360             : 
    4361             :     // if only a single generic, set the generic type
    4362           0 :     if (fontlist->Length() == 1) {
    4363           0 :       switch (fontType) {
    4364             :         case eFamily_serif:
    4365           0 :           generic = kGenericFont_serif;
    4366           0 :           break;
    4367             :         case eFamily_sans_serif:
    4368           0 :           generic = kGenericFont_sans_serif;
    4369           0 :           break;
    4370             :         case eFamily_monospace:
    4371           0 :           generic = kGenericFont_monospace;
    4372           0 :           break;
    4373             :         case eFamily_cursive:
    4374           0 :           generic = kGenericFont_cursive;
    4375           0 :           break;
    4376             :         case eFamily_fantasy:
    4377           0 :           generic = kGenericFont_fantasy;
    4378           0 :           break;
    4379             :         case eFamily_moz_fixed:
    4380           0 :           generic = kGenericFont_moz_fixed;
    4381           0 :           break;
    4382             :         default:
    4383           0 :           break;
    4384             :       }
    4385             :     }
    4386             :   }
    4387             : 
    4388             :   // Now compute our font struct
    4389          12 :   if (generic == kGenericFont_NONE) {
    4390             :     // continue the normal processing
    4391          12 :     nsRuleNode::SetFont(mPresContext, aContext, generic,
    4392             :                         aRuleData, parentFont, font,
    4393          12 :                         aStartStruct != nullptr, conditions);
    4394             :   }
    4395             :   else {
    4396             :     // re-calculate the font as a generic font
    4397           0 :     conditions.SetUncacheable();
    4398           0 :     nsRuleNode::SetGenericFont(mPresContext, aContext, generic,
    4399           0 :                                font);
    4400             :   }
    4401             : 
    4402          24 :   COMPUTE_END_INHERITED(Font, font)
    4403             : }
    4404             : 
    4405             : /*static*/ uint32_t
    4406           0 : nsRuleNode::ParseFontLanguageOverride(const nsAString& aLangTag)
    4407             : {
    4408           0 :   if (!aLangTag.Length() || aLangTag.Length() > 4) {
    4409           0 :     return NO_FONT_LANGUAGE_OVERRIDE;
    4410             :   }
    4411           0 :   uint32_t index, result = 0;
    4412           0 :   for (index = 0; index < aLangTag.Length(); ++index) {
    4413           0 :     char16_t ch = aLangTag[index];
    4414           0 :     if (!nsCRT::IsAscii(ch)) { // valid tags are pure ASCII
    4415           0 :       return NO_FONT_LANGUAGE_OVERRIDE;
    4416             :     }
    4417           0 :     result = (result << 8) + ch;
    4418             :   }
    4419           0 :   while (index++ < 4) {
    4420           0 :     result = (result << 8) + 0x20;
    4421             :   }
    4422           0 :   return result;
    4423             : }
    4424             : 
    4425             : template <typename T>
    4426         267 : inline uint32_t ListLength(const T* aList)
    4427             : {
    4428         267 :   uint32_t len = 0;
    4429         915 :   while (aList) {
    4430         324 :     len++;
    4431         324 :     aList = aList->mNext;
    4432             :   }
    4433         267 :   return len;
    4434             : }
    4435             : 
    4436             : static already_AddRefed<nsCSSShadowArray>
    4437           6 : GetShadowData(const nsCSSValueList* aList,
    4438             :               GeckoStyleContext* aContext,
    4439             :               bool aIsBoxShadow,
    4440             :               nsPresContext* aPresContext,
    4441             :               RuleNodeCacheConditions& aConditions)
    4442             : {
    4443           6 :   uint32_t arrayLength = ListLength(aList);
    4444             : 
    4445           6 :   MOZ_ASSERT(arrayLength > 0,
    4446             :              "Non-null text-shadow list, yet we counted 0 items.");
    4447             :   RefPtr<nsCSSShadowArray> shadowList =
    4448          12 :     new(arrayLength) nsCSSShadowArray(arrayLength);
    4449             : 
    4450           6 :   if (!shadowList)
    4451           0 :     return nullptr;
    4452             : 
    4453          12 :   nsStyleCoord tempCoord;
    4454          12 :   DebugOnly<bool> unitOK;
    4455          12 :   for (nsCSSShadowItem* item = shadowList->ShadowAt(0);
    4456          12 :        aList;
    4457           6 :        aList = aList->mNext, ++item) {
    4458           6 :     MOZ_ASSERT(aList->mValue.GetUnit() == eCSSUnit_Array,
    4459             :                "expecting a plain array value");
    4460           6 :     nsCSSValue::Array *arr = aList->mValue.GetArrayValue();
    4461             :     // OK to pass bad aParentCoord since we're not passing SETCOORD_INHERIT
    4462          12 :     unitOK = SetCoord(arr->Item(0), tempCoord, nsStyleCoord(),
    4463             :                       SETCOORD_LENGTH | SETCOORD_CALC_LENGTH_ONLY,
    4464           6 :                       aContext, aPresContext, aConditions);
    4465           6 :     NS_ASSERTION(unitOK, "unexpected unit");
    4466           6 :     item->mXOffset = tempCoord.GetCoordValue();
    4467             : 
    4468          12 :     unitOK = SetCoord(arr->Item(1), tempCoord, nsStyleCoord(),
    4469             :                       SETCOORD_LENGTH | SETCOORD_CALC_LENGTH_ONLY,
    4470           6 :                       aContext, aPresContext, aConditions);
    4471           6 :     NS_ASSERTION(unitOK, "unexpected unit");
    4472           6 :     item->mYOffset = tempCoord.GetCoordValue();
    4473             : 
    4474             :     // Blur radius is optional in the current box-shadow spec
    4475           6 :     if (arr->Item(2).GetUnit() != eCSSUnit_Null) {
    4476          12 :       unitOK = SetCoord(arr->Item(2), tempCoord, nsStyleCoord(),
    4477             :                         SETCOORD_LENGTH | SETCOORD_CALC_LENGTH_ONLY |
    4478             :                           SETCOORD_CALC_CLAMP_NONNEGATIVE,
    4479           6 :                         aContext, aPresContext, aConditions);
    4480           6 :       NS_ASSERTION(unitOK, "unexpected unit");
    4481           6 :       item->mRadius = tempCoord.GetCoordValue();
    4482             :     } else {
    4483           0 :       item->mRadius = 0;
    4484             :     }
    4485             : 
    4486             :     // Find the spread radius
    4487           6 :     if (aIsBoxShadow && arr->Item(3).GetUnit() != eCSSUnit_Null) {
    4488           0 :       unitOK = SetCoord(arr->Item(3), tempCoord, nsStyleCoord(),
    4489             :                         SETCOORD_LENGTH | SETCOORD_CALC_LENGTH_ONLY,
    4490           0 :                         aContext, aPresContext, aConditions);
    4491           0 :       NS_ASSERTION(unitOK, "unexpected unit");
    4492           0 :       item->mSpread = tempCoord.GetCoordValue();
    4493             :     } else {
    4494           6 :       item->mSpread = 0;
    4495             :     }
    4496             : 
    4497           6 :     if (arr->Item(4).GetUnit() != eCSSUnit_Null) {
    4498           6 :       item->mHasColor = true;
    4499             :       // 2nd argument can be bogus since inherit is not a valid color
    4500          12 :       unitOK = SetColor(arr->Item(4), 0, aPresContext, aContext, item->mColor,
    4501           6 :                         aConditions);
    4502           6 :       NS_ASSERTION(unitOK, "unexpected unit");
    4503             :     }
    4504             : 
    4505           6 :     if (aIsBoxShadow && arr->Item(5).GetUnit() == eCSSUnit_Enumerated) {
    4506           2 :       NS_ASSERTION(arr->Item(5).GetIntValue()
    4507             :                    == uint8_t(StyleBoxShadowType::Inset),
    4508             :                    "invalid keyword type for box shadow");
    4509           2 :       item->mInset = true;
    4510             :     } else {
    4511           4 :       item->mInset = false;
    4512             :     }
    4513             :   }
    4514             : 
    4515           6 :   return shadowList.forget();
    4516             : }
    4517             : 
    4518             : struct TextEmphasisChars
    4519             : {
    4520             :   const char16_t* mFilled;
    4521             :   const char16_t* mOpen;
    4522             : };
    4523             : 
    4524             : #define TEXT_EMPHASIS_CHARS_LIST() \
    4525             :   TEXT_EMPHASIS_CHARS_ITEM(u"", u"", NONE) \
    4526             :   TEXT_EMPHASIS_CHARS_ITEM(u"\u2022", u"\u25e6", DOT) \
    4527             :   TEXT_EMPHASIS_CHARS_ITEM(u"\u25cf", u"\u25cb", CIRCLE) \
    4528             :   TEXT_EMPHASIS_CHARS_ITEM(u"\u25c9", u"\u25ce", DOUBLE_CIRCLE) \
    4529             :   TEXT_EMPHASIS_CHARS_ITEM(u"\u25b2", u"\u25b3", TRIANGLE) \
    4530             :   TEXT_EMPHASIS_CHARS_ITEM(u"\ufe45", u"\ufe46", SESAME)
    4531             : 
    4532             : static constexpr TextEmphasisChars kTextEmphasisChars[] =
    4533             : {
    4534             : #define TEXT_EMPHASIS_CHARS_ITEM(filled_, open_, type_) \
    4535             :   { filled_, open_ }, // type_
    4536             :   TEXT_EMPHASIS_CHARS_LIST()
    4537             : #undef TEXT_EMPHASIS_CHARS_ITEM
    4538             : };
    4539             : 
    4540             : #define TEXT_EMPHASIS_CHARS_ITEM(filled_, open_, type_) \
    4541             :   static_assert(ArrayLength(filled_) <= 2 && \
    4542             :                 ArrayLength(open_) <= 2, \
    4543             :                 "emphasis marks should have no more than one char"); \
    4544             :   static_assert( \
    4545             :     *kTextEmphasisChars[NS_STYLE_TEXT_EMPHASIS_STYLE_##type_].mFilled == \
    4546             :     *filled_, "filled " #type_ " should be " #filled_); \
    4547             :   static_assert( \
    4548             :     *kTextEmphasisChars[NS_STYLE_TEXT_EMPHASIS_STYLE_##type_].mOpen == \
    4549             :     *open_, "open " #type_ " should be " #open_);
    4550             : TEXT_EMPHASIS_CHARS_LIST()
    4551             : #undef TEXT_EMPHASIS_CHARS_ITEM
    4552             : 
    4553             : #undef TEXT_EMPHASIS_CHARS_LIST
    4554             : 
    4555             : static void
    4556           0 : TruncateStringToSingleGrapheme(nsAString& aStr)
    4557             : {
    4558           0 :   unicode::ClusterIterator iter(aStr.Data(), aStr.Length());
    4559           0 :   if (!iter.AtEnd()) {
    4560           0 :     iter.Next();
    4561           0 :     if (!iter.AtEnd()) {
    4562             :       // Not mutating the string for common cases helps memory use
    4563             :       // since we share the buffer from the specified style into the
    4564             :       // computed style.
    4565           0 :       aStr.Truncate(iter - aStr.Data());
    4566             :     }
    4567             :   }
    4568           0 : }
    4569             : 
    4570             : struct LengthNumberCalcObj
    4571             : {
    4572             :   float mValue;
    4573             :   bool mIsNumber;
    4574             : };
    4575             : 
    4576             : struct LengthNumberCalcOps : public css::FloatCoeffsAlreadyNormalizedOps
    4577             : {
    4578             :   typedef LengthNumberCalcObj result_type;
    4579             :   GeckoStyleContext* const mStyleContext;
    4580             :   nsPresContext* const mPresContext;
    4581             :   RuleNodeCacheConditions& mConditions;
    4582             : 
    4583           0 :   LengthNumberCalcOps(GeckoStyleContext* aStyleContext,
    4584             :                       nsPresContext* aPresContext,
    4585             :                       RuleNodeCacheConditions& aConditions)
    4586           0 :     : mStyleContext(aStyleContext),
    4587             :       mPresContext(aPresContext),
    4588           0 :       mConditions(aConditions)
    4589             :   {
    4590           0 :   }
    4591             : 
    4592             :   result_type
    4593           0 :   MergeAdditive(nsCSSUnit aCalcFunction,
    4594             :                 result_type aValue1, result_type aValue2)
    4595             :   {
    4596           0 :     MOZ_ASSERT(aValue1.mIsNumber == aValue2.mIsNumber);
    4597             : 
    4598             :     LengthNumberCalcObj result;
    4599           0 :     result.mIsNumber = aValue1.mIsNumber;
    4600           0 :     if (aCalcFunction == eCSSUnit_Calc_Plus) {
    4601           0 :       result.mValue = aValue1.mValue + aValue2.mValue;
    4602           0 :       return result;
    4603             :     }
    4604           0 :     MOZ_ASSERT(aCalcFunction == eCSSUnit_Calc_Minus,
    4605             :                "unexpected unit");
    4606           0 :     result.mValue = aValue1.mValue - aValue2.mValue;
    4607           0 :     return result;
    4608             :   }
    4609             : 
    4610             :   result_type
    4611           0 :   MergeMultiplicativeL(nsCSSUnit aCalcFunction,
    4612             :                        float aValue1, result_type aValue2)
    4613             :   {
    4614           0 :     MOZ_ASSERT(aCalcFunction == eCSSUnit_Calc_Times_L,
    4615             :                "unexpected unit");
    4616             :     LengthNumberCalcObj result;
    4617           0 :     result.mIsNumber = aValue2.mIsNumber;
    4618           0 :     result.mValue = aValue1 * aValue2.mValue;
    4619           0 :     return result;
    4620             :   }
    4621             : 
    4622             :   result_type
    4623           0 :   MergeMultiplicativeR(nsCSSUnit aCalcFunction,
    4624             :                        result_type aValue1, float aValue2)
    4625             :   {
    4626             :     LengthNumberCalcObj result;
    4627           0 :     result.mIsNumber = aValue1.mIsNumber;
    4628           0 :     if (aCalcFunction == eCSSUnit_Calc_Times_R) {
    4629           0 :       result.mValue = aValue1.mValue * aValue2;
    4630           0 :       return result;
    4631             :     }
    4632           0 :     MOZ_ASSERT(aCalcFunction == eCSSUnit_Calc_Divided,
    4633             :                "unexpected unit");
    4634           0 :     result.mValue = aValue1.mValue / aValue2;
    4635           0 :     return result;
    4636             :   }
    4637             : 
    4638           0 :   result_type ComputeLeafValue(const nsCSSValue& aValue)
    4639             :   {
    4640             :     LengthNumberCalcObj result;
    4641           0 :     if (aValue.IsLengthUnit()) {
    4642           0 :       result.mIsNumber = false;
    4643           0 :       result.mValue = CalcLength(aValue, mStyleContext,
    4644           0 :                                       mPresContext, mConditions);
    4645             :     }
    4646           0 :     else if (eCSSUnit_Number == aValue.GetUnit()) {
    4647           0 :       result.mIsNumber = true;
    4648           0 :       result.mValue = aValue.GetFloatValue();
    4649             :     } else {
    4650           0 :       MOZ_ASSERT(false, "unexpected value");
    4651             :       result.mIsNumber = true;
    4652             :       result.mValue = 1.0f;
    4653             :     }
    4654             : 
    4655           0 :     return result;
    4656             :   }
    4657             : };
    4658             : 
    4659             : struct SetLineHeightCalcOps : public LengthNumberCalcOps
    4660             : {
    4661           0 :   SetLineHeightCalcOps(GeckoStyleContext* aStyleContext,
    4662             :                        nsPresContext* aPresContext,
    4663             :                        RuleNodeCacheConditions& aConditions)
    4664           0 :     : LengthNumberCalcOps(aStyleContext, aPresContext, aConditions)
    4665             :   {
    4666           0 :   }
    4667             : 
    4668           0 :   result_type ComputeLeafValue(const nsCSSValue& aValue)
    4669             :   {
    4670             :     LengthNumberCalcObj result;
    4671           0 :     if (aValue.IsLengthUnit()) {
    4672           0 :       result.mIsNumber = false;
    4673           0 :       result.mValue = CalcLength(aValue, mStyleContext,
    4674           0 :                                       mPresContext, mConditions);
    4675             :     }
    4676           0 :     else if (eCSSUnit_Percent == aValue.GetUnit()) {
    4677           0 :       mConditions.SetUncacheable();
    4678           0 :       result.mIsNumber = false;
    4679           0 :       nscoord fontSize = mStyleContext->StyleFont()->mFont.size;
    4680           0 :       result.mValue = fontSize * aValue.GetPercentValue();
    4681             :     }
    4682           0 :     else if (eCSSUnit_Number == aValue.GetUnit()) {
    4683           0 :       result.mIsNumber = true;
    4684           0 :       result.mValue = aValue.GetFloatValue();
    4685             :     } else {
    4686           0 :       MOZ_ASSERT(false, "unexpected value");
    4687             :       result.mIsNumber = true;
    4688             :       result.mValue = 1.0f;
    4689             :     }
    4690             : 
    4691           0 :     return result;
    4692             :   }
    4693             : };
    4694             : 
    4695             : const void*
    4696          46 : nsRuleNode::ComputeTextData(void* aStartStruct,
    4697             :                             const nsRuleData* aRuleData,
    4698             :                             GeckoStyleContext* aContext,
    4699             :                             nsRuleNode* aHighestNode,
    4700             :                             const RuleDetail aRuleDetail,
    4701             :                             const RuleNodeCacheConditions aConditions)
    4702             : {
    4703          92 :   COMPUTE_START_INHERITED(Text, text, parentText)
    4704             : 
    4705             :   auto setComplexColor = [&](const nsCSSValue* aValue,
    4706         138 :                              StyleComplexColor nsStyleText::* aField) {
    4707         276 :     SetComplexColor<eUnsetInherit>(*aValue, parentText->*aField,
    4708         276 :                                    StyleComplexColor::CurrentColor(),
    4709         414 :                                    mPresContext, text->*aField, conditions);
    4710         184 :   };
    4711             : 
    4712             :   // tab-size: number, length, calc, inherit
    4713          46 :   const nsCSSValue* tabSizeValue = aRuleData->ValueForTabSize();
    4714          46 :   if (tabSizeValue->GetUnit() == eCSSUnit_Initial) {
    4715           0 :     text->mTabSize = nsStyleCoord(float(NS_STYLE_TABSIZE_INITIAL), eStyleUnit_Factor);
    4716          46 :   } else if (eCSSUnit_Calc == tabSizeValue->GetUnit()) {
    4717           0 :     LengthNumberCalcOps ops(aContext, mPresContext, conditions);
    4718           0 :     LengthNumberCalcObj obj = css::ComputeCalc(*tabSizeValue, ops);
    4719           0 :     float value = obj.mValue < 0 ? 0 : obj.mValue;
    4720           0 :     if (obj.mIsNumber) {
    4721           0 :       text->mTabSize.SetFactorValue(value);
    4722             :     } else {
    4723           0 :       text->mTabSize.SetCoordValue(
    4724           0 :         NSToCoordRoundWithClamp(value));
    4725             :     }
    4726             :   } else {
    4727          46 :     SetCoord(*tabSizeValue, text->mTabSize, parentText->mTabSize,
    4728             :              SETCOORD_LH | SETCOORD_FACTOR | SETCOORD_UNSET_INHERIT,
    4729          92 :              aContext, mPresContext, conditions);
    4730             :   }
    4731             : 
    4732             :   // letter-spacing: normal, length, inherit
    4733          92 :   SetCoord(*aRuleData->ValueForLetterSpacing(),
    4734          92 :            text->mLetterSpacing, parentText->mLetterSpacing,
    4735             :            SETCOORD_LH | SETCOORD_NORMAL | SETCOORD_INITIAL_NORMAL |
    4736             :              SETCOORD_CALC_LENGTH_ONLY | SETCOORD_UNSET_INHERIT,
    4737          92 :            aContext, mPresContext, conditions);
    4738             : 
    4739             :   // text-shadow: none, list, inherit, initial
    4740          46 :   const nsCSSValue* textShadowValue = aRuleData->ValueForTextShadow();
    4741          46 :   if (textShadowValue->GetUnit() != eCSSUnit_Null) {
    4742          15 :     text->mTextShadow = nullptr;
    4743             : 
    4744             :     // Don't need to handle none/initial explicitly: The above assignment
    4745             :     // takes care of that
    4746          24 :     if (textShadowValue->GetUnit() == eCSSUnit_Inherit ||
    4747           9 :         textShadowValue->GetUnit() == eCSSUnit_Unset) {
    4748           6 :       conditions.SetUncacheable();
    4749           6 :       text->mTextShadow = parentText->mTextShadow;
    4750          18 :     } else if (textShadowValue->GetUnit() == eCSSUnit_List ||
    4751           9 :                textShadowValue->GetUnit() == eCSSUnit_ListDep) {
    4752             :       // List of arrays
    4753           0 :       text->mTextShadow = GetShadowData(textShadowValue->GetListValue(),
    4754           0 :                                         aContext, false, mPresContext, conditions);
    4755             :     }
    4756             :   }
    4757             : 
    4758             :   // line-height: normal, number, length, percent, calc, inherit
    4759          46 :   const nsCSSValue* lineHeightValue = aRuleData->ValueForLineHeight();
    4760          46 :   if (eCSSUnit_Percent == lineHeightValue->GetUnit()) {
    4761           0 :     conditions.SetUncacheable();
    4762             :     // Use |mFont.size| to pick up minimum font size.
    4763           0 :     text->mLineHeight.SetCoordValue(
    4764           0 :         NSToCoordRound(float(aContext->StyleFont()->mFont.size) *
    4765           0 :                        lineHeightValue->GetPercentValue()));
    4766             :   }
    4767          92 :   else if (eCSSUnit_Initial == lineHeightValue->GetUnit() ||
    4768          46 :            eCSSUnit_System_Font == lineHeightValue->GetUnit()) {
    4769           6 :     text->mLineHeight.SetNormalValue();
    4770             :   }
    4771          40 :   else if (eCSSUnit_Calc == lineHeightValue->GetUnit()) {
    4772           0 :     SetLineHeightCalcOps ops(aContext, mPresContext, conditions);
    4773           0 :     LengthNumberCalcObj obj = css::ComputeCalc(*lineHeightValue, ops);
    4774           0 :     if (obj.mIsNumber) {
    4775           0 :       text->mLineHeight.SetFactorValue(obj.mValue);
    4776             :     } else {
    4777           0 :       text->mLineHeight.SetCoordValue(
    4778           0 :         NSToCoordRoundWithClamp(obj.mValue));
    4779             :     }
    4780             :   }
    4781             :   else {
    4782          40 :     SetCoord(*lineHeightValue, text->mLineHeight, parentText->mLineHeight,
    4783             :              SETCOORD_LEH | SETCOORD_FACTOR | SETCOORD_NORMAL |
    4784             :                SETCOORD_UNSET_INHERIT,
    4785          80 :              aContext, mPresContext, conditions);
    4786          40 :     if (lineHeightValue->IsLengthUnit() &&
    4787           0 :         !lineHeightValue->IsRelativeLengthUnit()) {
    4788           0 :       nscoord lh = nsStyleFont::ZoomText(mPresContext,
    4789           0 :                                          text->mLineHeight.GetCoordValue());
    4790             : 
    4791           0 :       conditions.SetUncacheable();
    4792           0 :       const nsStyleFont *font = aContext->StyleFont();
    4793           0 :       nscoord minimumFontSize = mPresContext->MinFontSize(font->mLanguage);
    4794             : 
    4795           0 :       if (minimumFontSize > 0 && !mPresContext->IsChrome()) {
    4796           0 :         if (font->mSize != 0) {
    4797           0 :           lh = nscoord(float(lh) * float(font->mFont.size) / float(font->mSize));
    4798             :         } else {
    4799           0 :           lh = minimumFontSize;
    4800             :         }
    4801             :       }
    4802           0 :       text->mLineHeight.SetCoordValue(lh);
    4803             :     }
    4804             :   }
    4805             : 
    4806             : 
    4807             :   // text-align: enum, string, pair(enum|string), inherit, initial
    4808             :   // NOTE: string is not implemented yet.
    4809          46 :   const nsCSSValue* textAlignValue = aRuleData->ValueForTextAlign();
    4810          46 :   text->mTextAlignTrue = false;
    4811          46 :   if (eCSSUnit_String == textAlignValue->GetUnit()) {
    4812           0 :     NS_NOTYETIMPLEMENTED("align string");
    4813          50 :   } else if (eCSSUnit_Enumerated == textAlignValue->GetUnit() &&
    4814             :              NS_STYLE_TEXT_ALIGN_MOZ_CENTER_OR_INHERIT ==
    4815           4 :                textAlignValue->GetIntValue()) {
    4816           0 :     conditions.SetUncacheable();
    4817           0 :     uint8_t parentAlign = parentText->mTextAlign;
    4818           0 :     text->mTextAlign = (NS_STYLE_TEXT_ALIGN_START == parentAlign) ?
    4819           0 :       NS_STYLE_TEXT_ALIGN_CENTER : parentAlign;
    4820          50 :   } else if (eCSSUnit_Enumerated == textAlignValue->GetUnit() &&
    4821             :              NS_STYLE_TEXT_ALIGN_MATCH_PARENT ==
    4822           4 :                textAlignValue->GetIntValue()) {
    4823           0 :     conditions.SetUncacheable();
    4824           0 :     GeckoStyleContext* parent = aContext->GetParent();
    4825           0 :     if (parent) {
    4826           0 :       uint8_t parentAlign = parentText->mTextAlign;
    4827           0 :       uint8_t parentDirection = parent->StyleVisibility()->mDirection;
    4828           0 :       switch (parentAlign) {
    4829             :         case NS_STYLE_TEXT_ALIGN_START:
    4830           0 :           text->mTextAlign = parentDirection == NS_STYLE_DIRECTION_RTL ?
    4831           0 :             NS_STYLE_TEXT_ALIGN_RIGHT : NS_STYLE_TEXT_ALIGN_LEFT;
    4832           0 :           break;
    4833             : 
    4834             :         case NS_STYLE_TEXT_ALIGN_END:
    4835           0 :           text->mTextAlign = parentDirection == NS_STYLE_DIRECTION_RTL ?
    4836           0 :             NS_STYLE_TEXT_ALIGN_LEFT : NS_STYLE_TEXT_ALIGN_RIGHT;
    4837           0 :           break;
    4838             : 
    4839             :         default:
    4840           0 :           text->mTextAlign = parentAlign;
    4841             :       }
    4842             :     }
    4843             :   } else {
    4844          46 :     if (eCSSUnit_Pair == textAlignValue->GetUnit()) {
    4845             :       // Two values were specified, one must be 'true'.
    4846           0 :       text->mTextAlignTrue = true;
    4847           0 :       const nsCSSValuePair& textAlignValuePair = textAlignValue->GetPairValue();
    4848           0 :       textAlignValue = &textAlignValuePair.mXValue;
    4849           0 :       if (eCSSUnit_Enumerated == textAlignValue->GetUnit()) {
    4850           0 :         if (textAlignValue->GetIntValue() == NS_STYLE_TEXT_ALIGN_UNSAFE) {
    4851           0 :           textAlignValue = &textAlignValuePair.mYValue;
    4852             :         }
    4853           0 :       } else if (eCSSUnit_String == textAlignValue->GetUnit()) {
    4854           0 :         NS_NOTYETIMPLEMENTED("align string");
    4855             :       }
    4856          86 :     } else if (eCSSUnit_Inherit == textAlignValue->GetUnit() ||
    4857          40 :                eCSSUnit_Unset == textAlignValue->GetUnit()) {
    4858           6 :       text->mTextAlignTrue = parentText->mTextAlignTrue;
    4859             :     }
    4860          46 :     SetValue(*textAlignValue, text->mTextAlign, conditions,
    4861             :              SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    4862          46 :              parentText->mTextAlign,
    4863          46 :              NS_STYLE_TEXT_ALIGN_START);
    4864             :   }
    4865             : 
    4866             :   // text-align-last: enum, pair(enum), inherit, initial
    4867          46 :   const nsCSSValue* textAlignLastValue = aRuleData->ValueForTextAlignLast();
    4868          46 :   text->mTextAlignLastTrue = false;
    4869          46 :   if (eCSSUnit_Pair == textAlignLastValue->GetUnit()) {
    4870             :     // Two values were specified, one must be 'true'.
    4871           0 :     text->mTextAlignLastTrue = true;
    4872           0 :     const nsCSSValuePair& textAlignLastValuePair = textAlignLastValue->GetPairValue();
    4873           0 :     textAlignLastValue = &textAlignLastValuePair.mXValue;
    4874           0 :     if (eCSSUnit_Enumerated == textAlignLastValue->GetUnit()) {
    4875           0 :       if (textAlignLastValue->GetIntValue() == NS_STYLE_TEXT_ALIGN_UNSAFE) {
    4876           0 :         textAlignLastValue = &textAlignLastValuePair.mYValue;
    4877             :       }
    4878             :     }
    4879          92 :   } else if (eCSSUnit_Inherit == textAlignLastValue->GetUnit() ||
    4880          46 :              eCSSUnit_Unset == textAlignLastValue->GetUnit()) {
    4881           0 :     text->mTextAlignLastTrue = parentText->mTextAlignLastTrue;
    4882             :   }
    4883          46 :   SetValue(*textAlignLastValue, text->mTextAlignLast,
    4884             :            conditions,
    4885             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    4886          46 :            parentText->mTextAlignLast,
    4887          46 :            NS_STYLE_TEXT_ALIGN_AUTO);
    4888             : 
    4889             :   // text-indent: length, percent, calc, inherit, initial
    4890          46 :   SetCoord(*aRuleData->ValueForTextIndent(), text->mTextIndent, parentText->mTextIndent,
    4891             :            SETCOORD_LPH | SETCOORD_INITIAL_ZERO | SETCOORD_STORE_CALC |
    4892             :              SETCOORD_UNSET_INHERIT,
    4893          92 :            aContext, mPresContext, conditions);
    4894             : 
    4895             :   // text-justify: enum, inherit, initial
    4896          92 :   SetValue(*aRuleData->ValueForTextJustify(), text->mTextJustify, conditions,
    4897             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    4898          46 :            parentText->mTextJustify,
    4899          46 :            StyleTextJustify::Auto);
    4900             : 
    4901             :   // text-transform: enum, inherit, initial
    4902          46 :   SetValue(*aRuleData->ValueForTextTransform(), text->mTextTransform, conditions,
    4903             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    4904          46 :            parentText->mTextTransform,
    4905          46 :            NS_STYLE_TEXT_TRANSFORM_NONE);
    4906             : 
    4907             :   // white-space: enum, inherit, initial
    4908          92 :   SetValue(*aRuleData->ValueForWhiteSpace(), text->mWhiteSpace, conditions,
    4909             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    4910          46 :            parentText->mWhiteSpace,
    4911          46 :            StyleWhiteSpace::Normal);
    4912             : 
    4913             :   // word-break: enum, inherit, initial
    4914          46 :   SetValue(*aRuleData->ValueForWordBreak(), text->mWordBreak, conditions,
    4915             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    4916          46 :            parentText->mWordBreak,
    4917          46 :            NS_STYLE_WORDBREAK_NORMAL);
    4918             : 
    4919             :   // word-spacing: normal, length, percent, inherit
    4920          46 :   const nsCSSValue* wordSpacingValue = aRuleData->ValueForWordSpacing();
    4921          46 :   if (wordSpacingValue->GetUnit() == eCSSUnit_Normal) {
    4922             :     // Do this so that "normal" computes to 0px, as the CSS 2.1 spec requires.
    4923           6 :     text->mWordSpacing.SetCoordValue(0);
    4924             :   } else {
    4925          80 :     SetCoord(*aRuleData->ValueForWordSpacing(),
    4926          80 :              text->mWordSpacing, parentText->mWordSpacing,
    4927             :              SETCOORD_LPH | SETCOORD_INITIAL_ZERO |
    4928             :                SETCOORD_STORE_CALC | SETCOORD_UNSET_INHERIT,
    4929          80 :              aContext, mPresContext, conditions);
    4930             :   }
    4931             : 
    4932             :   // overflow-wrap: enum, inherit, initial
    4933          46 :   SetValue(*aRuleData->ValueForOverflowWrap(), text->mOverflowWrap, conditions,
    4934             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    4935          46 :            parentText->mOverflowWrap,
    4936          46 :            NS_STYLE_OVERFLOWWRAP_NORMAL);
    4937             : 
    4938             :   // hyphens: enum, inherit, initial
    4939          92 :   SetValue(*aRuleData->ValueForHyphens(), text->mHyphens, conditions,
    4940             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    4941          46 :            parentText->mHyphens,
    4942          46 :            StyleHyphens::Manual);
    4943             : 
    4944             :   // ruby-align: enum, inherit, initial
    4945          92 :   SetValue(*aRuleData->ValueForRubyAlign(),
    4946          46 :            text->mRubyAlign, conditions,
    4947             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    4948          46 :            parentText->mRubyAlign,
    4949          46 :            NS_STYLE_RUBY_ALIGN_SPACE_AROUND);
    4950             : 
    4951             :   // ruby-position: enum, inherit, initial
    4952          92 :   SetValue(*aRuleData->ValueForRubyPosition(),
    4953          46 :            text->mRubyPosition, conditions,
    4954             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    4955          46 :            parentText->mRubyPosition,
    4956          46 :            NS_STYLE_RUBY_POSITION_OVER);
    4957             : 
    4958             :   // text-size-adjust: enum, inherit, initial
    4959          92 :   SetValue(*aRuleData->ValueForTextSizeAdjust(),
    4960          46 :            text->mTextSizeAdjust, conditions,
    4961             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    4962          46 :            parentText->mTextSizeAdjust,
    4963          46 :            NS_STYLE_TEXT_SIZE_ADJUST_AUTO);
    4964             : 
    4965             :   // text-combine-upright: enum, inherit, initial
    4966          92 :   SetValue(*aRuleData->ValueForTextCombineUpright(),
    4967          46 :            text->mTextCombineUpright,
    4968             :            conditions,
    4969             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    4970          46 :            parentText->mTextCombineUpright,
    4971          46 :            NS_STYLE_TEXT_COMBINE_UPRIGHT_NONE);
    4972             : 
    4973             :   // text-emphasis-color: color, string, inherit, initial
    4974          46 :   setComplexColor(aRuleData->ValueForTextEmphasisColor(),
    4975          46 :                   &nsStyleText::mTextEmphasisColor);
    4976             : 
    4977             :   // text-emphasis-position: enum, inherit, initial
    4978          92 :   SetValue(*aRuleData->ValueForTextEmphasisPosition(),
    4979          46 :            text->mTextEmphasisPosition,
    4980             :            conditions,
    4981             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    4982          46 :            parentText->mTextEmphasisPosition,
    4983             :            NS_STYLE_TEXT_EMPHASIS_POSITION_OVER |
    4984          46 :            NS_STYLE_TEXT_EMPHASIS_POSITION_RIGHT);
    4985             : 
    4986             :   // text-emphasis-style: string, enum, inherit, initial
    4987             :   const nsCSSValue* textEmphasisStyleValue =
    4988          46 :     aRuleData->ValueForTextEmphasisStyle();
    4989          46 :   switch (textEmphasisStyleValue->GetUnit()) {
    4990             :     case eCSSUnit_Null:
    4991          46 :       break;
    4992             :     case eCSSUnit_Initial:
    4993             :     case eCSSUnit_None: {
    4994           0 :       text->mTextEmphasisStyle = NS_STYLE_TEXT_EMPHASIS_STYLE_NONE;
    4995           0 :       text->mTextEmphasisStyleString = u"";
    4996           0 :       break;
    4997             :     }
    4998             :     case eCSSUnit_Inherit:
    4999             :     case eCSSUnit_Unset: {
    5000           0 :       conditions.SetUncacheable();
    5001           0 :       text->mTextEmphasisStyle = parentText->mTextEmphasisStyle;
    5002           0 :       text->mTextEmphasisStyleString = parentText->mTextEmphasisStyleString;
    5003           0 :       break;
    5004             :     }
    5005             :     case eCSSUnit_Enumerated: {
    5006           0 :       auto style = textEmphasisStyleValue->GetIntValue();
    5007             :       // If shape part is not specified, compute it according to the
    5008             :       // writing-mode. Note that, if the fill part (filled/open) is not
    5009             :       // specified, we compute it to filled per spec. Since that value
    5010             :       // is zero, no additional computation is needed. See the assertion
    5011             :       // in CSSParserImpl::ParseTextEmphasisStyle().
    5012           0 :       if (!(style & NS_STYLE_TEXT_EMPHASIS_STYLE_SHAPE_MASK)) {
    5013           0 :         conditions.SetUncacheable();
    5014           0 :         if (WritingMode(aContext).IsVertical()) {
    5015           0 :           style |= NS_STYLE_TEXT_EMPHASIS_STYLE_SESAME;
    5016             :         } else {
    5017           0 :           style |= NS_STYLE_TEXT_EMPHASIS_STYLE_CIRCLE;
    5018             :         }
    5019             :       }
    5020           0 :       text->mTextEmphasisStyle = style;
    5021           0 :       size_t shape = style & NS_STYLE_TEXT_EMPHASIS_STYLE_SHAPE_MASK;
    5022           0 :       MOZ_ASSERT(shape > 0 && shape < ArrayLength(kTextEmphasisChars));
    5023           0 :       const TextEmphasisChars& chars = kTextEmphasisChars[shape];
    5024           0 :       text->mTextEmphasisStyleString =
    5025           0 :         (style & NS_STYLE_TEXT_EMPHASIS_STYLE_FILL_MASK) ==
    5026           0 :         NS_STYLE_TEXT_EMPHASIS_STYLE_FILLED ? chars.mFilled : chars.mOpen;
    5027           0 :       break;
    5028             :     }
    5029             :     case eCSSUnit_String: {
    5030           0 :       text->mTextEmphasisStyle = NS_STYLE_TEXT_EMPHASIS_STYLE_STRING;
    5031           0 :       nsString strValue;
    5032           0 :       textEmphasisStyleValue->GetStringValue(strValue);
    5033           0 :       TruncateStringToSingleGrapheme(strValue);
    5034           0 :       text->mTextEmphasisStyleString = strValue;
    5035           0 :       break;
    5036             :     }
    5037             :     default:
    5038           0 :       MOZ_ASSERT_UNREACHABLE("Unknown value unit type");
    5039             :   }
    5040             : 
    5041             :   // text-rendering: enum, inherit, initial
    5042          92 :   SetValue(*aRuleData->ValueForTextRendering(),
    5043          46 :            text->mTextRendering, conditions,
    5044             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    5045          46 :            parentText->mTextRendering,
    5046          46 :            NS_STYLE_TEXT_RENDERING_AUTO);
    5047             : 
    5048             :   // -webkit-text-fill-color: color, string, inherit, initial
    5049          46 :   setComplexColor(aRuleData->ValueForWebkitTextFillColor(),
    5050          46 :                   &nsStyleText::mWebkitTextFillColor);
    5051             : 
    5052             :   // -webkit-text-stroke-color: color, string, inherit, initial
    5053          46 :   setComplexColor(aRuleData->ValueForWebkitTextStrokeColor(),
    5054          46 :                   &nsStyleText::mWebkitTextStrokeColor);
    5055             : 
    5056             :   // -webkit-text-stroke-width: length, inherit, initial, enum
    5057             :   Maybe<nscoord> coord =
    5058             :     ComputeLineWidthValue<eUnsetInherit>(
    5059          46 :       *aRuleData->ValueForWebkitTextStrokeWidth(),
    5060          46 :       parentText->mWebkitTextStrokeWidth, 0,
    5061         138 :       aContext, mPresContext, conditions);
    5062          46 :   if (coord.isSome()) {
    5063           0 :     text->mWebkitTextStrokeWidth = *coord;
    5064             :   }
    5065             : 
    5066             :   // -moz-control-character-visibility: enum, inherit, initial
    5067         138 :   SetValue(*aRuleData->ValueForControlCharacterVisibility(),
    5068          46 :            text->mControlCharacterVisibility,
    5069             :            conditions,
    5070             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    5071          46 :            parentText->mControlCharacterVisibility,
    5072          92 :            nsCSSParser::ControlCharVisibilityDefault());
    5073             : 
    5074          92 :   COMPUTE_END_INHERITED(Text, text)
    5075             : }
    5076             : 
    5077             : const void*
    5078         121 : nsRuleNode::ComputeTextResetData(void* aStartStruct,
    5079             :                                  const nsRuleData* aRuleData,
    5080             :                                  GeckoStyleContext* aContext,
    5081             :                                  nsRuleNode* aHighestNode,
    5082             :                                  const RuleDetail aRuleDetail,
    5083             :                                  const RuleNodeCacheConditions aConditions)
    5084             : {
    5085         242 :   COMPUTE_START_RESET(TextReset, text, parentText)
    5086             : 
    5087             :   // text-decoration-line: enum (bit field), inherit, initial
    5088             :   const nsCSSValue* decorationLineValue =
    5089         121 :     aRuleData->ValueForTextDecorationLine();
    5090         121 :   if (eCSSUnit_Enumerated == decorationLineValue->GetUnit()) {
    5091           0 :     text->mTextDecorationLine = decorationLineValue->GetIntValue();
    5092         121 :   } else if (eCSSUnit_Inherit == decorationLineValue->GetUnit()) {
    5093          12 :     conditions.SetUncacheable();
    5094          12 :     text->mTextDecorationLine = parentText->mTextDecorationLine;
    5095         218 :   } else if (eCSSUnit_Initial == decorationLineValue->GetUnit() ||
    5096         109 :              eCSSUnit_Unset == decorationLineValue->GetUnit()) {
    5097           0 :     text->mTextDecorationLine = NS_STYLE_TEXT_DECORATION_LINE_NONE;
    5098             :   }
    5099             : 
    5100             :   // text-decoration-color: color, string, enum, inherit, initial
    5101         242 :   SetComplexColor<eUnsetInitial>(*aRuleData->ValueForTextDecorationColor(),
    5102             :                                  parentText->mTextDecorationColor,
    5103         242 :                                  StyleComplexColor::CurrentColor(),
    5104         121 :                                  mPresContext,
    5105         121 :                                  text->mTextDecorationColor, conditions);
    5106             : 
    5107             :   // text-decoration-style: enum, inherit, initial
    5108             :   const nsCSSValue* decorationStyleValue =
    5109         121 :     aRuleData->ValueForTextDecorationStyle();
    5110         121 :   if (eCSSUnit_Enumerated == decorationStyleValue->GetUnit()) {
    5111           0 :     text->mTextDecorationStyle = decorationStyleValue->GetIntValue();
    5112         121 :   } else if (eCSSUnit_Inherit == decorationStyleValue->GetUnit()) {
    5113          12 :     text->mTextDecorationStyle = parentText->mTextDecorationStyle;
    5114          12 :     conditions.SetUncacheable();
    5115         218 :   } else if (eCSSUnit_Initial == decorationStyleValue->GetUnit() ||
    5116         109 :              eCSSUnit_Unset == decorationStyleValue->GetUnit()) {
    5117           0 :     text->mTextDecorationStyle = NS_STYLE_TEXT_DECORATION_STYLE_SOLID;
    5118             :   }
    5119             : 
    5120             :   // text-overflow: enum, string, pair(enum|string), inherit, initial
    5121             :   const nsCSSValue* textOverflowValue =
    5122         121 :     aRuleData->ValueForTextOverflow();
    5123         242 :   if (eCSSUnit_Initial == textOverflowValue->GetUnit() ||
    5124         121 :       eCSSUnit_Unset == textOverflowValue->GetUnit()) {
    5125           0 :     text->mTextOverflow = nsStyleTextOverflow();
    5126         121 :   } else if (eCSSUnit_Inherit == textOverflowValue->GetUnit()) {
    5127          88 :     conditions.SetUncacheable();
    5128          88 :     text->mTextOverflow = parentText->mTextOverflow;
    5129          33 :   } else if (eCSSUnit_Enumerated == textOverflowValue->GetUnit()) {
    5130             :     // A single enumerated value.
    5131           0 :     SetValue(*textOverflowValue, text->mTextOverflow.mRight.mType,
    5132             :              conditions,
    5133           0 :              SETVAL_ENUMERATED, parentText->mTextOverflow.mRight.mType,
    5134           0 :              NS_STYLE_TEXT_OVERFLOW_CLIP);
    5135           0 :     text->mTextOverflow.mRight.mString.Truncate();
    5136           0 :     text->mTextOverflow.mLeft.mType = NS_STYLE_TEXT_OVERFLOW_CLIP;
    5137           0 :     text->mTextOverflow.mLeft.mString.Truncate();
    5138           0 :     text->mTextOverflow.mLogicalDirections = true;
    5139          33 :   } else if (eCSSUnit_String == textOverflowValue->GetUnit()) {
    5140             :     // A single string value.
    5141           0 :     text->mTextOverflow.mRight.mType = NS_STYLE_TEXT_OVERFLOW_STRING;
    5142           0 :     textOverflowValue->GetStringValue(text->mTextOverflow.mRight.mString);
    5143           0 :     text->mTextOverflow.mLeft.mType = NS_STYLE_TEXT_OVERFLOW_CLIP;
    5144           0 :     text->mTextOverflow.mLeft.mString.Truncate();
    5145           0 :     text->mTextOverflow.mLogicalDirections = true;
    5146          33 :   } else if (eCSSUnit_Pair == textOverflowValue->GetUnit()) {
    5147             :     // Two values were specified.
    5148           0 :     text->mTextOverflow.mLogicalDirections = false;
    5149             :     const nsCSSValuePair& textOverflowValuePair =
    5150           0 :       textOverflowValue->GetPairValue();
    5151             : 
    5152           0 :     const nsCSSValue *textOverflowLeftValue = &textOverflowValuePair.mXValue;
    5153           0 :     if (eCSSUnit_Enumerated == textOverflowLeftValue->GetUnit()) {
    5154           0 :       SetValue(*textOverflowLeftValue, text->mTextOverflow.mLeft.mType,
    5155             :                conditions,
    5156           0 :                SETVAL_ENUMERATED, parentText->mTextOverflow.mLeft.mType,
    5157           0 :                NS_STYLE_TEXT_OVERFLOW_CLIP);
    5158           0 :       text->mTextOverflow.mLeft.mString.Truncate();
    5159           0 :     } else if (eCSSUnit_String == textOverflowLeftValue->GetUnit()) {
    5160           0 :       textOverflowLeftValue->GetStringValue(text->mTextOverflow.mLeft.mString);
    5161           0 :       text->mTextOverflow.mLeft.mType = NS_STYLE_TEXT_OVERFLOW_STRING;
    5162             :     }
    5163             : 
    5164           0 :     const nsCSSValue *textOverflowRightValue = &textOverflowValuePair.mYValue;
    5165           0 :     if (eCSSUnit_Enumerated == textOverflowRightValue->GetUnit()) {
    5166           0 :       SetValue(*textOverflowRightValue, text->mTextOverflow.mRight.mType,
    5167             :                conditions,
    5168           0 :                SETVAL_ENUMERATED, parentText->mTextOverflow.mRight.mType,
    5169           0 :                NS_STYLE_TEXT_OVERFLOW_CLIP);
    5170           0 :       text->mTextOverflow.mRight.mString.Truncate();
    5171           0 :     } else if (eCSSUnit_String == textOverflowRightValue->GetUnit()) {
    5172           0 :       textOverflowRightValue->GetStringValue(text->mTextOverflow.mRight.mString);
    5173           0 :       text->mTextOverflow.mRight.mType = NS_STYLE_TEXT_OVERFLOW_STRING;
    5174             :     }
    5175             :   }
    5176             : 
    5177             :   // unicode-bidi: enum, inherit, initial
    5178         121 :   SetValue(*aRuleData->ValueForUnicodeBidi(), text->mUnicodeBidi, conditions,
    5179             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    5180         121 :            parentText->mUnicodeBidi,
    5181         121 :            NS_STYLE_UNICODE_BIDI_NORMAL);
    5182             : 
    5183             :   // initial-letter: normal, number, array(number, integer?), initial
    5184         121 :   const nsCSSValue* initialLetterValue = aRuleData->ValueForInitialLetter();
    5185         121 :   if (initialLetterValue->GetUnit() == eCSSUnit_Null) {
    5186             :     // We don't want to change anything in this case.
    5187           0 :   } else if (initialLetterValue->GetUnit() == eCSSUnit_Inherit) {
    5188           0 :     conditions.SetUncacheable();
    5189           0 :     text->mInitialLetterSink = parentText->mInitialLetterSink;
    5190           0 :     text->mInitialLetterSize = parentText->mInitialLetterSize;
    5191           0 :   } else if (initialLetterValue->GetUnit() == eCSSUnit_Initial ||
    5192           0 :              initialLetterValue->GetUnit() == eCSSUnit_Unset ||
    5193           0 :              initialLetterValue->GetUnit() == eCSSUnit_Normal) {
    5194             :     // Use invalid values in initial-letter property to mean normal. So we can
    5195             :     // determine whether it is normal by checking mInitialLetterSink == 0.
    5196           0 :     text->mInitialLetterSink = 0;
    5197           0 :     text->mInitialLetterSize = 0.0f;
    5198           0 :   } else if (initialLetterValue->GetUnit() == eCSSUnit_Array) {
    5199           0 :     const nsCSSValue& firstValue = initialLetterValue->GetArrayValue()->Item(0);
    5200           0 :     const nsCSSValue& secondValue = initialLetterValue->GetArrayValue()->Item(1);
    5201           0 :     MOZ_ASSERT(firstValue.GetUnit() == eCSSUnit_Number &&
    5202             :                secondValue.GetUnit() == eCSSUnit_Integer,
    5203             :                "unexpected value unit");
    5204           0 :     text->mInitialLetterSize = firstValue.GetFloatValue();
    5205           0 :     text->mInitialLetterSink = secondValue.GetIntValue();
    5206           0 :   } else if (initialLetterValue->GetUnit() == eCSSUnit_Number) {
    5207           0 :     text->mInitialLetterSize = initialLetterValue->GetFloatValue();
    5208           0 :     text->mInitialLetterSink = NSToCoordFloorClamped(text->mInitialLetterSize);
    5209             :   } else {
    5210           0 :     MOZ_ASSERT_UNREACHABLE("unknown unit for initial-letter");
    5211             :   }
    5212             : 
    5213         242 :   COMPUTE_END_RESET(TextReset, text)
    5214             : }
    5215             : 
    5216             : const void*
    5217        1490 : nsRuleNode::ComputeUserInterfaceData(void* aStartStruct,
    5218             :                                      const nsRuleData* aRuleData,
    5219             :                                      GeckoStyleContext* aContext,
    5220             :                                      nsRuleNode* aHighestNode,
    5221             :                                      const RuleDetail aRuleDetail,
    5222             :                                      const RuleNodeCacheConditions aConditions)
    5223             : {
    5224        2980 :   COMPUTE_START_INHERITED(UserInterface, ui, parentUI)
    5225             : 
    5226             :   // cursor: enum, url, inherit
    5227        1490 :   const nsCSSValue* cursorValue = aRuleData->ValueForCursor();
    5228        1490 :   nsCSSUnit cursorUnit = cursorValue->GetUnit();
    5229        1490 :   if (cursorUnit != eCSSUnit_Null) {
    5230         228 :     ui->mCursorImages.Clear();
    5231             : 
    5232         228 :     if (cursorUnit == eCSSUnit_Inherit ||
    5233             :         cursorUnit == eCSSUnit_Unset) {
    5234           0 :       conditions.SetUncacheable();
    5235           0 :       ui->mCursor = parentUI->mCursor;
    5236           0 :       ui->mCursorImages = parentUI->mCursorImages;
    5237             :     }
    5238         228 :     else if (cursorUnit == eCSSUnit_Initial) {
    5239           0 :       ui->mCursor = NS_STYLE_CURSOR_AUTO;
    5240             :     }
    5241             :     else {
    5242             :       // The parser will never create a list that is *all* URL values --
    5243             :       // that's invalid.
    5244         228 :       MOZ_ASSERT(cursorUnit == eCSSUnit_List || cursorUnit == eCSSUnit_ListDep,
    5245             :                  "unrecognized cursor unit");
    5246         228 :       const nsCSSValueList* list = cursorValue->GetListValue();
    5247         228 :       for ( ; list->mValue.GetUnit() == eCSSUnit_Array; list = list->mNext) {
    5248           0 :         nsCSSValue::Array* arr = list->mValue.GetArrayValue();
    5249           0 :         nsCursorImage* item = ui->mCursorImages.AppendElement();
    5250             :         item->mImage =
    5251           0 :           CreateStyleImageRequest(aContext->PresContext(), arr->Item(0),
    5252           0 :                                   nsStyleImageRequest::Mode::Discard);
    5253           0 :         if (arr->Item(1).GetUnit() != eCSSUnit_Null) {
    5254           0 :           item->mHaveHotspot = true;
    5255           0 :           item->mHotspotX = arr->Item(1).GetFloatValue();
    5256           0 :           item->mHotspotY = arr->Item(2).GetFloatValue();
    5257             :         }
    5258             :       }
    5259             : 
    5260         228 :       NS_ASSERTION(list, "Must have non-array value at the end");
    5261         228 :       NS_ASSERTION(list->mValue.GetUnit() == eCSSUnit_Enumerated,
    5262             :                    "Unexpected fallback value at end of cursor list");
    5263         228 :       ui->mCursor = list->mValue.GetIntValue();
    5264             :     }
    5265             :   }
    5266             : 
    5267             :   // user-input: enum, inherit, initial
    5268        1490 :   SetValue(*aRuleData->ValueForUserInput(),
    5269             :            ui->mUserInput, conditions,
    5270             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    5271        1490 :            parentUI->mUserInput,
    5272        1490 :            StyleUserInput::Auto);
    5273             : 
    5274             :   // user-modify: enum, inherit, initial
    5275        1490 :   SetValue(*aRuleData->ValueForUserModify(),
    5276             :            ui->mUserModify, conditions,
    5277             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    5278        1490 :            parentUI->mUserModify,
    5279        1490 :            StyleUserModify::ReadOnly);
    5280             : 
    5281             :   // user-focus: enum, inherit, initial
    5282        1490 :   SetValue(*aRuleData->ValueForUserFocus(),
    5283             :            ui->mUserFocus, conditions,
    5284             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    5285        1490 :            parentUI->mUserFocus,
    5286        1490 :            StyleUserFocus::None);
    5287             : 
    5288             :   // pointer-events: enum, inherit, initial
    5289        1490 :   SetValue(*aRuleData->ValueForPointerEvents(), ui->mPointerEvents,
    5290             :            conditions,
    5291             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    5292        1490 :            parentUI->mPointerEvents,
    5293        1490 :            NS_STYLE_POINTER_EVENTS_AUTO);
    5294             : 
    5295             :   // caret-color: auto, color, inherit
    5296        1490 :   const nsCSSValue* caretColorValue = aRuleData->ValueForCaretColor();
    5297        2980 :   SetComplexColor<eUnsetInherit>(*caretColorValue,
    5298             :                                  parentUI->mCaretColor,
    5299        2980 :                                  StyleComplexColor::Auto(),
    5300        1490 :                                  mPresContext,
    5301        1490 :                                  ui->mCaretColor, conditions);
    5302             : 
    5303        2980 :   COMPUTE_END_INHERITED(UserInterface, ui)
    5304             : }
    5305             : 
    5306             : const void*
    5307           9 : nsRuleNode::ComputeUIResetData(void* aStartStruct,
    5308             :                                const nsRuleData* aRuleData,
    5309             :                                GeckoStyleContext* aContext,
    5310             :                                nsRuleNode* aHighestNode,
    5311             :                                const RuleDetail aRuleDetail,
    5312             :                                const RuleNodeCacheConditions aConditions)
    5313             : {
    5314          18 :   COMPUTE_START_RESET(UIReset, ui, parentUI)
    5315             : 
    5316             :   // user-select: enum, inherit, initial
    5317           9 :   SetValue(*aRuleData->ValueForUserSelect(),
    5318             :            ui->mUserSelect, conditions,
    5319             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    5320           9 :            parentUI->mUserSelect,
    5321           9 :            StyleUserSelect::Auto);
    5322             : 
    5323             :   // ime-mode: enum, inherit, initial
    5324           9 :   SetValue(*aRuleData->ValueForImeMode(),
    5325             :            ui->mIMEMode, conditions,
    5326             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    5327           9 :            parentUI->mIMEMode,
    5328           9 :            NS_STYLE_IME_MODE_AUTO);
    5329             : 
    5330             :   // force-broken-image-icons: integer, inherit, initial
    5331           9 :   SetValue(*aRuleData->ValueForForceBrokenImageIcon(),
    5332             :            ui->mForceBrokenImageIcon,
    5333             :            conditions,
    5334             :            SETVAL_INTEGER | SETVAL_UNSET_INITIAL,
    5335          18 :            parentUI->mForceBrokenImageIcon, 0);
    5336             : 
    5337             :   // -moz-window-dragging: enum, inherit, initial
    5338           9 :   SetValue(*aRuleData->ValueForWindowDragging(),
    5339             :            ui->mWindowDragging, conditions,
    5340             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    5341           9 :            parentUI->mWindowDragging,
    5342           9 :            StyleWindowDragging::Default);
    5343             : 
    5344             :   // -moz-window-shadow: enum, inherit, initial
    5345           9 :   SetValue(*aRuleData->ValueForWindowShadow(),
    5346             :            ui->mWindowShadow, conditions,
    5347             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    5348           9 :            parentUI->mWindowShadow,
    5349           9 :            NS_STYLE_WINDOW_SHADOW_DEFAULT);
    5350             : 
    5351             :   // -moz-window-opacity: factor, inherit, initial
    5352           9 :   SetFactor(*aRuleData->ValueForWindowOpacity(),
    5353             :             ui->mWindowOpacity, conditions,
    5354           9 :             parentUI->mWindowOpacity, 1.0f,
    5355           9 :             SETFCT_OPACITY | SETFCT_UNSET_INITIAL);
    5356             : 
    5357             :   // -moz-window-transform
    5358           9 :   SetTransformValue(*aRuleData->ValueForWindowTransform(),
    5359             :                     ui->mSpecifiedWindowTransform, conditions,
    5360           9 :                     parentUI->mSpecifiedWindowTransform);
    5361             : 
    5362             :   // -moz-window-transform-origin
    5363             :   const nsCSSValue* windowTransformOriginValue =
    5364           9 :     aRuleData->ValueForWindowTransformOrigin();
    5365           9 :   if (windowTransformOriginValue->GetUnit() != eCSSUnit_Null) {
    5366             :     mozilla::DebugOnly<bool> result =
    5367           0 :       SetPairCoords(*windowTransformOriginValue,
    5368             :                     ui->mWindowTransformOrigin[0],
    5369             :                     ui->mWindowTransformOrigin[1],
    5370             :                     parentUI->mWindowTransformOrigin[0],
    5371             :                     parentUI->mWindowTransformOrigin[1],
    5372             :                     SETCOORD_LPH | SETCOORD_INITIAL_HALF |
    5373             :                       SETCOORD_BOX_POSITION | SETCOORD_STORE_CALC |
    5374             :                       SETCOORD_UNSET_INITIAL,
    5375           0 :                     aContext, mPresContext, conditions);
    5376           0 :     NS_ASSERTION(result, "Malformed -moz-window-transform-origin parse!");
    5377             :   }
    5378             : 
    5379          18 :   COMPUTE_END_RESET(UIReset, ui)
    5380             : }
    5381             : 
    5382             : // Information about each transition or animation property that is
    5383             : // constant.
    5384             : struct TransitionPropInfo {
    5385             :   nsCSSPropertyID property;
    5386             :   // Location of the count of the property's computed value.
    5387             :   uint32_t nsStyleDisplay::* sdCount;
    5388             : };
    5389             : 
    5390             : // Each property's index in this array must match its index in the
    5391             : // mutable array |transitionPropData| below.
    5392             : static const TransitionPropInfo transitionPropInfo[4] = {
    5393             :   { eCSSProperty_transition_delay,
    5394             :     &nsStyleDisplay::mTransitionDelayCount },
    5395             :   { eCSSProperty_transition_duration,
    5396             :     &nsStyleDisplay::mTransitionDurationCount },
    5397             :   { eCSSProperty_transition_property,
    5398             :     &nsStyleDisplay::mTransitionPropertyCount },
    5399             :   { eCSSProperty_transition_timing_function,
    5400             :     &nsStyleDisplay::mTransitionTimingFunctionCount },
    5401             : };
    5402             : 
    5403             : // Each property's index in this array must match its index in the
    5404             : // mutable array |animationPropData| below.
    5405             : static const TransitionPropInfo animationPropInfo[8] = {
    5406             :   { eCSSProperty_animation_delay,
    5407             :     &nsStyleDisplay::mAnimationDelayCount },
    5408             :   { eCSSProperty_animation_duration,
    5409             :     &nsStyleDisplay::mAnimationDurationCount },
    5410             :   { eCSSProperty_animation_name,
    5411             :     &nsStyleDisplay::mAnimationNameCount },
    5412             :   { eCSSProperty_animation_timing_function,
    5413             :     &nsStyleDisplay::mAnimationTimingFunctionCount },
    5414             :   { eCSSProperty_animation_direction,
    5415             :     &nsStyleDisplay::mAnimationDirectionCount },
    5416             :   { eCSSProperty_animation_fill_mode,
    5417             :     &nsStyleDisplay::mAnimationFillModeCount },
    5418             :   { eCSSProperty_animation_play_state,
    5419             :     &nsStyleDisplay::mAnimationPlayStateCount },
    5420             :   { eCSSProperty_animation_iteration_count,
    5421             :     &nsStyleDisplay::mAnimationIterationCountCount },
    5422             : };
    5423             : 
    5424             : // Information about each transition or animation property that changes
    5425             : // during ComputeDisplayData.
    5426             : struct TransitionPropData {
    5427             :   const nsCSSValueList *list;
    5428             :   nsCSSUnit unit;
    5429             :   uint32_t num;
    5430             : };
    5431             : 
    5432             : static uint32_t
    5433        1342 : CountTransitionProps(const TransitionPropInfo* aInfo,
    5434             :                      TransitionPropData* aData,
    5435             :                      size_t aLength,
    5436             :                      nsStyleDisplay* aDisplay,
    5437             :                      const nsStyleDisplay* aParentDisplay,
    5438             :                      const nsRuleData* aRuleData,
    5439             :                      RuleNodeCacheConditions& aConditions)
    5440             : {
    5441             :   // The four transition properties or eight animation properties are
    5442             :   // stored in nsCSSDisplay in a single array for all properties.  The
    5443             :   // number of transitions is equal to the number of items in the
    5444             :   // longest property's value.  Properties that have fewer values than
    5445             :   // the longest are filled in by repeating the list.  However, this
    5446             :   // repetition does not extend the computed value of that particular
    5447             :   // property (for purposes of inheritance, or, in our code, for when
    5448             :   // other properties are overridden by a more specific rule).
    5449             : 
    5450             :   // But actually, since the spec isn't clear yet, we'll fully compute
    5451             :   // all of them (so we can switch easily later), but only care about
    5452             :   // the ones up to the number of items for 'transition-property', per
    5453             :   // http://lists.w3.org/Archives/Public/www-style/2009Aug/0109.html .
    5454             : 
    5455             :   // Transitions are difficult to handle correctly because of this.  For
    5456             :   // example, we need to handle scenarios such as:
    5457             :   //  * a more general rule specifies transition-property: a, b, c;
    5458             :   //  * a more specific rule overrides as transition-property: d;
    5459             :   //
    5460             :   // If only the general rule applied, we would fill in the extra
    5461             :   // properties (duration, delay, etc) with initial values to create 3
    5462             :   // fully-specified transitions.  But when the more specific rule
    5463             :   // applies, we should only create a single transition.  In order to do
    5464             :   // this we need to remember which properties were explicitly specified
    5465             :   // and which ones were just filled in with initial values to get a
    5466             :   // fully-specified transition, which we do by remembering the number
    5467             :   // of values for each property.
    5468             : 
    5469        1342 :   uint32_t numTransitions = 0;
    5470        9394 :   for (size_t i = 0; i < aLength; ++i) {
    5471        8052 :     const TransitionPropInfo& info = aInfo[i];
    5472        8052 :     TransitionPropData& data = aData[i];
    5473             : 
    5474             :     // cache whether any of the properties are specified as 'inherit' so
    5475             :     // we can use it below
    5476             : 
    5477        8052 :     const nsCSSValue& value = *aRuleData->ValueFor(info.property);
    5478        8052 :     data.unit = value.GetUnit();
    5479       23895 :     data.list = (value.GetUnit() == eCSSUnit_List ||
    5480        7791 :                  value.GetUnit() == eCSSUnit_ListDep)
    5481        8313 :                   ? value.GetListValue() : nullptr;
    5482             : 
    5483             :     // General algorithm to determine how many total transitions we need
    5484             :     // to build.  For each property:
    5485             :     //  - if there is no value specified in for the property in
    5486             :     //    displayData, use the values from the start struct, but only if
    5487             :     //    they were explicitly specified
    5488             :     //  - if there is a value specified for the property in displayData:
    5489             :     //    - if the value is 'inherit', count the number of values for
    5490             :     //      that property are specified by the parent, but only those
    5491             :     //      that were explicitly specified
    5492             :     //    - otherwise, count the number of values specified in displayData
    5493             : 
    5494             : 
    5495             :     // calculate number of elements
    5496        8052 :     if (data.unit == eCSSUnit_Inherit) {
    5497           0 :       data.num = aParentDisplay->*(info.sdCount);
    5498           0 :       aConditions.SetUncacheable();
    5499        8052 :     } else if (data.list) {
    5500         261 :       data.num = ListLength(data.list);
    5501             :     } else {
    5502        7791 :       data.num = aDisplay->*(info.sdCount);
    5503             :     }
    5504        8052 :     if (data.num > numTransitions)
    5505        1353 :       numTransitions = data.num;
    5506             :   }
    5507             : 
    5508        1342 :   return numTransitions;
    5509             : }
    5510             : 
    5511             : /* static */ void
    5512          65 : nsRuleNode::ComputeTimingFunction(const nsCSSValue& aValue,
    5513             :                                   nsTimingFunction& aResult)
    5514             : {
    5515          65 :   switch (aValue.GetUnit()) {
    5516             :     case eCSSUnit_Enumerated:
    5517          62 :       aResult = nsTimingFunction(aValue.GetIntValue());
    5518          62 :       break;
    5519             :     case eCSSUnit_Cubic_Bezier:
    5520             :       {
    5521           0 :         nsCSSValue::Array* array = aValue.GetArrayValue();
    5522           0 :         NS_ASSERTION(array && array->Count() == 4,
    5523             :                      "Need 4 control points");
    5524           0 :         aResult = nsTimingFunction(array->Item(0).GetFloatValue(),
    5525           0 :                                    array->Item(1).GetFloatValue(),
    5526           0 :                                    array->Item(2).GetFloatValue(),
    5527           0 :                                    array->Item(3).GetFloatValue());
    5528             :       }
    5529           0 :       break;
    5530             :     case eCSSUnit_Steps:
    5531             :       {
    5532           3 :         nsCSSValue::Array* array = aValue.GetArrayValue();
    5533           3 :         NS_ASSERTION(array && array->Count() == 2,
    5534             :                      "Need 2 items");
    5535           3 :         NS_ASSERTION(array->Item(0).GetUnit() == eCSSUnit_Integer,
    5536             :                      "unexpected first value");
    5537           3 :         NS_ASSERTION(array->Item(1).GetUnit() == eCSSUnit_Enumerated &&
    5538             :                      (array->Item(1).GetIntValue() ==
    5539             :                        NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_START ||
    5540             :                       array->Item(1).GetIntValue() ==
    5541             :                        NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END ||
    5542             :                       array->Item(1).GetIntValue() == -1),
    5543             :                      "unexpected second value");
    5544             :         nsTimingFunction::Type type =
    5545           3 :           (array->Item(1).GetIntValue() ==
    5546           3 :             NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_START) ?
    5547             :               nsTimingFunction::Type::StepStart :
    5548           3 :               nsTimingFunction::Type::StepEnd;
    5549           3 :         aResult = nsTimingFunction(type, array->Item(0).GetIntValue());
    5550             :       }
    5551           3 :       break;
    5552             :     case eCSSUnit_Function:
    5553             :       {
    5554           0 :         nsCSSValue::Array* array = aValue.GetArrayValue();
    5555           0 :         NS_ASSERTION(array && array->Count() == 2, "Need 2 items");
    5556           0 :         NS_ASSERTION(array->Item(0).GetKeywordValue() == eCSSKeyword_frames,
    5557             :                      "should be frames function");
    5558           0 :         NS_ASSERTION(array->Item(1).GetUnit() == eCSSUnit_Integer,
    5559             :                      "unexpected frames function value");
    5560           0 :         aResult = nsTimingFunction(nsTimingFunction::Type::Frames,
    5561           0 :                                    array->Item(1).GetIntValue());
    5562             :       }
    5563           0 :       break;
    5564             :     default:
    5565           0 :       NS_NOTREACHED("Invalid transition property unit");
    5566             :   }
    5567          65 : }
    5568             : 
    5569             : static uint8_t
    5570           0 : GetWillChangeBitFieldFromPropFlags(const nsCSSPropertyID& aProp)
    5571             : {
    5572           0 :   uint8_t willChangeBitField = 0;
    5573           0 :   if (nsCSSProps::PropHasFlags(aProp, CSS_PROPERTY_CREATES_STACKING_CONTEXT)) {
    5574           0 :     willChangeBitField |= NS_STYLE_WILL_CHANGE_STACKING_CONTEXT;
    5575             :   }
    5576             : 
    5577           0 :   if (nsCSSProps::PropHasFlags(aProp, CSS_PROPERTY_FIXPOS_CB)) {
    5578           0 :     willChangeBitField |= NS_STYLE_WILL_CHANGE_FIXPOS_CB;
    5579             :   }
    5580             : 
    5581           0 :   if (nsCSSProps::PropHasFlags(aProp, CSS_PROPERTY_ABSPOS_CB)) {
    5582           0 :     willChangeBitField |= NS_STYLE_WILL_CHANGE_ABSPOS_CB;
    5583             :   }
    5584             : 
    5585           0 :   return willChangeBitField;
    5586             : }
    5587             : 
    5588             : const void*
    5589         671 : nsRuleNode::ComputeDisplayData(void* aStartStruct,
    5590             :                                const nsRuleData* aRuleData,
    5591             :                                GeckoStyleContext* aContext,
    5592             :                                nsRuleNode* aHighestNode,
    5593             :                                const RuleDetail aRuleDetail,
    5594             :                                const RuleNodeCacheConditions aConditions)
    5595             : {
    5596        1342 :   COMPUTE_START_RESET(Display, display, parentDisplay)
    5597             : 
    5598             :   // We may have ended up with aStartStruct's values of mDisplay and
    5599             :   // mFloat, but those may not be correct if our style data overrides
    5600             :   // its position or float properties.  Reset to mOriginalDisplay and
    5601             :   // mOriginalFloat; if it turns out we still need the display/floats
    5602             :   // adjustments, we'll do them below.
    5603         671 :   display->mDisplay = display->mOriginalDisplay;
    5604         671 :   display->mFloat = display->mOriginalFloat;
    5605             : 
    5606             :   // Each property's index in this array must match its index in the
    5607             :   // const array |transitionPropInfo| above.
    5608             :   TransitionPropData transitionPropData[4];
    5609         671 :   TransitionPropData& delay = transitionPropData[0];
    5610         671 :   TransitionPropData& duration = transitionPropData[1];
    5611         671 :   TransitionPropData& property = transitionPropData[2];
    5612         671 :   TransitionPropData& timingFunction = transitionPropData[3];
    5613             : 
    5614             : #define FOR_ALL_TRANSITION_PROPS(var_) \
    5615             :                                       for (uint32_t var_ = 0; var_ < 4; ++var_)
    5616             : 
    5617             :   // CSS Transitions
    5618             :   uint32_t numTransitions =
    5619         671 :     CountTransitionProps(transitionPropInfo, transitionPropData,
    5620             :                          ArrayLength(transitionPropData),
    5621             :                          display, parentDisplay, aRuleData,
    5622         671 :                          conditions);
    5623             : 
    5624         671 :   display->mTransitions.SetLengthNonZero(numTransitions);
    5625             : 
    5626        3355 :   FOR_ALL_TRANSITION_PROPS(p) {
    5627        2684 :     const TransitionPropInfo& i = transitionPropInfo[p];
    5628        2684 :     TransitionPropData& d = transitionPropData[p];
    5629             : 
    5630        2684 :     display->*(i.sdCount) = d.num;
    5631             :   }
    5632             : 
    5633             :   // Fill in the transitions we just allocated with the appropriate values.
    5634        1372 :   for (uint32_t i = 0; i < numTransitions; ++i) {
    5635         701 :     StyleTransition *transition = &display->mTransitions[i];
    5636             : 
    5637         701 :     if (i >= delay.num) {
    5638          21 :       MOZ_ASSERT(delay.num, "delay.num must be greater than 0");
    5639          21 :       transition->SetDelay(display->mTransitions[i % delay.num].GetDelay());
    5640         680 :     } else if (delay.unit == eCSSUnit_Inherit) {
    5641             :       // FIXME (Bug 522599) (for all transition properties): write a test that
    5642             :       // detects when this was wrong for i >= delay.num if parent had
    5643             :       // count for this property not equal to length
    5644           0 :       MOZ_ASSERT(i < parentDisplay->mTransitionDelayCount,
    5645             :                  "delay.num computed incorrectly");
    5646           0 :       MOZ_ASSERT(!conditions.Cacheable(),
    5647             :                  "should have made conditions.Cacheable() false above");
    5648           0 :       transition->SetDelay(parentDisplay->mTransitions[i].GetDelay());
    5649        1360 :     } else if (delay.unit == eCSSUnit_Initial ||
    5650         680 :                delay.unit == eCSSUnit_Unset) {
    5651           0 :       transition->SetDelay(0.0);
    5652         680 :     } else if (delay.list) {
    5653          58 :       switch (delay.list->mValue.GetUnit()) {
    5654             :         case eCSSUnit_Seconds:
    5655          36 :           transition->SetDelay(PR_MSEC_PER_SEC *
    5656          72 :                                delay.list->mValue.GetFloatValue());
    5657          36 :           break;
    5658             :         case eCSSUnit_Milliseconds:
    5659          22 :           transition->SetDelay(delay.list->mValue.GetFloatValue());
    5660          22 :           break;
    5661             :         default:
    5662           0 :           NS_NOTREACHED("Invalid delay unit");
    5663             :       }
    5664             :     }
    5665             : 
    5666         701 :     if (i >= duration.num) {
    5667          21 :       MOZ_ASSERT(duration.num, "duration.num must be greater than 0");
    5668          21 :       transition->SetDuration(
    5669          42 :         display->mTransitions[i % duration.num].GetDuration());
    5670         680 :     } else if (duration.unit == eCSSUnit_Inherit) {
    5671           0 :       MOZ_ASSERT(i < parentDisplay->mTransitionDurationCount,
    5672             :                  "duration.num computed incorrectly");
    5673           0 :       MOZ_ASSERT(!conditions.Cacheable(),
    5674             :                  "should have made conditions.Cacheable() false above");
    5675           0 :       transition->SetDuration(parentDisplay->mTransitions[i].GetDuration());
    5676        1360 :     } else if (duration.unit == eCSSUnit_Initial ||
    5677         680 :                duration.unit == eCSSUnit_Unset) {
    5678           0 :       transition->SetDuration(0.0);
    5679         680 :     } else if (duration.list) {
    5680          69 :       switch (duration.list->mValue.GetUnit()) {
    5681             :         case eCSSUnit_Seconds:
    5682          30 :           transition->SetDuration(PR_MSEC_PER_SEC *
    5683          60 :                                   duration.list->mValue.GetFloatValue());
    5684          30 :           break;
    5685             :         case eCSSUnit_Milliseconds:
    5686          39 :           transition->SetDuration(duration.list->mValue.GetFloatValue());
    5687          39 :           break;
    5688             :         default:
    5689           0 :           NS_NOTREACHED("Invalid duration unit");
    5690             :       }
    5691             :     }
    5692             : 
    5693         701 :     if (i >= property.num) {
    5694           0 :       MOZ_ASSERT(property.num, "property.num must be greater than 0");
    5695           0 :       transition->CopyPropertyFrom(display->mTransitions[i % property.num]);
    5696         701 :     } else if (property.unit == eCSSUnit_Inherit) {
    5697           0 :       MOZ_ASSERT(i < parentDisplay->mTransitionPropertyCount,
    5698             :                  "property.num computed incorrectly");
    5699           0 :       MOZ_ASSERT(!conditions.Cacheable(),
    5700             :                  "should have made conditions.Cacheable() false above");
    5701           0 :       transition->CopyPropertyFrom(parentDisplay->mTransitions[i]);
    5702        1402 :     } else if (property.unit == eCSSUnit_Initial ||
    5703         701 :                property.unit == eCSSUnit_Unset) {
    5704           0 :       transition->SetProperty(eCSSPropertyExtra_all_properties);
    5705         701 :     } else if (property.unit == eCSSUnit_None) {
    5706           3 :       transition->SetProperty(eCSSPropertyExtra_no_properties);
    5707         698 :     } else if (property.list) {
    5708          87 :       const nsCSSValue &val = property.list->mValue;
    5709             : 
    5710          87 :       if (val.GetUnit() == eCSSUnit_Ident) {
    5711             :         nsDependentString
    5712         174 :           propertyStr(property.list->mValue.GetStringBufferValue());
    5713             :         nsCSSPropertyID prop =
    5714             :           nsCSSProps::LookupProperty(propertyStr,
    5715          87 :                                      CSSEnabledState::eForAllContent);
    5716          87 :         if (prop == eCSSProperty_UNKNOWN ||
    5717             :             prop == eCSSPropertyExtra_variable) {
    5718           0 :           transition->SetUnknownProperty(prop, propertyStr);
    5719             :         } else {
    5720          87 :           transition->SetProperty(prop);
    5721             :         }
    5722             :       } else {
    5723           0 :         MOZ_ASSERT(val.GetUnit() == eCSSUnit_All,
    5724             :                    "Invalid transition property unit");
    5725           0 :         transition->SetProperty(eCSSPropertyExtra_all_properties);
    5726             :       }
    5727             :     }
    5728             : 
    5729         701 :     if (i >= timingFunction.num) {
    5730          21 :       MOZ_ASSERT(timingFunction.num,
    5731             :         "timingFunction.num must be greater than 0");
    5732          21 :       transition->SetTimingFunction(
    5733          42 :         display->mTransitions[i % timingFunction.num].GetTimingFunction());
    5734         680 :     } else if (timingFunction.unit == eCSSUnit_Inherit) {
    5735           0 :       MOZ_ASSERT(i < parentDisplay->mTransitionTimingFunctionCount,
    5736             :                  "timingFunction.num computed incorrectly");
    5737           0 :       MOZ_ASSERT(!conditions.Cacheable(),
    5738             :                  "should have made conditions.Cacheable() false above");
    5739           0 :       transition->SetTimingFunction(
    5740           0 :         parentDisplay->mTransitions[i].GetTimingFunction());
    5741        1360 :     } else if (timingFunction.unit == eCSSUnit_Initial ||
    5742         680 :                timingFunction.unit == eCSSUnit_Unset) {
    5743             :       transition->SetTimingFunction(
    5744           0 :         nsTimingFunction(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE));
    5745         680 :     } else if (timingFunction.list) {
    5746          58 :       ComputeTimingFunction(timingFunction.list->mValue,
    5747          58 :                             transition->TimingFunctionSlot());
    5748             :     }
    5749             : 
    5750        3505 :     FOR_ALL_TRANSITION_PROPS(p) {
    5751        2804 :       const TransitionPropInfo& info = transitionPropInfo[p];
    5752        2804 :       TransitionPropData& d = transitionPropData[p];
    5753             : 
    5754             :       // if we're at the end of the list, start at the beginning and repeat
    5755             :       // until we're out of transitions to populate
    5756        2804 :       if (d.list) {
    5757         529 :         d.list = d.list->mNext ? d.list->mNext :
    5758         236 :           aRuleData->ValueFor(info.property)->GetListValue();
    5759             :       }
    5760             :     }
    5761             :   }
    5762             : 
    5763             :   // Each property's index in this array must match its index in the
    5764             :   // const array |animationPropInfo| above.
    5765             :   TransitionPropData animationPropData[8];
    5766         671 :   TransitionPropData& animDelay = animationPropData[0];
    5767         671 :   TransitionPropData& animDuration = animationPropData[1];
    5768         671 :   TransitionPropData& animName = animationPropData[2];
    5769         671 :   TransitionPropData& animTimingFunction = animationPropData[3];
    5770         671 :   TransitionPropData& animDirection = animationPropData[4];
    5771         671 :   TransitionPropData& animFillMode = animationPropData[5];
    5772         671 :   TransitionPropData& animPlayState = animationPropData[6];
    5773         671 :   TransitionPropData& animIterationCount = animationPropData[7];
    5774             : 
    5775             : #define FOR_ALL_ANIMATION_PROPS(var_) \
    5776             :     for (uint32_t var_ = 0; var_ < 8; ++var_)
    5777             : 
    5778             :   // CSS Animations.
    5779             : 
    5780             :   uint32_t numAnimations =
    5781         671 :     CountTransitionProps(animationPropInfo, animationPropData,
    5782             :                          ArrayLength(animationPropData),
    5783             :                          display, parentDisplay, aRuleData,
    5784         671 :                          conditions);
    5785             : 
    5786         671 :   display->mAnimations.SetLengthNonZero(numAnimations);
    5787             : 
    5788        6039 :   FOR_ALL_ANIMATION_PROPS(p) {
    5789        5368 :     const TransitionPropInfo& i = animationPropInfo[p];
    5790        5368 :     TransitionPropData& d = animationPropData[p];
    5791             : 
    5792        5368 :     display->*(i.sdCount) = d.num;
    5793             :   }
    5794             : 
    5795             :   // Fill in the animations we just allocated with the appropriate values.
    5796        1342 :   for (uint32_t i = 0; i < numAnimations; ++i) {
    5797         671 :     StyleAnimation *animation = &display->mAnimations[i];
    5798             : 
    5799         671 :     if (i >= animDelay.num) {
    5800           0 :       MOZ_ASSERT(animDelay.num, "animDelay.num must be greater than 0");
    5801           0 :       animation->SetDelay(display->mAnimations[i % animDelay.num].GetDelay());
    5802         671 :     } else if (animDelay.unit == eCSSUnit_Inherit) {
    5803             :       // FIXME (Bug 522599) (for all animation properties): write a test that
    5804             :       // detects when this was wrong for i >= animDelay.num if parent had
    5805             :       // count for this property not equal to length
    5806           0 :       MOZ_ASSERT(i < parentDisplay->mAnimationDelayCount,
    5807             :                  "animDelay.num computed incorrectly");
    5808           0 :       MOZ_ASSERT(!conditions.Cacheable(),
    5809             :                  "should have made conditions.Cacheable() false above");
    5810           0 :       animation->SetDelay(parentDisplay->mAnimations[i].GetDelay());
    5811        1342 :     } else if (animDelay.unit == eCSSUnit_Initial ||
    5812         671 :                animDelay.unit == eCSSUnit_Unset) {
    5813           0 :       animation->SetDelay(0.0);
    5814         671 :     } else if (animDelay.list) {
    5815           4 :       switch (animDelay.list->mValue.GetUnit()) {
    5816             :         case eCSSUnit_Seconds:
    5817           4 :           animation->SetDelay(PR_MSEC_PER_SEC *
    5818           8 :                               animDelay.list->mValue.GetFloatValue());
    5819           4 :           break;
    5820             :         case eCSSUnit_Milliseconds:
    5821           0 :           animation->SetDelay(animDelay.list->mValue.GetFloatValue());
    5822           0 :           break;
    5823             :         default:
    5824           0 :           NS_NOTREACHED("Invalid delay unit");
    5825             :       }
    5826             :     }
    5827             : 
    5828         671 :     if (i >= animDuration.num) {
    5829           0 :       MOZ_ASSERT(animDuration.num, "animDuration.num must be greater than 0");
    5830           0 :       animation->SetDuration(
    5831           0 :         display->mAnimations[i % animDuration.num].GetDuration());
    5832         671 :     } else if (animDuration.unit == eCSSUnit_Inherit) {
    5833           0 :       MOZ_ASSERT(i < parentDisplay->mAnimationDurationCount,
    5834             :                  "animDuration.num computed incorrectly");
    5835           0 :       MOZ_ASSERT(!conditions.Cacheable(),
    5836             :                  "should have made conditions.Cacheable() false above");
    5837           0 :       animation->SetDuration(parentDisplay->mAnimations[i].GetDuration());
    5838        1342 :     } else if (animDuration.unit == eCSSUnit_Initial ||
    5839         671 :                animDuration.unit == eCSSUnit_Unset) {
    5840           0 :       animation->SetDuration(0.0);
    5841         671 :     } else if (animDuration.list) {
    5842           7 :       switch (animDuration.list->mValue.GetUnit()) {
    5843             :         case eCSSUnit_Seconds:
    5844           4 :           animation->SetDuration(PR_MSEC_PER_SEC *
    5845           8 :                                  animDuration.list->mValue.GetFloatValue());
    5846           4 :           break;
    5847             :         case eCSSUnit_Milliseconds:
    5848           3 :           animation->SetDuration(animDuration.list->mValue.GetFloatValue());
    5849           3 :           break;
    5850             :         default:
    5851           0 :           NS_NOTREACHED("Invalid duration unit");
    5852             :       }
    5853             :     }
    5854             : 
    5855         671 :     if (i >= animName.num) {
    5856           0 :       MOZ_ASSERT(animName.num, "animName.num must be greater than 0");
    5857           0 :       animation->SetName(display->mAnimations[i % animName.num].GetName());
    5858         671 :     } else if (animName.unit == eCSSUnit_Inherit) {
    5859           0 :       MOZ_ASSERT(i < parentDisplay->mAnimationNameCount,
    5860             :                  "animName.num computed incorrectly");
    5861           0 :       MOZ_ASSERT(!conditions.Cacheable(),
    5862             :                  "should have made conditions.Cacheable() false above");
    5863           0 :       animation->SetName(parentDisplay->mAnimations[i].GetName());
    5864        1342 :     } else if (animName.unit == eCSSUnit_Initial ||
    5865         671 :                animName.unit == eCSSUnit_Unset) {
    5866           0 :       animation->SetName(EmptyString());
    5867         671 :     } else if (animName.list) {
    5868           4 :       switch (animName.list->mValue.GetUnit()) {
    5869             :         case eCSSUnit_String:
    5870             :         case eCSSUnit_Ident: {
    5871             :           nsDependentString
    5872           8 :             nameStr(animName.list->mValue.GetStringBufferValue());
    5873           4 :           animation->SetName(nameStr);
    5874           4 :           break;
    5875             :         }
    5876             :         case eCSSUnit_None: {
    5877           0 :           animation->SetName(EmptyString());
    5878           0 :           break;
    5879             :         }
    5880             :         default:
    5881           0 :           MOZ_ASSERT(false, "Invalid animation-name unit");
    5882             :       }
    5883             :     }
    5884             : 
    5885         671 :     if (i >= animTimingFunction.num) {
    5886           0 :       MOZ_ASSERT(animTimingFunction.num,
    5887             :         "animTimingFunction.num must be greater than 0");
    5888           0 :       animation->SetTimingFunction(
    5889           0 :         display->mAnimations[i % animTimingFunction.num].GetTimingFunction());
    5890         671 :     } else if (animTimingFunction.unit == eCSSUnit_Inherit) {
    5891           0 :       MOZ_ASSERT(i < parentDisplay->mAnimationTimingFunctionCount,
    5892             :                  "animTimingFunction.num computed incorrectly");
    5893           0 :       MOZ_ASSERT(!conditions.Cacheable(),
    5894             :                  "should have made conditions.Cacheable() false above");
    5895           0 :       animation->SetTimingFunction(
    5896           0 :         parentDisplay->mAnimations[i].GetTimingFunction());
    5897        1342 :     } else if (animTimingFunction.unit == eCSSUnit_Initial ||
    5898         671 :                animTimingFunction.unit == eCSSUnit_Unset) {
    5899             :       animation->SetTimingFunction(
    5900           0 :         nsTimingFunction(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE));
    5901         671 :     } else if (animTimingFunction.list) {
    5902           7 :       ComputeTimingFunction(animTimingFunction.list->mValue,
    5903           7 :                             animation->TimingFunctionSlot());
    5904             :     }
    5905             : 
    5906         671 :     if (i >= animDirection.num) {
    5907           0 :       MOZ_ASSERT(animDirection.num,
    5908             :         "animDirection.num must be greater than 0");
    5909           0 :       animation->SetDirection(display->mAnimations[i % animDirection.num].GetDirection());
    5910         671 :     } else if (animDirection.unit == eCSSUnit_Inherit) {
    5911           0 :       MOZ_ASSERT(i < parentDisplay->mAnimationDirectionCount,
    5912             :                  "animDirection.num computed incorrectly");
    5913           0 :       MOZ_ASSERT(!conditions.Cacheable(),
    5914             :                  "should have made conditions.Cacheable() false above");
    5915           0 :       animation->SetDirection(parentDisplay->mAnimations[i].GetDirection());
    5916        1342 :     } else if (animDirection.unit == eCSSUnit_Initial ||
    5917         671 :                animDirection.unit == eCSSUnit_Unset) {
    5918           0 :       animation->SetDirection(dom::PlaybackDirection::Normal);
    5919         671 :     } else if (animDirection.list) {
    5920           4 :       MOZ_ASSERT(animDirection.list->mValue.GetUnit() == eCSSUnit_Enumerated,
    5921             :                  "Invalid animation-direction unit");
    5922             : 
    5923           4 :       animation->SetDirection(
    5924           8 :           static_cast<dom::PlaybackDirection>(animDirection.list->mValue.GetIntValue()));
    5925             :     }
    5926             : 
    5927         671 :     if (i >= animFillMode.num) {
    5928           0 :       MOZ_ASSERT(animFillMode.num, "animFillMode.num must be greater than 0");
    5929           0 :       animation->SetFillMode(display->mAnimations[i % animFillMode.num].GetFillMode());
    5930         671 :     } else if (animFillMode.unit == eCSSUnit_Inherit) {
    5931           0 :       MOZ_ASSERT(i < parentDisplay->mAnimationFillModeCount,
    5932             :                  "animFillMode.num computed incorrectly");
    5933           0 :       MOZ_ASSERT(!conditions.Cacheable(),
    5934             :                  "should have made conditions.Cacheable() false above");
    5935           0 :       animation->SetFillMode(parentDisplay->mAnimations[i].GetFillMode());
    5936        1342 :     } else if (animFillMode.unit == eCSSUnit_Initial ||
    5937         671 :                animFillMode.unit == eCSSUnit_Unset) {
    5938           0 :       animation->SetFillMode(dom::FillMode::None);
    5939         671 :     } else if (animFillMode.list) {
    5940           8 :       MOZ_ASSERT(animFillMode.list->mValue.GetUnit() == eCSSUnit_Enumerated,
    5941             :                  "Invalid animation-fill-mode unit");
    5942             : 
    5943           8 :       animation->SetFillMode(
    5944          16 :           static_cast<dom::FillMode>(animFillMode.list->mValue.GetIntValue()));
    5945             :     }
    5946             : 
    5947         671 :     if (i >= animPlayState.num) {
    5948           0 :       MOZ_ASSERT(animPlayState.num,
    5949             :         "animPlayState.num must be greater than 0");
    5950           0 :       animation->SetPlayState(display->mAnimations[i % animPlayState.num].GetPlayState());
    5951         671 :     } else if (animPlayState.unit == eCSSUnit_Inherit) {
    5952           0 :       MOZ_ASSERT(i < parentDisplay->mAnimationPlayStateCount,
    5953             :                  "animPlayState.num computed incorrectly");
    5954           0 :       MOZ_ASSERT(!conditions.Cacheable(),
    5955             :                  "should have made conditions.Cacheable() false above");
    5956           0 :       animation->SetPlayState(parentDisplay->mAnimations[i].GetPlayState());
    5957        1342 :     } else if (animPlayState.unit == eCSSUnit_Initial ||
    5958         671 :                animPlayState.unit == eCSSUnit_Unset) {
    5959           0 :       animation->SetPlayState(NS_STYLE_ANIMATION_PLAY_STATE_RUNNING);
    5960         671 :     } else if (animPlayState.list) {
    5961           4 :       MOZ_ASSERT(animPlayState.list->mValue.GetUnit() == eCSSUnit_Enumerated,
    5962             :                  "Invalid animation-play-state unit");
    5963             : 
    5964           4 :       animation->SetPlayState(animPlayState.list->mValue.GetIntValue());
    5965             :     }
    5966             : 
    5967         671 :     if (i >= animIterationCount.num) {
    5968           0 :       MOZ_ASSERT(animIterationCount.num,
    5969             :         "animIterationCount.num must be greater than 0");
    5970           0 :       animation->SetIterationCount(display->mAnimations[i % animIterationCount.num].GetIterationCount());
    5971         671 :     } else if (animIterationCount.unit == eCSSUnit_Inherit) {
    5972           0 :       MOZ_ASSERT(i < parentDisplay->mAnimationIterationCountCount,
    5973             :                  "animIterationCount.num computed incorrectly");
    5974           0 :       MOZ_ASSERT(!conditions.Cacheable(),
    5975             :                  "should have made conditions.Cacheable() false above");
    5976           0 :       animation->SetIterationCount(parentDisplay->mAnimations[i].GetIterationCount());
    5977        1342 :     } else if (animIterationCount.unit == eCSSUnit_Initial ||
    5978         671 :                animIterationCount.unit == eCSSUnit_Unset) {
    5979           0 :       animation->SetIterationCount(1.0f);
    5980         671 :     } else if (animIterationCount.list) {
    5981           8 :       switch (animIterationCount.list->mValue.GetUnit()) {
    5982             :         case eCSSUnit_Enumerated:
    5983           4 :           MOZ_ASSERT(animIterationCount.list->mValue.GetIntValue() ==
    5984             :                        NS_STYLE_ANIMATION_ITERATION_COUNT_INFINITE,
    5985             :                      "unexpected value");
    5986           4 :           animation->SetIterationCount(NS_IEEEPositiveInfinity());
    5987           4 :           break;
    5988             :         case eCSSUnit_Number:
    5989           4 :           animation->SetIterationCount(
    5990           8 :             animIterationCount.list->mValue.GetFloatValue());
    5991           4 :           break;
    5992             :         default:
    5993           0 :           MOZ_ASSERT(false,
    5994             :                      "unexpected animation-iteration-count unit");
    5995             :       }
    5996             :     }
    5997             : 
    5998        6039 :     FOR_ALL_ANIMATION_PROPS(p) {
    5999        5368 :       const TransitionPropInfo& info = animationPropInfo[p];
    6000        5368 :       TransitionPropData& d = animationPropData[p];
    6001             : 
    6002             :       // if we're at the end of the list, start at the beginning and repeat
    6003             :       // until we're out of animations to populate
    6004        5368 :       if (d.list) {
    6005          92 :         d.list = d.list->mNext ? d.list->mNext :
    6006          46 :           aRuleData->ValueFor(info.property)->GetListValue();
    6007             :       }
    6008             :     }
    6009             :   }
    6010             : 
    6011             :   // display: enum, inherit, initial
    6012         671 :   SetValue(*aRuleData->ValueForDisplay(), display->mDisplay, conditions,
    6013             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    6014         671 :            parentDisplay->mDisplay,
    6015         671 :            StyleDisplay::Inline);
    6016             : 
    6017             :   // contain: none, enum, inherit, initial
    6018         671 :   SetValue(*aRuleData->ValueForContain(), display->mContain, conditions,
    6019             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    6020         671 :            parentDisplay->mContain,
    6021             :            NS_STYLE_CONTAIN_NONE, Unused,
    6022         671 :            NS_STYLE_CONTAIN_NONE, Unused, Unused);
    6023             : 
    6024             :   // scroll-behavior: enum, inherit, initial
    6025         671 :   SetValue(*aRuleData->ValueForScrollBehavior(), display->mScrollBehavior,
    6026             :            conditions,
    6027             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    6028        1342 :            parentDisplay->mScrollBehavior, NS_STYLE_SCROLL_BEHAVIOR_AUTO);
    6029             : 
    6030             :   // scroll-snap-type-x: none, enum, inherit, initial
    6031         671 :   SetValue(*aRuleData->ValueForScrollSnapTypeX(), display->mScrollSnapTypeX,
    6032             :            conditions,
    6033             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    6034        1342 :            parentDisplay->mScrollSnapTypeX, NS_STYLE_SCROLL_SNAP_TYPE_NONE);
    6035             : 
    6036             :   // scroll-snap-type-y: none, enum, inherit, initial
    6037         671 :   SetValue(*aRuleData->ValueForScrollSnapTypeY(), display->mScrollSnapTypeY,
    6038             :            conditions,
    6039             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    6040        1342 :            parentDisplay->mScrollSnapTypeY, NS_STYLE_SCROLL_SNAP_TYPE_NONE);
    6041             : 
    6042             :   // scroll-snap-points-x: none, inherit, initial
    6043         671 :   const nsCSSValue& scrollSnapPointsX = *aRuleData->ValueForScrollSnapPointsX();
    6044         671 :   switch (scrollSnapPointsX.GetUnit()) {
    6045             :     case eCSSUnit_Null:
    6046         671 :       break;
    6047             :     case eCSSUnit_Initial:
    6048             :     case eCSSUnit_Unset:
    6049             :     case eCSSUnit_None:
    6050           0 :       display->mScrollSnapPointsX.SetNoneValue();
    6051           0 :       break;
    6052             :     case eCSSUnit_Inherit:
    6053           0 :       display->mScrollSnapPointsX = parentDisplay->mScrollSnapPointsX;
    6054           0 :       conditions.SetUncacheable();
    6055           0 :       break;
    6056             :     case eCSSUnit_Function: {
    6057           0 :       nsCSSValue::Array* func = scrollSnapPointsX.GetArrayValue();
    6058           0 :       NS_ASSERTION(func->Item(0).GetKeywordValue() == eCSSKeyword_repeat,
    6059             :                    "Expected repeat(), got another function name");
    6060           0 :       nsStyleCoord coord;
    6061           0 :       if (SetCoord(func->Item(1), coord, nsStyleCoord(),
    6062             :                    SETCOORD_LP | SETCOORD_STORE_CALC |
    6063             :                    SETCOORD_CALC_CLAMP_NONNEGATIVE,
    6064           0 :                    aContext, mPresContext, conditions)) {
    6065           0 :         NS_ASSERTION(coord.GetUnit() == eStyleUnit_Coord ||
    6066             :                      coord.GetUnit() == eStyleUnit_Percent ||
    6067             :                      coord.GetUnit() == eStyleUnit_Calc,
    6068             :                      "unexpected unit");
    6069           0 :         display->mScrollSnapPointsX = coord;
    6070             :       }
    6071           0 :       break;
    6072             :     }
    6073             :     default:
    6074           0 :       NS_NOTREACHED("unexpected unit");
    6075             :   }
    6076             : 
    6077             :   // scroll-snap-points-y: none, inherit, initial
    6078         671 :   const nsCSSValue& scrollSnapPointsY = *aRuleData->ValueForScrollSnapPointsY();
    6079         671 :   switch (scrollSnapPointsY.GetUnit()) {
    6080             :     case eCSSUnit_Null:
    6081         671 :       break;
    6082             :     case eCSSUnit_Initial:
    6083             :     case eCSSUnit_Unset:
    6084             :     case eCSSUnit_None:
    6085           0 :       display->mScrollSnapPointsY.SetNoneValue();
    6086           0 :       break;
    6087             :     case eCSSUnit_Inherit:
    6088           0 :       display->mScrollSnapPointsY = parentDisplay->mScrollSnapPointsY;
    6089           0 :       conditions.SetUncacheable();
    6090           0 :       break;
    6091             :     case eCSSUnit_Function: {
    6092           0 :       nsCSSValue::Array* func = scrollSnapPointsY.GetArrayValue();
    6093           0 :       NS_ASSERTION(func->Item(0).GetKeywordValue() == eCSSKeyword_repeat,
    6094             :                    "Expected repeat(), got another function name");
    6095           0 :       nsStyleCoord coord;
    6096           0 :       if (SetCoord(func->Item(1), coord, nsStyleCoord(),
    6097             :                    SETCOORD_LP | SETCOORD_STORE_CALC |
    6098             :                    SETCOORD_CALC_CLAMP_NONNEGATIVE,
    6099           0 :                    aContext, mPresContext, conditions)) {
    6100           0 :         NS_ASSERTION(coord.GetUnit() == eStyleUnit_Coord ||
    6101             :                      coord.GetUnit() == eStyleUnit_Percent ||
    6102             :                      coord.GetUnit() == eStyleUnit_Calc,
    6103             :                      "unexpected unit");
    6104           0 :         display->mScrollSnapPointsY = coord;
    6105             :       }
    6106           0 :       break;
    6107             :     }
    6108             :     default:
    6109           0 :       NS_NOTREACHED("unexpected unit");
    6110             :   }
    6111             : 
    6112             :   // scroll-snap-destination: inherit, initial
    6113         671 :   const nsCSSValue& snapDestination = *aRuleData->ValueForScrollSnapDestination();
    6114         671 :   switch (snapDestination.GetUnit()) {
    6115             :     case eCSSUnit_Null:
    6116         671 :       break;
    6117             :     case eCSSUnit_Initial:
    6118             :     case eCSSUnit_Unset:
    6119           0 :       display->mScrollSnapDestination.SetInitialZeroValues();
    6120           0 :       break;
    6121             :     case eCSSUnit_Inherit:
    6122           0 :       display->mScrollSnapDestination = parentDisplay->mScrollSnapDestination;
    6123           0 :       conditions.SetUncacheable();
    6124           0 :       break;
    6125             :     default: {
    6126           0 :         ComputePositionValue(aContext, snapDestination,
    6127           0 :                              display->mScrollSnapDestination, conditions);
    6128             :       }
    6129             :   }
    6130             : 
    6131             :   // scroll-snap-coordinate: none, inherit, initial
    6132         671 :   const nsCSSValue& snapCoordinate = *aRuleData->ValueForScrollSnapCoordinate();
    6133         671 :   switch (snapCoordinate.GetUnit()) {
    6134             :     case eCSSUnit_Null:
    6135         671 :       break;
    6136             :     case eCSSUnit_Initial:
    6137             :     case eCSSUnit_Unset:
    6138             :     case eCSSUnit_None:
    6139             :       // Unset and Initial is none, indicated by an empty array
    6140           0 :       display->mScrollSnapCoordinate.Clear();
    6141           0 :       break;
    6142             :     case eCSSUnit_Inherit:
    6143           0 :       display->mScrollSnapCoordinate = parentDisplay->mScrollSnapCoordinate;
    6144           0 :       conditions.SetUncacheable();
    6145           0 :       break;
    6146             :     case eCSSUnit_List: {
    6147           0 :       display->mScrollSnapCoordinate.Clear();
    6148           0 :       const nsCSSValueList* item = snapCoordinate.GetListValue();
    6149           0 :       do {
    6150           0 :         NS_ASSERTION(item->mValue.GetUnit() != eCSSUnit_Null &&
    6151             :                      item->mValue.GetUnit() != eCSSUnit_Inherit &&
    6152             :                      item->mValue.GetUnit() != eCSSUnit_Initial &&
    6153             :                      item->mValue.GetUnit() != eCSSUnit_Unset,
    6154             :                      "unexpected unit");
    6155           0 :         Position* pos = display->mScrollSnapCoordinate.AppendElement();
    6156           0 :         ComputePositionValue(aContext, item->mValue, *pos, conditions);
    6157           0 :         item = item->mNext;
    6158           0 :       } while(item);
    6159           0 :       break;
    6160             :     }
    6161             :     default:
    6162           0 :       NS_NOTREACHED("unexpected unit");
    6163             :   }
    6164             : 
    6165             :   // isolation: enum, inherit, initial
    6166         671 :   SetValue(*aRuleData->ValueForIsolation(), display->mIsolation,
    6167             :            conditions,
    6168             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    6169        1342 :            parentDisplay->mIsolation, NS_STYLE_ISOLATION_AUTO);
    6170             : 
    6171             :   // -moz-top-layer: enum, inherit, initial
    6172         671 :   SetValue(*aRuleData->ValueForTopLayer(), display->mTopLayer,
    6173             :            conditions,
    6174             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    6175        1342 :            parentDisplay->mTopLayer, NS_STYLE_TOP_LAYER_NONE);
    6176             : 
    6177             :   // Backup original display value for calculation of a hypothetical
    6178             :   // box (CSS2 10.6.4/10.6.5), in addition to getting our style data right later.
    6179             :   // See ReflowInput::CalculateHypotheticalBox
    6180         671 :   display->mOriginalDisplay = display->mDisplay;
    6181             : 
    6182             :   // appearance: enum, inherit, initial
    6183         671 :   SetValue(*aRuleData->ValueForAppearance(),
    6184             :            display->mAppearance, conditions,
    6185             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    6186         671 :            parentDisplay->mAppearance,
    6187         671 :            NS_THEME_NONE);
    6188             : 
    6189             :   // binding: url, none, inherit
    6190         671 :   const nsCSSValue* bindingValue = aRuleData->ValueForBinding();
    6191         671 :   if (eCSSUnit_URL == bindingValue->GetUnit()) {
    6192         239 :     mozilla::css::URLValue* url = bindingValue->GetURLStructValue();
    6193         239 :     NS_ASSERTION(url, "What's going on here?");
    6194         239 :     display->mBinding.Set(url);
    6195             :   }
    6196        1267 :   else if (eCSSUnit_None == bindingValue->GetUnit() ||
    6197         835 :            eCSSUnit_Initial == bindingValue->GetUnit() ||
    6198         403 :            eCSSUnit_Unset == bindingValue->GetUnit()) {
    6199          29 :     display->mBinding.Set(nullptr);
    6200             :   }
    6201         403 :   else if (eCSSUnit_Inherit == bindingValue->GetUnit()) {
    6202           0 :     conditions.SetUncacheable();
    6203           0 :     display->mBinding.Set(parentDisplay->mBinding);
    6204             :   }
    6205             : 
    6206             :   // position: enum, inherit, initial
    6207         671 :   SetValue(*aRuleData->ValueForPosition(), display->mPosition, conditions,
    6208             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    6209         671 :            parentDisplay->mPosition,
    6210         671 :            NS_STYLE_POSITION_STATIC);
    6211             :   // If an element is put in the top layer, while it is not absolutely
    6212             :   // positioned, the position value should be computed to 'absolute' per
    6213             :   // the Fullscreen API spec.
    6214         676 :   if (display->mTopLayer != NS_STYLE_TOP_LAYER_NONE &&
    6215           5 :       !display->IsAbsolutelyPositionedStyle()) {
    6216           0 :     display->mPosition = NS_STYLE_POSITION_ABSOLUTE;
    6217             :     // We cannot cache this struct because otherwise it may be used as
    6218             :     // an aStartStruct for some other elements.
    6219           0 :     conditions.SetUncacheable();
    6220             :   }
    6221             : 
    6222             :   // clear: enum, inherit, initial
    6223         671 :   SetValue(*aRuleData->ValueForClear(), display->mBreakType, conditions,
    6224             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    6225         671 :            parentDisplay->mBreakType,
    6226         671 :            StyleClear::None);
    6227             : 
    6228             :   // temp fix for bug 24000
    6229             :   // Map 'auto' and 'avoid' to false, and 'always', 'left', and
    6230             :   // 'right' to true.
    6231             :   // "A conforming user agent may interpret the values 'left' and
    6232             :   // 'right' as 'always'." - CSS2.1, section 13.3.1
    6233         671 :   const nsCSSValue* breakBeforeValue = aRuleData->ValueForPageBreakBefore();
    6234         671 :   if (eCSSUnit_Enumerated == breakBeforeValue->GetUnit()) {
    6235           0 :     display->mBreakBefore =
    6236           0 :       (NS_STYLE_PAGE_BREAK_AVOID != breakBeforeValue->GetIntValue() &&
    6237           0 :        NS_STYLE_PAGE_BREAK_AUTO  != breakBeforeValue->GetIntValue());
    6238             :   }
    6239        1342 :   else if (eCSSUnit_Initial == breakBeforeValue->GetUnit() ||
    6240         671 :            eCSSUnit_Unset == breakBeforeValue->GetUnit()) {
    6241           0 :     display->mBreakBefore = false;
    6242             :   }
    6243         671 :   else if (eCSSUnit_Inherit == breakBeforeValue->GetUnit()) {
    6244           0 :     conditions.SetUncacheable();
    6245           0 :     display->mBreakBefore = parentDisplay->mBreakBefore;
    6246             :   }
    6247             : 
    6248         671 :   const nsCSSValue* breakAfterValue = aRuleData->ValueForPageBreakAfter();
    6249         671 :   if (eCSSUnit_Enumerated == breakAfterValue->GetUnit()) {
    6250           0 :     display->mBreakAfter =
    6251           0 :       (NS_STYLE_PAGE_BREAK_AVOID != breakAfterValue->GetIntValue() &&
    6252           0 :        NS_STYLE_PAGE_BREAK_AUTO  != breakAfterValue->GetIntValue());
    6253             :   }
    6254        1342 :   else if (eCSSUnit_Initial == breakAfterValue->GetUnit() ||
    6255         671 :            eCSSUnit_Unset == breakAfterValue->GetUnit()) {
    6256           0 :     display->mBreakAfter = false;
    6257             :   }
    6258         671 :   else if (eCSSUnit_Inherit == breakAfterValue->GetUnit()) {
    6259           0 :     conditions.SetUncacheable();
    6260           0 :     display->mBreakAfter = parentDisplay->mBreakAfter;
    6261             :   }
    6262             :   // end temp fix
    6263             : 
    6264             :   // page-break-inside: enum, inherit, initial
    6265         671 :   SetValue(*aRuleData->ValueForPageBreakInside(),
    6266             :            display->mBreakInside, conditions,
    6267             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    6268         671 :            parentDisplay->mBreakInside,
    6269         671 :            NS_STYLE_PAGE_BREAK_AUTO);
    6270             : 
    6271             :   // touch-action: none, auto, enum, inherit, initial
    6272         671 :   SetValue(*aRuleData->ValueForTouchAction(), display->mTouchAction,
    6273             :            conditions,
    6274             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    6275         671 :            parentDisplay->mTouchAction,
    6276             :            /* initial */ NS_STYLE_TOUCH_ACTION_AUTO,
    6277             :            /* auto */ NS_STYLE_TOUCH_ACTION_AUTO,
    6278         671 :            /* none */ NS_STYLE_TOUCH_ACTION_NONE, Unused, Unused);
    6279             : 
    6280             :   // float: enum, inherit, initial
    6281         671 :   SetValue(*aRuleData->ValueForFloat(),
    6282             :            display->mFloat, conditions,
    6283             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    6284         671 :            parentDisplay->mFloat,
    6285         671 :            StyleFloat::None);
    6286             :   // Save mFloat in mOriginalFloat in case we need it later
    6287         671 :   display->mOriginalFloat = display->mFloat;
    6288             : 
    6289             :   // overflow-x: enum, inherit, initial
    6290         671 :   SetValue(*aRuleData->ValueForOverflowX(),
    6291             :            display->mOverflowX, conditions,
    6292             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    6293         671 :            parentDisplay->mOverflowX,
    6294         671 :            NS_STYLE_OVERFLOW_VISIBLE);
    6295             : 
    6296             :   // overflow-y: enum, inherit, initial
    6297         671 :   SetValue(*aRuleData->ValueForOverflowY(),
    6298             :            display->mOverflowY, conditions,
    6299             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    6300         671 :            parentDisplay->mOverflowY,
    6301         671 :            NS_STYLE_OVERFLOW_VISIBLE);
    6302             : 
    6303             :   // CSS3 overflow-x and overflow-y require some fixup as well in some
    6304             :   // cases.  NS_STYLE_OVERFLOW_VISIBLE and NS_STYLE_OVERFLOW_CLIP are
    6305             :   // meaningful only when used in both dimensions.
    6306         681 :   if (display->mOverflowX != display->mOverflowY &&
    6307          20 :       (display->mOverflowX == NS_STYLE_OVERFLOW_VISIBLE ||
    6308          20 :        display->mOverflowX == NS_STYLE_OVERFLOW_CLIP ||
    6309          20 :        display->mOverflowY == NS_STYLE_OVERFLOW_VISIBLE ||
    6310          10 :        display->mOverflowY == NS_STYLE_OVERFLOW_CLIP)) {
    6311             :     // We can't store in the rule tree since a more specific rule might
    6312             :     // change these conditions.
    6313           0 :     conditions.SetUncacheable();
    6314             : 
    6315             :     // NS_STYLE_OVERFLOW_CLIP is a deprecated value, so if it's specified
    6316             :     // in only one dimension, convert it to NS_STYLE_OVERFLOW_HIDDEN.
    6317           0 :     if (display->mOverflowX == NS_STYLE_OVERFLOW_CLIP)
    6318           0 :       display->mOverflowX = NS_STYLE_OVERFLOW_HIDDEN;
    6319           0 :     if (display->mOverflowY == NS_STYLE_OVERFLOW_CLIP)
    6320           0 :       display->mOverflowY = NS_STYLE_OVERFLOW_HIDDEN;
    6321             : 
    6322             :     // If 'visible' is specified but doesn't match the other dimension, it
    6323             :     // turns into 'auto'.
    6324           0 :     if (display->mOverflowX == NS_STYLE_OVERFLOW_VISIBLE)
    6325           0 :       display->mOverflowX = NS_STYLE_OVERFLOW_AUTO;
    6326           0 :     if (display->mOverflowY == NS_STYLE_OVERFLOW_VISIBLE)
    6327           0 :       display->mOverflowY = NS_STYLE_OVERFLOW_AUTO;
    6328             :   }
    6329             : 
    6330             :   // When 'contain: paint', update overflow from 'visible' to 'clip'.
    6331         671 :   if (display->IsContainPaint()) {
    6332             :     // XXX This actually sets overflow-[x|y] to -moz-hidden-unscrollable.
    6333           0 :     if (display->mOverflowX == NS_STYLE_OVERFLOW_VISIBLE) {
    6334             :       // This uncacheability (and the one below) could be fixed by adding
    6335             :       // mOriginalOverflowX and mOriginalOverflowY fields, if necessary.
    6336           0 :       display->mOverflowX = NS_STYLE_OVERFLOW_CLIP;
    6337           0 :       conditions.SetUncacheable();
    6338             :     }
    6339           0 :     if (display->mOverflowY == NS_STYLE_OVERFLOW_VISIBLE) {
    6340           0 :       display->mOverflowY = NS_STYLE_OVERFLOW_CLIP;
    6341           0 :       conditions.SetUncacheable();
    6342             :     }
    6343             :   }
    6344             : 
    6345         671 :   SetValue(*aRuleData->ValueForOverflowClipBox(), display->mOverflowClipBox,
    6346             :            conditions,
    6347             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    6348         671 :            parentDisplay->mOverflowClipBox,
    6349         671 :            NS_STYLE_OVERFLOW_CLIP_BOX_PADDING_BOX);
    6350             : 
    6351         671 :   SetValue(*aRuleData->ValueForResize(), display->mResize, conditions,
    6352             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    6353         671 :            parentDisplay->mResize,
    6354         671 :            NS_STYLE_RESIZE_NONE);
    6355             : 
    6356         671 :   if (display->mDisplay != StyleDisplay::None) {
    6357             :     // CSS2 9.7 specifies display type corrections dealing with 'float'
    6358             :     // and 'position'.  Since generated content can't be floated or
    6359             :     // positioned, we can deal with it here.
    6360             : 
    6361         484 :     nsIAtom* pseudo = aContext->GetPseudo();
    6362         484 :     if (pseudo && display->mDisplay == StyleDisplay::Contents) {
    6363             :       // We don't want to create frames for anonymous content using a parent
    6364             :       // frame that is for content above the root of the anon tree.
    6365             :       // (XXX what we really should check here is not GetPseudo() but if there's
    6366             :       //  a 'content' property value that implies anon content but we can't
    6367             :       //  check that here since that's a different struct(?))
    6368             :       // We might get display:contents to work for CSS_PSEUDO_ELEMENT_CONTAINS_ELEMENTS
    6369             :       // pseudos (:first-letter etc) in the future, but those have a lot of
    6370             :       // special handling in frame construction so they are also unsupported
    6371             :       // for now.
    6372           0 :       display->mOriginalDisplay = display->mDisplay = StyleDisplay::Inline;
    6373           0 :       conditions.SetUncacheable();
    6374             :     }
    6375             : 
    6376             :     // Inherit a <fieldset> grid/flex display type into its anon content frame.
    6377         484 :     if (pseudo == nsCSSAnonBoxes::fieldsetContent) {
    6378           0 :       MOZ_ASSERT(display->mDisplay == StyleDisplay::Block,
    6379             :                  "forms.css should have set 'display:block'");
    6380           0 :       switch (parentDisplay->mDisplay) {
    6381             :         case StyleDisplay::Grid:
    6382             :         case StyleDisplay::InlineGrid:
    6383           0 :           display->mDisplay = StyleDisplay::Grid;
    6384           0 :           conditions.SetUncacheable();
    6385           0 :           break;
    6386             :         case StyleDisplay::Flex:
    6387             :         case StyleDisplay::InlineFlex:
    6388           0 :           display->mDisplay = StyleDisplay::Flex;
    6389           0 :           conditions.SetUncacheable();
    6390           0 :           break;
    6391             :         default:
    6392           0 :           break; // Do nothing
    6393             :       }
    6394             :     }
    6395             : 
    6396         484 :     if (nsCSSPseudoElements::firstLetter == pseudo) {
    6397             :       // a non-floating first-letter must be inline
    6398             :       // XXX this fix can go away once bug 103189 is fixed correctly
    6399             :       // Note that we reset mOriginalDisplay to enforce the invariant that it equals mDisplay if we're not positioned or floating.
    6400           0 :       display->mOriginalDisplay = display->mDisplay = StyleDisplay::Inline;
    6401             : 
    6402             :       // We can't cache the data in the rule tree since if a more specific
    6403             :       // rule has 'float: left' we'll end up with the wrong 'display'
    6404             :       // property.
    6405           0 :       conditions.SetUncacheable();
    6406             :     }
    6407             : 
    6408         484 :     if (display->IsAbsolutelyPositionedStyle()) {
    6409             :       // 1) if position is 'absolute' or 'fixed' then display must be
    6410             :       // block-level and float must be 'none'
    6411           8 :       EnsureBlockDisplay(display->mDisplay);
    6412           8 :       display->mFloat = StyleFloat::None;
    6413             : 
    6414             :       // Note that it's OK to cache this struct in the ruletree
    6415             :       // because it's fine as-is for any style context that points to
    6416             :       // it directly, and any use of it as aStartStruct (e.g. if a
    6417             :       // more specific rule sets "position: static") will use
    6418             :       // mOriginalDisplay and mOriginalFloat, which we have carefully
    6419             :       // not changed.
    6420         476 :     } else if (display->mFloat != StyleFloat::None) {
    6421             :       // 2) if float is not none, and display is not none, then we must
    6422             :       // set a block-level 'display' type per CSS2.1 section 9.7.
    6423           0 :       EnsureBlockDisplay(display->mDisplay);
    6424             : 
    6425             :       // Note that it's OK to cache this struct in the ruletree
    6426             :       // because it's fine as-is for any style context that points to
    6427             :       // it directly, and any use of it as aStartStruct (e.g. if a
    6428             :       // more specific rule sets "float: none") will use
    6429             :       // mOriginalDisplay, which we have carefully not changed.
    6430             :     }
    6431             : 
    6432         484 :     if (display->IsContainPaint()) {
    6433             :       // An element with contain:paint or contain:layout needs to "be a
    6434             :       // formatting context". For the purposes of the "display" property, that
    6435             :       // just means we need to promote "display:inline" to "inline-block".
    6436             :       // XXX We may also need to promote ruby display vals; see bug 1179349.
    6437             : 
    6438             :       // It's okay to cache this change in the rule tree for the same
    6439             :       // reasons as floats in the previous condition.
    6440           0 :       if (display->mDisplay == StyleDisplay::Inline) {
    6441           0 :         display->mDisplay = StyleDisplay::InlineBlock;
    6442             :       }
    6443             :     }
    6444             :   }
    6445             : 
    6446         671 :   SetTransformValue(*aRuleData->ValueForTransform(),
    6447             :                     display->mSpecifiedTransform, conditions,
    6448         671 :                     parentDisplay->mSpecifiedTransform);
    6449             : 
    6450             :   /* Convert the nsCSSValueList into a will-change bitfield for fast lookup */
    6451         671 :   const nsCSSValue* willChangeValue = aRuleData->ValueForWillChange();
    6452         671 :   switch (willChangeValue->GetUnit()) {
    6453             :   case eCSSUnit_Null:
    6454         671 :     break;
    6455             : 
    6456             :   case eCSSUnit_List:
    6457             :   case eCSSUnit_ListDep: {
    6458           0 :     display->mWillChange.Clear();
    6459           0 :     display->mWillChangeBitField = 0;
    6460           0 :     for (const nsCSSValueList* item = willChangeValue->GetListValue();
    6461           0 :          item; item = item->mNext)
    6462             :     {
    6463           0 :       nsIAtom* atom = item->mValue.GetAtomValue();
    6464           0 :       display->mWillChange.AppendElement(atom);
    6465           0 :       if (atom == nsGkAtoms::transform) {
    6466           0 :         display->mWillChangeBitField |= NS_STYLE_WILL_CHANGE_TRANSFORM;
    6467           0 :       } else if (atom == nsGkAtoms::opacity) {
    6468           0 :         display->mWillChangeBitField |= NS_STYLE_WILL_CHANGE_OPACITY;
    6469           0 :       } else if (atom == nsGkAtoms::scrollPosition) {
    6470           0 :         display->mWillChangeBitField |= NS_STYLE_WILL_CHANGE_SCROLL;
    6471             :       }
    6472             : 
    6473           0 :       nsDependentAtomString buffer(atom);
    6474             :       nsCSSPropertyID prop =
    6475           0 :         nsCSSProps::LookupProperty(buffer, CSSEnabledState::eForAllContent);
    6476           0 :       if (prop != eCSSProperty_UNKNOWN &&
    6477           0 :           prop != eCSSPropertyExtra_variable) {
    6478             :         // If the property given is a shorthand, it indicates the expectation
    6479             :         // for all the longhands the shorthand expands to.
    6480           0 :         if (nsCSSProps::IsShorthand(prop)) {
    6481           0 :           for (const nsCSSPropertyID* shorthands =
    6482           0 :                   nsCSSProps::SubpropertyEntryFor(prop);
    6483           0 :                 *shorthands != eCSSProperty_UNKNOWN; ++shorthands) {
    6484           0 :             display->mWillChangeBitField |= GetWillChangeBitFieldFromPropFlags(*shorthands);
    6485             :           }
    6486             :         } else {
    6487           0 :           display->mWillChangeBitField |= GetWillChangeBitFieldFromPropFlags(prop);
    6488             :         }
    6489             :       }
    6490             :     }
    6491           0 :     break;
    6492             :   }
    6493             : 
    6494             :   case eCSSUnit_Inherit:
    6495           0 :     display->mWillChange.Clear();
    6496           0 :     display->mWillChange.AppendElements(parentDisplay->mWillChange);
    6497           0 :     display->mWillChangeBitField = parentDisplay->mWillChangeBitField;
    6498           0 :     conditions.SetUncacheable();
    6499           0 :     break;
    6500             : 
    6501             :   case eCSSUnit_Initial:
    6502             :   case eCSSUnit_Unset:
    6503             :   case eCSSUnit_Auto:
    6504           0 :     display->mWillChange.Clear();
    6505           0 :     display->mWillChangeBitField = 0;
    6506           0 :     break;
    6507             : 
    6508             :   default:
    6509           0 :     MOZ_ASSERT(false, "unrecognized will-change unit");
    6510             :   }
    6511             : 
    6512             :   // vertical-align: enum, length, percent, calc, inherit
    6513         671 :   const nsCSSValue* verticalAlignValue = aRuleData->ValueForVerticalAlign();
    6514         671 :   if (!SetCoord(*verticalAlignValue, display->mVerticalAlign,
    6515             :                 parentDisplay->mVerticalAlign,
    6516             :                 SETCOORD_LPH | SETCOORD_ENUMERATED | SETCOORD_STORE_CALC,
    6517         671 :                 aContext, mPresContext, conditions)) {
    6518        1338 :     if (eCSSUnit_Initial == verticalAlignValue->GetUnit() ||
    6519         669 :         eCSSUnit_Unset == verticalAlignValue->GetUnit()) {
    6520           0 :       display->mVerticalAlign.SetIntValue(NS_STYLE_VERTICAL_ALIGN_BASELINE,
    6521           0 :                                           eStyleUnit_Enumerated);
    6522             :     }
    6523             :   }
    6524             : 
    6525             :   /* Convert -moz-transform-origin. */
    6526             :   const nsCSSValue* transformOriginValue =
    6527         671 :     aRuleData->ValueForTransformOrigin();
    6528         671 :   if (transformOriginValue->GetUnit() != eCSSUnit_Null) {
    6529             :     const nsCSSValue& valX =
    6530          30 :       transformOriginValue->GetUnit() == eCSSUnit_Triplet ?
    6531          30 :         transformOriginValue->GetTripletValue().mXValue : *transformOriginValue;
    6532             :     const nsCSSValue& valY =
    6533          30 :       transformOriginValue->GetUnit() == eCSSUnit_Triplet ?
    6534          30 :         transformOriginValue->GetTripletValue().mYValue : *transformOriginValue;
    6535             :     const nsCSSValue& valZ =
    6536          30 :       transformOriginValue->GetUnit() == eCSSUnit_Triplet ?
    6537          30 :         transformOriginValue->GetTripletValue().mZValue : *transformOriginValue;
    6538             : 
    6539             :     mozilla::DebugOnly<bool> cX =
    6540          60 :        SetCoord(valX, display->mTransformOrigin[0],
    6541             :                 parentDisplay->mTransformOrigin[0],
    6542             :                 SETCOORD_LPH | SETCOORD_INITIAL_HALF |
    6543             :                   SETCOORD_BOX_POSITION | SETCOORD_STORE_CALC |
    6544             :                   SETCOORD_UNSET_INITIAL,
    6545          90 :                 aContext, mPresContext, conditions);
    6546             : 
    6547             :      mozilla::DebugOnly<bool> cY =
    6548          60 :        SetCoord(valY, display->mTransformOrigin[1],
    6549             :                 parentDisplay->mTransformOrigin[1],
    6550             :                 SETCOORD_LPH | SETCOORD_INITIAL_HALF |
    6551             :                   SETCOORD_BOX_POSITION | SETCOORD_STORE_CALC |
    6552             :                   SETCOORD_UNSET_INITIAL,
    6553          90 :                 aContext, mPresContext, conditions);
    6554             : 
    6555          30 :      if (valZ.GetUnit() == eCSSUnit_Null) {
    6556             :        // Null for the z component means a 0 translation, not
    6557             :        // unspecified, as we have already checked the triplet
    6558             :        // value for Null.
    6559           0 :        display->mTransformOrigin[2].SetCoordValue(0);
    6560             :      } else {
    6561             :        mozilla::DebugOnly<bool> cZ =
    6562          60 :          SetCoord(valZ, display->mTransformOrigin[2],
    6563             :                   parentDisplay->mTransformOrigin[2],
    6564             :                   SETCOORD_LH | SETCOORD_INITIAL_ZERO | SETCOORD_STORE_CALC |
    6565             :                     SETCOORD_UNSET_INITIAL,
    6566          90 :                   aContext, mPresContext, conditions);
    6567          30 :        MOZ_ASSERT(cY == cZ, "changed one but not the other");
    6568             :      }
    6569          30 :      MOZ_ASSERT(cX == cY, "changed one but not the other");
    6570          30 :      NS_ASSERTION(cX, "Malformed -moz-transform-origin parse!");
    6571             :   }
    6572             : 
    6573             :   const nsCSSValue* perspectiveOriginValue =
    6574         671 :     aRuleData->ValueForPerspectiveOrigin();
    6575         671 :   if (perspectiveOriginValue->GetUnit() != eCSSUnit_Null) {
    6576             :     mozilla::DebugOnly<bool> result =
    6577           0 :       SetPairCoords(*perspectiveOriginValue,
    6578             :                     display->mPerspectiveOrigin[0],
    6579             :                     display->mPerspectiveOrigin[1],
    6580             :                     parentDisplay->mPerspectiveOrigin[0],
    6581             :                     parentDisplay->mPerspectiveOrigin[1],
    6582             :                     SETCOORD_LPH | SETCOORD_INITIAL_HALF |
    6583             :                       SETCOORD_BOX_POSITION | SETCOORD_STORE_CALC |
    6584             :                       SETCOORD_UNSET_INITIAL,
    6585           0 :                     aContext, mPresContext, conditions);
    6586           0 :     NS_ASSERTION(result, "Malformed -moz-perspective-origin parse!");
    6587             :   }
    6588             : 
    6589         671 :   SetCoord(*aRuleData->ValueForPerspective(),
    6590             :            display->mChildPerspective, parentDisplay->mChildPerspective,
    6591             :            SETCOORD_LAH | SETCOORD_INITIAL_NONE | SETCOORD_NONE |
    6592             :              SETCOORD_UNSET_INITIAL,
    6593        1342 :            aContext, mPresContext, conditions);
    6594             : 
    6595         671 :   SetValue(*aRuleData->ValueForBackfaceVisibility(),
    6596             :            display->mBackfaceVisibility, conditions,
    6597             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    6598         671 :            parentDisplay->mBackfaceVisibility,
    6599         671 :            NS_STYLE_BACKFACE_VISIBILITY_VISIBLE);
    6600             : 
    6601             :   // transform-style: enum, inherit, initial
    6602         671 :   SetValue(*aRuleData->ValueForTransformStyle(),
    6603             :            display->mTransformStyle, conditions,
    6604             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    6605         671 :            parentDisplay->mTransformStyle,
    6606         671 :            NS_STYLE_TRANSFORM_STYLE_FLAT);
    6607             : 
    6608             :   // transform-box: enum, inherit, initial
    6609         671 :   SetValue(*aRuleData->ValueForTransformBox(),
    6610             :            display->mTransformBox, conditions,
    6611             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    6612         671 :            parentDisplay->mTransformBox,
    6613         671 :            StyleGeometryBox::BorderBox);
    6614             : 
    6615             :   // orient: enum, inherit, initial
    6616         671 :   SetValue(*aRuleData->ValueForOrient(),
    6617             :            display->mOrient, conditions,
    6618             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    6619         671 :            parentDisplay->mOrient,
    6620         671 :            StyleOrient::Inline);
    6621             : 
    6622             :   // shape-outside: none | [ <basic-shape> || <shape-box> ] | <image>
    6623         671 :   const nsCSSValue* shapeOutsideValue = aRuleData->ValueForShapeOutside();
    6624         671 :   switch (shapeOutsideValue->GetUnit()) {
    6625             :     case eCSSUnit_Null:
    6626         671 :       break;
    6627             :     case eCSSUnit_None:
    6628             :     case eCSSUnit_Initial:
    6629             :     case eCSSUnit_Unset:
    6630           0 :       display->mShapeOutside = StyleShapeSource();
    6631           0 :       break;
    6632             :     case eCSSUnit_Inherit:
    6633           0 :       conditions.SetUncacheable();
    6634           0 :       display->mShapeOutside = parentDisplay->mShapeOutside;
    6635           0 :       break;
    6636             :     case eCSSUnit_URL: {
    6637           0 :       display->mShapeOutside = StyleShapeSource();
    6638           0 :       display->mShapeOutside.SetURL(shapeOutsideValue->GetURLStructValue());
    6639           0 :       break;
    6640             :     }
    6641             :     case eCSSUnit_Array: {
    6642           0 :       display->mShapeOutside = StyleShapeSource();
    6643           0 :       SetStyleShapeSourceToCSSValue(&display->mShapeOutside, shapeOutsideValue,
    6644           0 :                                     aContext, mPresContext, conditions);
    6645           0 :       break;
    6646             :     }
    6647             :     default:
    6648           0 :       MOZ_ASSERT_UNREACHABLE("Unrecognized shape-outside unit!");
    6649             :   }
    6650             : 
    6651        1342 :   COMPUTE_END_RESET(Display, display)
    6652             : }
    6653             : 
    6654             : const void*
    6655         142 : nsRuleNode::ComputeVisibilityData(void* aStartStruct,
    6656             :                                   const nsRuleData* aRuleData,
    6657             :                                   GeckoStyleContext* aContext,
    6658             :                                   nsRuleNode* aHighestNode,
    6659             :                                   const RuleDetail aRuleDetail,
    6660             :                                   const RuleNodeCacheConditions aConditions)
    6661             : {
    6662         284 :   COMPUTE_START_INHERITED(Visibility, visibility, parentVisibility)
    6663             : 
    6664             :   // IMPORTANT: No properties in this struct have lengths in them.  We
    6665             :   // depend on this since CalcLengthWith can call StyleVisibility()
    6666             :   // to get the language for resolving fonts!
    6667             : 
    6668             :   // direction: enum, inherit, initial
    6669         284 :   SetValue(*aRuleData->ValueForDirection(), visibility->mDirection,
    6670             :            conditions,
    6671             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    6672         142 :            parentVisibility->mDirection,
    6673         142 :            (GET_BIDI_OPTION_DIRECTION(mPresContext->GetBidi())
    6674             :             == IBMBIDI_TEXTDIRECTION_RTL)
    6675         142 :             ? NS_STYLE_DIRECTION_RTL : NS_STYLE_DIRECTION_LTR);
    6676             : 
    6677             :   // visibility: enum, inherit, initial
    6678         142 :   SetValue(*aRuleData->ValueForVisibility(), visibility->mVisible,
    6679             :            conditions,
    6680             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    6681         142 :            parentVisibility->mVisible,
    6682         142 :            NS_STYLE_VISIBILITY_VISIBLE);
    6683             : 
    6684             :   // image-rendering: enum, inherit
    6685         142 :   SetValue(*aRuleData->ValueForImageRendering(),
    6686             :            visibility->mImageRendering, conditions,
    6687             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    6688         142 :            parentVisibility->mImageRendering,
    6689         142 :            NS_STYLE_IMAGE_RENDERING_AUTO);
    6690             : 
    6691             :   // writing-mode: enum, inherit, initial
    6692         142 :   SetValue(*aRuleData->ValueForWritingMode(), visibility->mWritingMode,
    6693             :            conditions,
    6694             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    6695         142 :            parentVisibility->mWritingMode,
    6696         142 :            NS_STYLE_WRITING_MODE_HORIZONTAL_TB);
    6697             : 
    6698             :   // text-orientation: enum, inherit, initial
    6699         142 :   SetValue(*aRuleData->ValueForTextOrientation(), visibility->mTextOrientation,
    6700             :            conditions,
    6701             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    6702         142 :            parentVisibility->mTextOrientation,
    6703         142 :            NS_STYLE_TEXT_ORIENTATION_MIXED);
    6704             : 
    6705             :   // image-orientation: enum, inherit, initial
    6706         142 :   const nsCSSValue* orientation = aRuleData->ValueForImageOrientation();
    6707         284 :   if (orientation->GetUnit() == eCSSUnit_Inherit ||
    6708         142 :       orientation->GetUnit() == eCSSUnit_Unset) {
    6709           0 :     conditions.SetUncacheable();
    6710           0 :     visibility->mImageOrientation = parentVisibility->mImageOrientation;
    6711         142 :   } else if (orientation->GetUnit() == eCSSUnit_Initial) {
    6712           0 :     visibility->mImageOrientation = nsStyleImageOrientation();
    6713         142 :   } else if (orientation->IsAngularUnit()) {
    6714           0 :     double angle = orientation->GetAngleValueInRadians();
    6715             :     visibility->mImageOrientation =
    6716           0 :       nsStyleImageOrientation::CreateAsAngleAndFlip(angle, false);
    6717         142 :   } else if (orientation->GetUnit() == eCSSUnit_Array) {
    6718           0 :     const nsCSSValue::Array* array = orientation->GetArrayValue();
    6719           0 :     MOZ_ASSERT(array->Item(0).IsAngularUnit(),
    6720             :                "First image-orientation value is not an angle");
    6721           0 :     MOZ_ASSERT(array->Item(1).GetUnit() == eCSSUnit_Enumerated &&
    6722             :                array->Item(1).GetIntValue() == NS_STYLE_IMAGE_ORIENTATION_FLIP,
    6723             :                "Second image-orientation value is not 'flip'");
    6724           0 :     double angle = array->Item(0).GetAngleValueInRadians();
    6725             :     visibility->mImageOrientation =
    6726           0 :       nsStyleImageOrientation::CreateAsAngleAndFlip(angle, true);
    6727             : 
    6728         142 :   } else if (orientation->GetUnit() == eCSSUnit_Enumerated) {
    6729           0 :     switch (orientation->GetIntValue()) {
    6730             :       case NS_STYLE_IMAGE_ORIENTATION_FLIP:
    6731           0 :         visibility->mImageOrientation = nsStyleImageOrientation::CreateAsFlip();
    6732           0 :         break;
    6733             :       case NS_STYLE_IMAGE_ORIENTATION_FROM_IMAGE:
    6734           0 :         visibility->mImageOrientation = nsStyleImageOrientation::CreateAsFromImage();
    6735           0 :         break;
    6736             :       default:
    6737           0 :         NS_NOTREACHED("Invalid image-orientation enumerated value");
    6738             :     }
    6739             :   } else {
    6740         142 :     MOZ_ASSERT(orientation->GetUnit() == eCSSUnit_Null, "Should be null unit");
    6741             :   }
    6742             : 
    6743         142 :   SetValue(*aRuleData->ValueForColorAdjust(), visibility->mColorAdjust,
    6744             :            conditions,
    6745             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    6746         142 :            parentVisibility->mColorAdjust,
    6747         142 :            NS_STYLE_COLOR_ADJUST_ECONOMY);
    6748             : 
    6749         284 :   COMPUTE_END_INHERITED(Visibility, visibility)
    6750             : }
    6751             : 
    6752             : const void*
    6753          10 : nsRuleNode::ComputeColorData(void* aStartStruct,
    6754             :                              const nsRuleData* aRuleData,
    6755             :                              GeckoStyleContext* aContext,
    6756             :                              nsRuleNode* aHighestNode,
    6757             :                              const RuleDetail aRuleDetail,
    6758             :                              const RuleNodeCacheConditions aConditions)
    6759             : {
    6760          20 :   COMPUTE_START_INHERITED(Color, color, parentColor)
    6761             : 
    6762             :   // color: color, string, inherit
    6763             :   // Special case for currentColor.  According to CSS3, setting color to 'currentColor'
    6764             :   // should behave as if it is inherited
    6765          10 :   const nsCSSValue* colorValue = aRuleData->ValueForColor();
    6766          30 :   if ((colorValue->GetUnit() == eCSSUnit_EnumColor &&
    6767          20 :        colorValue->GetIntValue() == NS_COLOR_CURRENTCOLOR) ||
    6768          10 :       colorValue->GetUnit() == eCSSUnit_Unset) {
    6769           0 :     color->mColor = parentColor->mColor;
    6770           0 :     conditions.SetUncacheable();
    6771             :   }
    6772          10 :   else if (colorValue->GetUnit() == eCSSUnit_Initial) {
    6773           0 :     color->mColor = mPresContext->DefaultColor();
    6774             :   }
    6775             :   else {
    6776          10 :     SetColor(*colorValue, parentColor->mColor, mPresContext, aContext,
    6777          10 :              color->mColor, conditions);
    6778             :   }
    6779             : 
    6780          20 :   COMPUTE_END_INHERITED(Color, color)
    6781             : }
    6782             : 
    6783             : // information about how to compute values for background-* properties
    6784             : template <class SpecifiedValueItem, class ComputedValueItem>
    6785             : struct BackgroundItemComputer {
    6786             : };
    6787             : 
    6788             : template <>
    6789             : struct BackgroundItemComputer<nsCSSValueList, uint8_t>
    6790             : {
    6791           6 :   static void ComputeValue(GeckoStyleContext* aStyleContext,
    6792             :                            const nsCSSValueList* aSpecifiedValue,
    6793             :                            uint8_t& aComputedValue,
    6794             :                            RuleNodeCacheConditions& aConditions)
    6795             :   {
    6796           6 :     SetValue(aSpecifiedValue->mValue, aComputedValue, aConditions,
    6797           6 :              SETVAL_ENUMERATED, uint8_t(0), 0);
    6798           6 :   }
    6799             : };
    6800             : 
    6801             : template <>
    6802             : struct BackgroundItemComputer<nsCSSValuePairList, nsStyleImageLayers::Repeat>
    6803             : {
    6804          18 :   static void ComputeValue(GeckoStyleContext* aStyleContext,
    6805             :                            const nsCSSValuePairList* aSpecifiedValue,
    6806             :                            nsStyleImageLayers::Repeat& aComputedValue,
    6807             :                            RuleNodeCacheConditions& aConditions)
    6808             :   {
    6809          18 :     NS_ASSERTION(aSpecifiedValue->mXValue.GetUnit() == eCSSUnit_Enumerated &&
    6810             :                  (aSpecifiedValue->mYValue.GetUnit() == eCSSUnit_Enumerated ||
    6811             :                   aSpecifiedValue->mYValue.GetUnit() == eCSSUnit_Null),
    6812             :                  "Invalid unit");
    6813             : 
    6814          18 :     bool hasContraction = true;
    6815             :     StyleImageLayerRepeat value =
    6816          18 :       static_cast<StyleImageLayerRepeat>(aSpecifiedValue->mXValue.GetIntValue());
    6817          18 :     switch (value) {
    6818             :       case StyleImageLayerRepeat::RepeatX:
    6819           5 :       aComputedValue.mXRepeat = StyleImageLayerRepeat::Repeat;
    6820           5 :       aComputedValue.mYRepeat = StyleImageLayerRepeat::NoRepeat;
    6821           5 :       break;
    6822             :       case StyleImageLayerRepeat::RepeatY:
    6823           0 :       aComputedValue.mXRepeat = StyleImageLayerRepeat::NoRepeat;
    6824           0 :       aComputedValue.mYRepeat = StyleImageLayerRepeat::Repeat;
    6825           0 :       break;
    6826             :     default:
    6827          13 :       NS_ASSERTION(value == StyleImageLayerRepeat::NoRepeat ||
    6828             :                    value == StyleImageLayerRepeat::Repeat ||
    6829             :                    value == StyleImageLayerRepeat::Space ||
    6830             :                    value == StyleImageLayerRepeat::Round, "Unexpected value");
    6831          13 :       aComputedValue.mXRepeat = value;
    6832          13 :       hasContraction = false;
    6833          13 :       break;
    6834             :     }
    6835             : 
    6836          18 :     if (hasContraction) {
    6837           5 :       NS_ASSERTION(aSpecifiedValue->mYValue.GetUnit() == eCSSUnit_Null,
    6838             :                    "Invalid unit.");
    6839           5 :       return;
    6840             :     }
    6841             : 
    6842          13 :     switch (aSpecifiedValue->mYValue.GetUnit()) {
    6843             :     case eCSSUnit_Null:
    6844          13 :       aComputedValue.mYRepeat = aComputedValue.mXRepeat;
    6845          13 :       break;
    6846             :     case eCSSUnit_Enumerated:
    6847           0 :       value =
    6848           0 :         static_cast<StyleImageLayerRepeat>(aSpecifiedValue->mYValue.GetIntValue());
    6849           0 :       NS_ASSERTION(value == StyleImageLayerRepeat::NoRepeat ||
    6850             :                    value == StyleImageLayerRepeat::Repeat ||
    6851             :                    value == StyleImageLayerRepeat::Space ||
    6852             :                    value == StyleImageLayerRepeat::Round, "Unexpected value");
    6853           0 :       aComputedValue.mYRepeat = value;
    6854           0 :       break;
    6855             :     default:
    6856           0 :       NS_NOTREACHED("Unexpected CSS value");
    6857           0 :       break;
    6858             :     }
    6859             :   }
    6860             : };
    6861             : 
    6862             : template <>
    6863             : struct BackgroundItemComputer<nsCSSValueList, nsStyleImage>
    6864             : {
    6865          47 :   static void ComputeValue(GeckoStyleContext* aStyleContext,
    6866             :                            const nsCSSValueList* aSpecifiedValue,
    6867             :                            nsStyleImage& aComputedValue,
    6868             :                            RuleNodeCacheConditions& aConditions)
    6869             :   {
    6870          47 :     SetStyleImage(aStyleContext, aSpecifiedValue->mValue, aComputedValue,
    6871          47 :                   aConditions);
    6872          47 :   }
    6873             : };
    6874             : 
    6875             : template <typename T>
    6876             : struct BackgroundItemComputer<nsCSSValueList, T>
    6877             : {
    6878             :   typedef typename EnableIf<IsEnum<T>::value, T>::Type ComputedType;
    6879             : 
    6880          39 :   static void ComputeValue(GeckoStyleContext* aStyleContext,
    6881             :                            const nsCSSValueList* aSpecifiedValue,
    6882             :                            ComputedType& aComputedValue,
    6883             :                            RuleNodeCacheConditions& aConditions)
    6884             :   {
    6885          39 :     aComputedValue =
    6886          39 :       static_cast<T>(aSpecifiedValue->mValue.GetIntValue());
    6887          39 :   }
    6888             : };
    6889             : 
    6890             : /* Helper function for ComputePositionValue.
    6891             :  * This function computes a single PositionCoord from two nsCSSValue objects,
    6892             :  * which represent an edge and an offset from that edge.
    6893             :  */
    6894             : static void
    6895          26 : ComputePositionCoord(GeckoStyleContext* aStyleContext,
    6896             :                      const nsCSSValue& aEdge,
    6897             :                      const nsCSSValue& aOffset,
    6898             :                      Position::Coord* aResult,
    6899             :                      RuleNodeCacheConditions& aConditions)
    6900             : {
    6901          26 :   if (eCSSUnit_Percent == aOffset.GetUnit()) {
    6902          10 :     aResult->mLength = 0;
    6903          10 :     aResult->mPercent = aOffset.GetPercentValue();
    6904          10 :     aResult->mHasPercent = true;
    6905          16 :   } else if (aOffset.IsLengthUnit()) {
    6906           0 :     aResult->mLength = CalcLength(aOffset, aStyleContext,
    6907             :                                   aStyleContext->PresContext(),
    6908             :                                   aConditions);
    6909           0 :     aResult->mPercent = 0.0f;
    6910           0 :     aResult->mHasPercent = false;
    6911          16 :   } else if (aOffset.IsCalcUnit()) {
    6912             :     LengthPercentPairCalcOps ops(aStyleContext,
    6913             :                                  aStyleContext->PresContext(),
    6914           0 :                                  aConditions);
    6915           0 :     nsRuleNode::ComputedCalc vals = ComputeCalc(aOffset, ops);
    6916           0 :     aResult->mLength = vals.mLength;
    6917           0 :     aResult->mPercent = vals.mPercent;
    6918           0 :     aResult->mHasPercent = ops.mHasPercent;
    6919             :   } else {
    6920          16 :     aResult->mLength = 0;
    6921          16 :     aResult->mPercent = 0.0f;
    6922          16 :     aResult->mHasPercent = false;
    6923          16 :     NS_ASSERTION(aOffset.GetUnit() == eCSSUnit_Null, "unexpected unit");
    6924             :   }
    6925             : 
    6926          26 :   if (eCSSUnit_Enumerated == aEdge.GetUnit()) {
    6927             :     int sign;
    6928          16 :     if (aEdge.GetIntValue() & (NS_STYLE_IMAGELAYER_POSITION_BOTTOM |
    6929             :                                NS_STYLE_IMAGELAYER_POSITION_RIGHT)) {
    6930           2 :       sign = -1;
    6931             :     } else {
    6932          14 :       sign = 1;
    6933             :     }
    6934          32 :     aResult->mPercent = GetFloatFromBoxPosition(aEdge.GetIntValue()) +
    6935          16 :                         sign * aResult->mPercent;
    6936          16 :     aResult->mLength = sign * aResult->mLength;
    6937          16 :     aResult->mHasPercent = true;
    6938             :   } else {
    6939          10 :     NS_ASSERTION(eCSSUnit_Null == aEdge.GetUnit(), "unexpected unit");
    6940             :   }
    6941          26 : }
    6942             : 
    6943             : /* Helper function to convert a CSS <position> specified value into its
    6944             :  * computed-style form. */
    6945             : static void
    6946           0 : ComputePositionValue(GeckoStyleContext* aStyleContext,
    6947             :                      const nsCSSValue& aValue,
    6948             :                      Position& aComputedValue,
    6949             :                      RuleNodeCacheConditions& aConditions)
    6950             : {
    6951           0 :   NS_ASSERTION(aValue.GetUnit() == eCSSUnit_Array,
    6952             :                "unexpected unit for CSS <position> value");
    6953             : 
    6954           0 :   RefPtr<nsCSSValue::Array> positionArray = aValue.GetArrayValue();
    6955           0 :   NS_ASSERTION(positionArray->Count() == 4,
    6956             :                "unexpected number of values in CSS <position> value");
    6957             : 
    6958           0 :   const nsCSSValue &xEdge   = positionArray->Item(0);
    6959           0 :   const nsCSSValue &xOffset = positionArray->Item(1);
    6960           0 :   const nsCSSValue &yEdge   = positionArray->Item(2);
    6961           0 :   const nsCSSValue &yOffset = positionArray->Item(3);
    6962             : 
    6963           0 :   NS_ASSERTION((eCSSUnit_Enumerated == xEdge.GetUnit()  ||
    6964             :                 eCSSUnit_Null       == xEdge.GetUnit()) &&
    6965             :                (eCSSUnit_Enumerated == yEdge.GetUnit()  ||
    6966             :                 eCSSUnit_Null       == yEdge.GetUnit()) &&
    6967             :                eCSSUnit_Enumerated != xOffset.GetUnit()  &&
    6968             :                eCSSUnit_Enumerated != yOffset.GetUnit(),
    6969             :                "Invalid background position");
    6970             : 
    6971           0 :   ComputePositionCoord(aStyleContext, xEdge, xOffset,
    6972             :                        &aComputedValue.mXPosition,
    6973           0 :                        aConditions);
    6974             : 
    6975           0 :   ComputePositionCoord(aStyleContext, yEdge, yOffset,
    6976             :                        &aComputedValue.mYPosition,
    6977           0 :                        aConditions);
    6978           0 : }
    6979             : 
    6980             : /* Helper function to convert the -x or -y part of a CSS <position> specified
    6981             :  * value into its computed-style form. */
    6982             : static void
    6983          26 : ComputePositionCoordValue(GeckoStyleContext* aStyleContext,
    6984             :                           const nsCSSValue& aValue,
    6985             :                           Position::Coord& aComputedValue,
    6986             :                           RuleNodeCacheConditions& aConditions)
    6987             : {
    6988          26 :   NS_ASSERTION(aValue.GetUnit() == eCSSUnit_Array,
    6989             :                "unexpected unit for position coord value");
    6990             : 
    6991          52 :   RefPtr<nsCSSValue::Array> positionArray = aValue.GetArrayValue();
    6992          26 :   NS_ASSERTION(positionArray->Count() == 2,
    6993             :                "unexpected number of values, expecting one edge and one offset");
    6994             : 
    6995          26 :   const nsCSSValue &edge   = positionArray->Item(0);
    6996          26 :   const nsCSSValue &offset = positionArray->Item(1);
    6997             : 
    6998          26 :   NS_ASSERTION((eCSSUnit_Enumerated == edge.GetUnit() ||
    6999             :                 eCSSUnit_Null       == edge.GetUnit()) &&
    7000             :                eCSSUnit_Enumerated != offset.GetUnit(),
    7001             :                "Invalid background position");
    7002             : 
    7003             :   ComputePositionCoord(aStyleContext, edge, offset,
    7004             :                        &aComputedValue,
    7005          26 :                        aConditions);
    7006          26 : }
    7007             : 
    7008             : struct BackgroundSizeAxis {
    7009             :   nsCSSValue nsCSSValuePairList::* specified;
    7010             :   nsStyleImageLayers::Size::Dimension nsStyleImageLayers::Size::* result;
    7011             :   uint8_t nsStyleImageLayers::Size::* type;
    7012             : };
    7013             : 
    7014             : static const BackgroundSizeAxis gBGSizeAxes[] = {
    7015             :   { &nsCSSValuePairList::mXValue,
    7016             :     &nsStyleImageLayers::Size::mWidth,
    7017             :     &nsStyleImageLayers::Size::mWidthType },
    7018             :   { &nsCSSValuePairList::mYValue,
    7019             :     &nsStyleImageLayers::Size::mHeight,
    7020             :     &nsStyleImageLayers::Size::mHeightType }
    7021             : };
    7022             : 
    7023             : template <>
    7024             : struct BackgroundItemComputer<nsCSSValuePairList, nsStyleImageLayers::Size>
    7025             : {
    7026          28 :   static void ComputeValue(GeckoStyleContext* aStyleContext,
    7027             :                            const nsCSSValuePairList* aSpecifiedValue,
    7028             :                            nsStyleImageLayers::Size& aComputedValue,
    7029             :                            RuleNodeCacheConditions& aConditions)
    7030             :   {
    7031          28 :     nsStyleImageLayers::Size &size = aComputedValue;
    7032          84 :     for (const BackgroundSizeAxis *axis = gBGSizeAxes,
    7033          28 :                         *axis_end = ArrayEnd(gBGSizeAxes);
    7034          84 :          axis < axis_end; ++axis) {
    7035          56 :       const nsCSSValue &specified = aSpecifiedValue->*(axis->specified);
    7036          56 :       if (eCSSUnit_Auto == specified.GetUnit()) {
    7037          24 :         size.*(axis->type) = nsStyleImageLayers::Size::eAuto;
    7038             :       }
    7039          32 :       else if (eCSSUnit_Enumerated == specified.GetUnit()) {
    7040             :         static_assert(nsStyleImageLayers::Size::eContain ==
    7041             :                       NS_STYLE_IMAGELAYER_SIZE_CONTAIN &&
    7042             :                       nsStyleImageLayers::Size::eCover ==
    7043             :                       NS_STYLE_IMAGELAYER_SIZE_COVER,
    7044             :                       "background size constants out of sync");
    7045           0 :         MOZ_ASSERT(specified.GetIntValue() == NS_STYLE_IMAGELAYER_SIZE_CONTAIN ||
    7046             :                    specified.GetIntValue() == NS_STYLE_IMAGELAYER_SIZE_COVER,
    7047             :                    "invalid enumerated value for size coordinate");
    7048           0 :         size.*(axis->type) = specified.GetIntValue();
    7049             :       }
    7050          32 :       else if (eCSSUnit_Null == specified.GetUnit()) {
    7051           0 :         MOZ_ASSERT(axis == gBGSizeAxes + 1,
    7052             :                    "null allowed only as height value, and only "
    7053             :                    "for contain/cover/initial/inherit");
    7054             : #ifdef DEBUG
    7055             :         {
    7056           0 :           const nsCSSValue &widthValue = aSpecifiedValue->mXValue;
    7057           0 :           MOZ_ASSERT(widthValue.GetUnit() != eCSSUnit_Inherit &&
    7058             :                      widthValue.GetUnit() != eCSSUnit_Initial &&
    7059             :                      widthValue.GetUnit() != eCSSUnit_Unset,
    7060             :                      "initial/inherit/unset should already have been handled");
    7061           0 :           MOZ_ASSERT(widthValue.GetUnit() == eCSSUnit_Enumerated &&
    7062             :                      (widthValue.GetIntValue() == NS_STYLE_IMAGELAYER_SIZE_CONTAIN ||
    7063             :                       widthValue.GetIntValue() == NS_STYLE_IMAGELAYER_SIZE_COVER),
    7064             :                      "null height value not corresponding to allowable "
    7065             :                      "non-null width value");
    7066             :         }
    7067             : #endif
    7068           0 :         size.*(axis->type) = size.mWidthType;
    7069             :       }
    7070          32 :       else if (eCSSUnit_Percent == specified.GetUnit()) {
    7071          28 :         (size.*(axis->result)).mLength = 0;
    7072          28 :         (size.*(axis->result)).mPercent = specified.GetPercentValue();
    7073          28 :         (size.*(axis->result)).mHasPercent = true;
    7074          28 :         size.*(axis->type) = nsStyleImageLayers::Size::eLengthPercentage;
    7075             :       }
    7076           4 :       else if (specified.IsLengthUnit()) {
    7077           8 :         (size.*(axis->result)).mLength =
    7078           4 :           CalcLength(specified, aStyleContext, aStyleContext->PresContext(),
    7079             :                      aConditions);
    7080           4 :         (size.*(axis->result)).mPercent = 0.0f;
    7081           4 :         (size.*(axis->result)).mHasPercent = false;
    7082           4 :         size.*(axis->type) = nsStyleImageLayers::Size::eLengthPercentage;
    7083             :       } else {
    7084           0 :         MOZ_ASSERT(specified.IsCalcUnit(), "unexpected unit");
    7085             :         LengthPercentPairCalcOps ops(aStyleContext,
    7086             :                                      aStyleContext->PresContext(),
    7087           0 :                                      aConditions);
    7088           0 :         nsRuleNode::ComputedCalc vals = ComputeCalc(specified, ops);
    7089           0 :         (size.*(axis->result)).mLength = vals.mLength;
    7090           0 :         (size.*(axis->result)).mPercent = vals.mPercent;
    7091           0 :         (size.*(axis->result)).mHasPercent = ops.mHasPercent;
    7092           0 :         size.*(axis->type) = nsStyleImageLayers::Size::eLengthPercentage;
    7093             :       }
    7094             :     }
    7095             : 
    7096          28 :     MOZ_ASSERT(size.mWidthType < nsStyleImageLayers::Size::eDimensionType_COUNT,
    7097             :                "bad width type");
    7098          28 :     MOZ_ASSERT(size.mHeightType < nsStyleImageLayers::Size::eDimensionType_COUNT,
    7099             :                "bad height type");
    7100          28 :     MOZ_ASSERT((size.mWidthType != nsStyleImageLayers::Size::eContain &&
    7101             :                 size.mWidthType != nsStyleImageLayers::Size::eCover) ||
    7102             :                size.mWidthType == size.mHeightType,
    7103             :                "contain/cover apply to both dimensions or to neither");
    7104          28 :   }
    7105             : };
    7106             : 
    7107             : template <class ComputedValueItem>
    7108             : static void
    7109        1140 : SetImageLayerList(GeckoStyleContext* aStyleContext,
    7110             :                   const nsCSSValue& aValue,
    7111             :                   nsStyleAutoArray<nsStyleImageLayers::Layer>& aLayers,
    7112             :                   const nsStyleAutoArray<nsStyleImageLayers::Layer>& aParentLayers,
    7113             :                   ComputedValueItem nsStyleImageLayers::Layer::* aResultLocation,
    7114             :                   ComputedValueItem aInitialValue,
    7115             :                   uint32_t aParentItemCount,
    7116             :                   uint32_t& aItemCount,
    7117             :                   uint32_t& aMaxItemCount,
    7118             :                   bool& aRebuild,
    7119             :                   RuleNodeCacheConditions& aConditions)
    7120             : {
    7121        1140 :   switch (aValue.GetUnit()) {
    7122             :   case eCSSUnit_Null:
    7123        1072 :     break;
    7124             : 
    7125             :   case eCSSUnit_Inherit:
    7126           0 :     aRebuild = true;
    7127           0 :     aConditions.SetUncacheable();
    7128           0 :     aLayers.EnsureLengthAtLeast(aParentItemCount);
    7129           0 :     aItemCount = aParentItemCount;
    7130           0 :     for (uint32_t i = 0; i < aParentItemCount; ++i) {
    7131           0 :       aLayers[i].*aResultLocation = aParentLayers[i].*aResultLocation;
    7132             :     }
    7133           0 :     break;
    7134             : 
    7135             :   case eCSSUnit_Initial:
    7136             :   case eCSSUnit_Unset:
    7137           0 :     aRebuild = true;
    7138           0 :     aItemCount = 1;
    7139           0 :     aLayers[0].*aResultLocation = aInitialValue;
    7140           0 :     break;
    7141             : 
    7142             :   case eCSSUnit_List:
    7143             :   case eCSSUnit_ListDep: {
    7144          68 :     aRebuild = true;
    7145          68 :     aItemCount = 0;
    7146          68 :     const nsCSSValueList* item = aValue.GetListValue();
    7147          92 :     do {
    7148          92 :       NS_ASSERTION(item->mValue.GetUnit() != eCSSUnit_Null &&
    7149             :                    item->mValue.GetUnit() != eCSSUnit_Inherit &&
    7150             :                    item->mValue.GetUnit() != eCSSUnit_Initial &&
    7151             :                    item->mValue.GetUnit() != eCSSUnit_Unset,
    7152             :                    "unexpected unit");
    7153          92 :       ++aItemCount;
    7154          92 :       aLayers.EnsureLengthAtLeast(aItemCount);
    7155          92 :       BackgroundItemComputer<nsCSSValueList, ComputedValueItem>
    7156          92 :         ::ComputeValue(aStyleContext, item,
    7157          92 :                        aLayers[aItemCount-1].*aResultLocation,
    7158             :                        aConditions);
    7159          92 :       item = item->mNext;
    7160             :     } while (item);
    7161          68 :     break;
    7162             :   }
    7163             : 
    7164             :   default:
    7165           0 :     MOZ_ASSERT(false, "unexpected unit");
    7166             :   }
    7167             : 
    7168        1140 :   if (aItemCount > aMaxItemCount)
    7169           7 :     aMaxItemCount = aItemCount;
    7170        1140 : }
    7171             : 
    7172             : // The same as SetImageLayerList, but for values stored in
    7173             : // layer.mPosition.*aResultLocation instead of layer.*aResultLocation.
    7174             : // This code is duplicated because it would be annoying to make
    7175             : // SetImageLayerList generic enough to handle both cases.
    7176             : static void
    7177         456 : SetImageLayerPositionCoordList(
    7178             :                   GeckoStyleContext* aStyleContext,
    7179             :                   const nsCSSValue& aValue,
    7180             :                   nsStyleAutoArray<nsStyleImageLayers::Layer>& aLayers,
    7181             :                   const nsStyleAutoArray<nsStyleImageLayers::Layer>& aParentLayers,
    7182             :                   Position::Coord
    7183             :                       Position::* aResultLocation,
    7184             :                   Position::Coord aInitialValue,
    7185             :                   uint32_t aParentItemCount,
    7186             :                   uint32_t& aItemCount,
    7187             :                   uint32_t& aMaxItemCount,
    7188             :                   bool& aRebuild,
    7189             :                   RuleNodeCacheConditions& aConditions)
    7190             : {
    7191         456 :   switch (aValue.GetUnit()) {
    7192             :   case eCSSUnit_Null:
    7193         430 :     break;
    7194             : 
    7195             :   case eCSSUnit_Inherit:
    7196           0 :     aRebuild = true;
    7197           0 :     aConditions.SetUncacheable();
    7198           0 :     aLayers.EnsureLengthAtLeast(aParentItemCount);
    7199           0 :     aItemCount = aParentItemCount;
    7200           0 :     for (uint32_t i = 0; i < aParentItemCount; ++i) {
    7201           0 :       aLayers[i].mPosition.*aResultLocation = aParentLayers[i].mPosition.*aResultLocation;
    7202             :     }
    7203           0 :     break;
    7204             : 
    7205             :   case eCSSUnit_Initial:
    7206             :   case eCSSUnit_Unset:
    7207           0 :     aRebuild = true;
    7208           0 :     aItemCount = 1;
    7209           0 :     aLayers[0].mPosition.*aResultLocation = aInitialValue;
    7210           0 :     break;
    7211             : 
    7212             :   case eCSSUnit_List:
    7213             :   case eCSSUnit_ListDep: {
    7214          26 :     aRebuild = true;
    7215          26 :     aItemCount = 0;
    7216          26 :     const nsCSSValueList* item = aValue.GetListValue();
    7217           0 :     do {
    7218          26 :       NS_ASSERTION(item->mValue.GetUnit() != eCSSUnit_Null &&
    7219             :                    item->mValue.GetUnit() != eCSSUnit_Inherit &&
    7220             :                    item->mValue.GetUnit() != eCSSUnit_Initial &&
    7221             :                    item->mValue.GetUnit() != eCSSUnit_Unset,
    7222             :                    "unexpected unit");
    7223          26 :       ++aItemCount;
    7224          26 :       aLayers.EnsureLengthAtLeast(aItemCount);
    7225             : 
    7226          26 :       ComputePositionCoordValue(aStyleContext, item->mValue,
    7227          26 :                                 aLayers[aItemCount-1].mPosition.*aResultLocation,
    7228          26 :                                 aConditions);
    7229          26 :       item = item->mNext;
    7230          26 :     } while (item);
    7231          26 :     break;
    7232             :   }
    7233             : 
    7234             :   default:
    7235           0 :     MOZ_ASSERT(false, "unexpected unit");
    7236             :   }
    7237             : 
    7238         456 :   if (aItemCount > aMaxItemCount)
    7239           0 :     aMaxItemCount = aItemCount;
    7240         456 : }
    7241             : 
    7242             : template <class ComputedValueItem>
    7243             : static void
    7244         456 : SetImageLayerPairList(GeckoStyleContext* aStyleContext,
    7245             :                       const nsCSSValue& aValue,
    7246             :                       nsStyleAutoArray<nsStyleImageLayers::Layer>& aLayers,
    7247             :                       const nsStyleAutoArray<nsStyleImageLayers::Layer>& aParentLayers,
    7248             :                       ComputedValueItem nsStyleImageLayers::Layer::*
    7249             :                                                                 aResultLocation,
    7250             :                       ComputedValueItem aInitialValue,
    7251             :                       uint32_t aParentItemCount,
    7252             :                       uint32_t& aItemCount,
    7253             :                       uint32_t& aMaxItemCount,
    7254             :                       bool& aRebuild,
    7255             :                       RuleNodeCacheConditions& aConditions)
    7256             : {
    7257         456 :   switch (aValue.GetUnit()) {
    7258             :   case eCSSUnit_Null:
    7259         415 :     break;
    7260             : 
    7261             :   case eCSSUnit_Inherit:
    7262           0 :     aRebuild = true;
    7263           0 :     aConditions.SetUncacheable();
    7264           0 :     aLayers.EnsureLengthAtLeast(aParentItemCount);
    7265           0 :     aItemCount = aParentItemCount;
    7266           0 :     for (uint32_t i = 0; i < aParentItemCount; ++i) {
    7267           0 :       aLayers[i].*aResultLocation = aParentLayers[i].*aResultLocation;
    7268             :     }
    7269           0 :     break;
    7270             : 
    7271             :   case eCSSUnit_Initial:
    7272             :   case eCSSUnit_Unset:
    7273           0 :     aRebuild = true;
    7274           0 :     aItemCount = 1;
    7275           0 :     aLayers[0].*aResultLocation = aInitialValue;
    7276           0 :     break;
    7277             : 
    7278             :   case eCSSUnit_PairList:
    7279             :   case eCSSUnit_PairListDep: {
    7280          41 :     aRebuild = true;
    7281          41 :     aItemCount = 0;
    7282          41 :     const nsCSSValuePairList* item = aValue.GetPairListValue();
    7283          46 :     do {
    7284          46 :       NS_ASSERTION(item->mXValue.GetUnit() != eCSSUnit_Inherit &&
    7285             :                    item->mXValue.GetUnit() != eCSSUnit_Initial &&
    7286             :                    item->mXValue.GetUnit() != eCSSUnit_Unset &&
    7287             :                    item->mYValue.GetUnit() != eCSSUnit_Inherit &&
    7288             :                    item->mYValue.GetUnit() != eCSSUnit_Initial &&
    7289             :                    item->mYValue.GetUnit() != eCSSUnit_Unset,
    7290             :                    "unexpected unit");
    7291          46 :       ++aItemCount;
    7292          46 :       aLayers.EnsureLengthAtLeast(aItemCount);
    7293          46 :       BackgroundItemComputer<nsCSSValuePairList, ComputedValueItem>
    7294          46 :         ::ComputeValue(aStyleContext, item,
    7295          46 :                        aLayers[aItemCount-1].*aResultLocation,
    7296             :                        aConditions);
    7297          46 :       item = item->mNext;
    7298             :     } while (item);
    7299          41 :     break;
    7300             :   }
    7301             : 
    7302             :   default:
    7303           0 :     MOZ_ASSERT(false, "unexpected unit");
    7304             :   }
    7305             : 
    7306         456 :   if (aItemCount > aMaxItemCount)
    7307           0 :     aMaxItemCount = aItemCount;
    7308         456 : }
    7309             : 
    7310             : template <class ComputedValueItem>
    7311             : static void
    7312         405 : FillImageLayerList(
    7313             :     nsStyleAutoArray<nsStyleImageLayers::Layer>& aLayers,
    7314             :     ComputedValueItem nsStyleImageLayers::Layer::* aResultLocation,
    7315             :     uint32_t aItemCount, uint32_t aFillCount)
    7316             : {
    7317         405 :   NS_PRECONDITION(aFillCount <= aLayers.Length(), "unexpected array length");
    7318         502 :   for (uint32_t sourceLayer = 0, destLayer = aItemCount;
    7319         502 :        destLayer < aFillCount;
    7320             :        ++sourceLayer, ++destLayer) {
    7321         194 :     aLayers[destLayer].*aResultLocation =
    7322          97 :       aLayers[sourceLayer].*aResultLocation;
    7323             :   }
    7324         405 : }
    7325             : 
    7326             : // The same as FillImageLayerList, but for values stored in
    7327             : // layer.mPosition.*aResultLocation instead of layer.*aResultLocation.
    7328             : static void
    7329          90 : FillImageLayerPositionCoordList(
    7330             :     nsStyleAutoArray<nsStyleImageLayers::Layer>& aLayers,
    7331             :     Position::Coord
    7332             :         Position::* aResultLocation,
    7333             :     uint32_t aItemCount, uint32_t aFillCount)
    7334             : {
    7335          90 :   NS_PRECONDITION(aFillCount <= aLayers.Length(), "unexpected array length");
    7336         118 :   for (uint32_t sourceLayer = 0, destLayer = aItemCount;
    7337         118 :        destLayer < aFillCount;
    7338             :        ++sourceLayer, ++destLayer) {
    7339          56 :     aLayers[destLayer].mPosition.*aResultLocation =
    7340          28 :       aLayers[sourceLayer].mPosition.*aResultLocation;
    7341             :   }
    7342          90 : }
    7343             : 
    7344             : /* static */
    7345             : void
    7346          45 : nsRuleNode::FillAllBackgroundLists(nsStyleImageLayers& aImage,
    7347             :                                    uint32_t aMaxItemCount)
    7348             : {
    7349             :   // Delete any extra items.  We need to keep layers in which any
    7350             :   // property was specified.
    7351          45 :   aImage.mLayers.TruncateLengthNonZero(aMaxItemCount);
    7352             : 
    7353          45 :   uint32_t fillCount = aImage.mImageCount;
    7354          45 :   FillImageLayerList(aImage.mLayers,
    7355             :                      &nsStyleImageLayers::Layer::mImage,
    7356          45 :                      aImage.mImageCount, fillCount);
    7357          45 :   FillImageLayerList(aImage.mLayers,
    7358             :                      &nsStyleImageLayers::Layer::mRepeat,
    7359          45 :                      aImage.mRepeatCount, fillCount);
    7360          45 :   FillImageLayerList(aImage.mLayers,
    7361             :                      &nsStyleImageLayers::Layer::mAttachment,
    7362          45 :                      aImage.mAttachmentCount, fillCount);
    7363          45 :   FillImageLayerList(aImage.mLayers,
    7364             :                      &nsStyleImageLayers::Layer::mClip,
    7365          45 :                      aImage.mClipCount, fillCount);
    7366          45 :   FillImageLayerList(aImage.mLayers,
    7367             :                      &nsStyleImageLayers::Layer::mBlendMode,
    7368          45 :                      aImage.mBlendModeCount, fillCount);
    7369          45 :   FillImageLayerList(aImage.mLayers,
    7370             :                      &nsStyleImageLayers::Layer::mOrigin,
    7371          45 :                      aImage.mOriginCount, fillCount);
    7372          45 :   FillImageLayerPositionCoordList(aImage.mLayers,
    7373             :                                   &Position::mXPosition,
    7374          45 :                                   aImage.mPositionXCount, fillCount);
    7375          45 :   FillImageLayerPositionCoordList(aImage.mLayers,
    7376             :                                   &Position::mYPosition,
    7377          45 :                                   aImage.mPositionYCount, fillCount);
    7378          45 :   FillImageLayerList(aImage.mLayers,
    7379             :                      &nsStyleImageLayers::Layer::mSize,
    7380          45 :                      aImage.mSizeCount, fillCount);
    7381          45 :   FillImageLayerList(aImage.mLayers,
    7382             :                      &nsStyleImageLayers::Layer::mMaskMode,
    7383          45 :                      aImage.mMaskModeCount, fillCount);
    7384          45 :   FillImageLayerList(aImage.mLayers,
    7385             :                      &nsStyleImageLayers::Layer::mComposite,
    7386          45 :                      aImage.mCompositeCount, fillCount);
    7387          45 : }
    7388             : 
    7389             : const void*
    7390         198 : nsRuleNode::ComputeBackgroundData(void* aStartStruct,
    7391             :                                   const nsRuleData* aRuleData,
    7392             :                                   GeckoStyleContext* aContext,
    7393             :                                   nsRuleNode* aHighestNode,
    7394             :                                   const RuleDetail aRuleDetail,
    7395             :                                   const RuleNodeCacheConditions aConditions)
    7396             : {
    7397         396 :   COMPUTE_START_RESET(Background, bg, parentBG)
    7398             : 
    7399             :   // background-color: color, inherit
    7400         396 :   SetComplexColor<eUnsetInitial>(*aRuleData->ValueForBackgroundColor(),
    7401             :                                  parentBG->mBackgroundColor,
    7402         396 :                                  StyleComplexColor::FromColor(
    7403             :                                      NS_RGBA(0, 0, 0, 0)),
    7404         198 :                                  mPresContext,
    7405         198 :                                  bg->mBackgroundColor, conditions);
    7406             : 
    7407         198 :   uint32_t maxItemCount = 1;
    7408         198 :   bool rebuild = false;
    7409             : 
    7410             :   // background-image: url (stored as image), none, inherit [list]
    7411         396 :   nsStyleImage initialImage;
    7412         594 :   SetImageLayerList(aContext, *aRuleData->ValueForBackgroundImage(),
    7413             :                     bg->mImage.mLayers,
    7414             :                     parentBG->mImage.mLayers,
    7415             :                     &nsStyleImageLayers::Layer::mImage,
    7416         198 :                     initialImage, parentBG->mImage.mImageCount,
    7417             :                     bg->mImage.mImageCount,
    7418         198 :                     maxItemCount, rebuild, conditions);
    7419             : 
    7420             :   // background-repeat: enum, inherit, initial [pair list]
    7421         198 :   nsStyleImageLayers::Repeat initialRepeat;
    7422         198 :   initialRepeat.SetInitialValues();
    7423         396 :   SetImageLayerPairList(aContext, *aRuleData->ValueForBackgroundRepeat(),
    7424             :                         bg->mImage.mLayers,
    7425             :                         parentBG->mImage.mLayers,
    7426             :                         &nsStyleImageLayers::Layer::mRepeat,
    7427         198 :                         initialRepeat, parentBG->mImage.mRepeatCount,
    7428             :                         bg->mImage.mRepeatCount, maxItemCount, rebuild,
    7429         198 :                         conditions);
    7430             : 
    7431             :   // background-attachment: enum, inherit, initial [list]
    7432         396 :   SetImageLayerList(aContext, *aRuleData->ValueForBackgroundAttachment(),
    7433             :                     bg->mImage.mLayers, parentBG->mImage.mLayers,
    7434             :                     &nsStyleImageLayers::Layer::mAttachment,
    7435             :                     uint8_t(NS_STYLE_IMAGELAYER_ATTACHMENT_SCROLL),
    7436         198 :                     parentBG->mImage.mAttachmentCount,
    7437             :                     bg->mImage.mAttachmentCount, maxItemCount, rebuild,
    7438         198 :                     conditions);
    7439             : 
    7440             :   // background-clip: enum, inherit, initial [list]
    7441         396 :   SetImageLayerList(aContext, *aRuleData->ValueForBackgroundClip(),
    7442             :                     bg->mImage.mLayers,
    7443             :                     parentBG->mImage.mLayers,
    7444             :                     &nsStyleImageLayers::Layer::mClip,
    7445             :                     StyleGeometryBox::BorderBox,
    7446         198 :                     parentBG->mImage.mClipCount,
    7447         198 :                     bg->mImage.mClipCount, maxItemCount, rebuild, conditions);
    7448             : 
    7449             :   // background-blend-mode: enum, inherit, initial [list]
    7450         396 :   SetImageLayerList(aContext, *aRuleData->ValueForBackgroundBlendMode(),
    7451             :                     bg->mImage.mLayers,
    7452             :                     parentBG->mImage.mLayers,
    7453             :                     &nsStyleImageLayers::Layer::mBlendMode,
    7454             :                     uint8_t(NS_STYLE_BLEND_NORMAL),
    7455         198 :                     parentBG->mImage.mBlendModeCount,
    7456             :                     bg->mImage.mBlendModeCount, maxItemCount, rebuild,
    7457         198 :                     conditions);
    7458             : 
    7459             :   // background-origin: enum, inherit, initial [list]
    7460         396 :   SetImageLayerList(aContext, *aRuleData->ValueForBackgroundOrigin(),
    7461             :                     bg->mImage.mLayers,
    7462             :                     parentBG->mImage.mLayers,
    7463             :                     &nsStyleImageLayers::Layer::mOrigin,
    7464             :                     StyleGeometryBox::PaddingBox,
    7465         198 :                     parentBG->mImage.mOriginCount,
    7466             :                     bg->mImage.mOriginCount, maxItemCount, rebuild,
    7467         198 :                     conditions);
    7468             : 
    7469             :   // background-position-x/y: enum, length, percent (flags), inherit [list]
    7470             :   Position::Coord initialPositionCoord;
    7471         198 :   initialPositionCoord.mPercent = 0.0f;
    7472         198 :   initialPositionCoord.mLength = 0;
    7473         198 :   initialPositionCoord.mHasPercent = true;
    7474             : 
    7475         396 :   SetImageLayerPositionCoordList(
    7476         198 :                     aContext, *aRuleData->ValueForBackgroundPositionX(),
    7477             :                     bg->mImage.mLayers,
    7478             :                     parentBG->mImage.mLayers,
    7479             :                     &Position::mXPosition,
    7480         198 :                     initialPositionCoord, parentBG->mImage.mPositionXCount,
    7481             :                     bg->mImage.mPositionXCount, maxItemCount, rebuild,
    7482         198 :                     conditions);
    7483         396 :   SetImageLayerPositionCoordList(
    7484         198 :                     aContext, *aRuleData->ValueForBackgroundPositionY(),
    7485             :                     bg->mImage.mLayers,
    7486             :                     parentBG->mImage.mLayers,
    7487             :                     &Position::mYPosition,
    7488         198 :                     initialPositionCoord, parentBG->mImage.mPositionYCount,
    7489             :                     bg->mImage.mPositionYCount, maxItemCount, rebuild,
    7490         198 :                     conditions);
    7491             : 
    7492             :   // background-size: enum, length, auto, inherit, initial [pair list]
    7493         198 :   nsStyleImageLayers::Size initialSize;
    7494         198 :   initialSize.SetInitialValues();
    7495         396 :   SetImageLayerPairList(aContext, *aRuleData->ValueForBackgroundSize(),
    7496             :                         bg->mImage.mLayers,
    7497             :                         parentBG->mImage.mLayers,
    7498             :                         &nsStyleImageLayers::Layer::mSize,
    7499         198 :                         initialSize, parentBG->mImage.mSizeCount,
    7500             :                         bg->mImage.mSizeCount, maxItemCount, rebuild,
    7501         198 :                         conditions);
    7502             : 
    7503         198 :   if (rebuild) {
    7504          43 :     FillAllBackgroundLists(bg->mImage, maxItemCount);
    7505             :   }
    7506             : 
    7507         396 :   COMPUTE_END_RESET(Background, bg)
    7508             : }
    7509             : 
    7510             : const void*
    7511         214 : nsRuleNode::ComputeMarginData(void* aStartStruct,
    7512             :                               const nsRuleData* aRuleData,
    7513             :                               GeckoStyleContext* aContext,
    7514             :                               nsRuleNode* aHighestNode,
    7515             :                               const RuleDetail aRuleDetail,
    7516             :                               const RuleNodeCacheConditions aConditions)
    7517             : {
    7518         428 :   COMPUTE_START_RESET(Margin, margin, parentMargin)
    7519             : 
    7520             :   // margin: length, percent, calc, inherit
    7521             :   const nsCSSPropertyID* subprops =
    7522         214 :     nsCSSProps::SubpropertyEntryFor(eCSSProperty_margin);
    7523         428 :   nsStyleCoord coord;
    7524        1070 :   NS_FOR_CSS_SIDES(side) {
    7525        1712 :     nsStyleCoord parentCoord = parentMargin->mMargin.Get(side);
    7526         856 :     if (SetCoord(*aRuleData->ValueFor(subprops[side]),
    7527             :                  coord, parentCoord,
    7528             :                  SETCOORD_LPAH | SETCOORD_INITIAL_ZERO | SETCOORD_STORE_CALC |
    7529             :                    SETCOORD_UNSET_INITIAL,
    7530         856 :                  aContext, mPresContext, conditions)) {
    7531         510 :       margin->mMargin.Set(side, coord);
    7532             :     }
    7533             :   }
    7534             : 
    7535         428 :   COMPUTE_END_RESET(Margin, margin)
    7536             : }
    7537             : 
    7538             : static void
    7539         483 : SetBorderImageRect(const nsCSSValue& aValue,
    7540             :                    /** outparam */ nsCSSRect& aRect)
    7541             : {
    7542         483 :   switch (aValue.GetUnit()) {
    7543             :   case eCSSUnit_Null:
    7544         300 :     aRect.Reset();
    7545         300 :     break;
    7546             :   case eCSSUnit_Rect:
    7547         183 :     aRect = aValue.GetRectValue();
    7548         183 :     break;
    7549             :   case eCSSUnit_Inherit:
    7550             :   case eCSSUnit_Initial:
    7551             :   case eCSSUnit_Unset:
    7552           0 :     aRect.SetAllSidesTo(aValue);
    7553           0 :     break;
    7554             :   default:
    7555           0 :     NS_ASSERTION(false, "Unexpected border image value for rect.");
    7556             :   }
    7557         483 : }
    7558             : 
    7559             : static void
    7560         161 : SetBorderImagePair(const nsCSSValue& aValue,
    7561             :                    /** outparam */ nsCSSValuePair& aPair)
    7562             : {
    7563         161 :   switch (aValue.GetUnit()) {
    7564             :   case eCSSUnit_Null:
    7565         100 :     aPair.Reset();
    7566         100 :     break;
    7567             :   case eCSSUnit_Pair:
    7568          61 :     aPair = aValue.GetPairValue();
    7569          61 :     break;
    7570             :   case eCSSUnit_Inherit:
    7571             :   case eCSSUnit_Initial:
    7572             :   case eCSSUnit_Unset:
    7573           0 :     aPair.SetBothValuesTo(aValue);
    7574           0 :     break;
    7575             :   default:
    7576           0 :     NS_ASSERTION(false, "Unexpected border image value for pair.");
    7577             :   }
    7578         161 : }
    7579             : 
    7580             : static void
    7581         161 : SetBorderImageSlice(const nsCSSValue& aValue,
    7582             :                     /** outparam */ nsCSSValue& aSlice,
    7583             :                     /** outparam */ nsCSSValue& aFill)
    7584             : {
    7585             :   const nsCSSValueList* valueList;
    7586         161 :   switch (aValue.GetUnit()) {
    7587             :   case eCSSUnit_Null:
    7588         100 :     aSlice.Reset();
    7589         100 :     aFill.Reset();
    7590         100 :     break;
    7591             :   case eCSSUnit_List:
    7592             :     // Get slice dimensions.
    7593          61 :     valueList = aValue.GetListValue();
    7594          61 :     aSlice = valueList->mValue;
    7595             : 
    7596             :     // Get "fill" keyword.
    7597          61 :     valueList = valueList->mNext;
    7598          61 :     if (valueList) {
    7599           0 :       aFill = valueList->mValue;
    7600             :     } else {
    7601          61 :       aFill.SetInitialValue();
    7602             :     }
    7603          61 :     break;
    7604             :   case eCSSUnit_Inherit:
    7605             :   case eCSSUnit_Initial:
    7606             :   case eCSSUnit_Unset:
    7607           0 :     aSlice = aValue;
    7608           0 :     aFill = aValue;
    7609           0 :     break;
    7610             :   default:
    7611           0 :     NS_ASSERTION(false, "Unexpected border image value for pair.");
    7612             :   }
    7613         161 : }
    7614             : 
    7615             : const void*
    7616         161 : nsRuleNode::ComputeBorderData(void* aStartStruct,
    7617             :                               const nsRuleData* aRuleData,
    7618             :                               GeckoStyleContext* aContext,
    7619             :                               nsRuleNode* aHighestNode,
    7620             :                               const RuleDetail aRuleDetail,
    7621             :                               const RuleNodeCacheConditions aConditions)
    7622             : {
    7623         322 :   COMPUTE_START_RESET(Border, border, parentBorder)
    7624             : 
    7625             :   // box-decoration-break: enum, inherit, initial
    7626         161 :   SetValue(*aRuleData->ValueForBoxDecorationBreak(),
    7627             :            border->mBoxDecorationBreak, conditions,
    7628             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    7629         161 :            parentBorder->mBoxDecorationBreak,
    7630         161 :            StyleBoxDecorationBreak::Slice);
    7631             : 
    7632             :   // border-width, border-*-width: length, enum, inherit
    7633         322 :   nsStyleCoord coord;
    7634             :   {
    7635             :     const nsCSSPropertyID* subprops =
    7636         161 :       nsCSSProps::SubpropertyEntryFor(eCSSProperty_border_width);
    7637         805 :     NS_FOR_CSS_SIDES(side) {
    7638         644 :       const nsCSSValue& value = *aRuleData->ValueFor(subprops[side]);
    7639         644 :       NS_ASSERTION(eCSSUnit_Percent != value.GetUnit(),
    7640             :                    "Percentage borders not implemented yet "
    7641             :                    "If implementing, make sure to fix all consumers of "
    7642             :                    "nsStyleBorder, the IsPercentageAwareChild method, "
    7643             :                    "the nsAbsoluteContainingBlock::FrameDependsOnContainer "
    7644             :                    "method, the "
    7645             :                    "nsLineLayout::IsPercentageAwareReplacedElement method "
    7646             :                    "and probably some other places");
    7647             :       Maybe<nscoord> coord =
    7648             :         ComputeLineWidthValue<eUnsetInitial>(
    7649         644 :           value, parentBorder->GetComputedBorder().Side(side),
    7650             :           nsPresContext::GetBorderWidthForKeyword(NS_STYLE_BORDER_WIDTH_MEDIUM),
    7651        1932 :           aContext, mPresContext, conditions);
    7652         644 :       if (coord.isSome()) {
    7653         282 :         border->SetBorderWidth(side, *coord);
    7654             :       }
    7655             :     }
    7656             :   }
    7657             : 
    7658             :   // border-style, border-*-style: enum, inherit
    7659             :   {
    7660             :     const nsCSSPropertyID* subprops =
    7661         161 :       nsCSSProps::SubpropertyEntryFor(eCSSProperty_border_style);
    7662         805 :     NS_FOR_CSS_SIDES(side) {
    7663         644 :       const nsCSSValue& value = *aRuleData->ValueFor(subprops[side]);
    7664         644 :       nsCSSUnit unit = value.GetUnit();
    7665         644 :       MOZ_ASSERT(eCSSUnit_None != unit,
    7666             :                  "'none' should be handled as enumerated value");
    7667         644 :       if (eCSSUnit_Enumerated == unit) {
    7668         292 :         border->SetBorderStyle(side, value.GetIntValue());
    7669             :       }
    7670         352 :       else if (eCSSUnit_Initial == unit ||
    7671             :                eCSSUnit_Unset == unit) {
    7672           0 :         border->SetBorderStyle(side, NS_STYLE_BORDER_STYLE_NONE);
    7673             :       }
    7674         352 :       else if (eCSSUnit_Inherit == unit) {
    7675           0 :         conditions.SetUncacheable();
    7676           0 :         border->SetBorderStyle(side, parentBorder->GetBorderStyle(side));
    7677             :       }
    7678             :     }
    7679             :   }
    7680             : 
    7681             :   // -moz-border-*-colors: color, string, enum, none, inherit/initial
    7682             :   nscolor borderColor;
    7683         161 :   nscolor unused = NS_RGB(0,0,0);
    7684             : 
    7685             :   static const nsCSSPropertyID borderColorsProps[] = {
    7686             :     eCSSProperty__moz_border_top_colors,
    7687             :     eCSSProperty__moz_border_right_colors,
    7688             :     eCSSProperty__moz_border_bottom_colors,
    7689             :     eCSSProperty__moz_border_left_colors
    7690             :   };
    7691             : 
    7692         805 :   NS_FOR_CSS_SIDES(side) {
    7693         644 :     const nsCSSValue& value = *aRuleData->ValueFor(borderColorsProps[side]);
    7694         644 :     switch (value.GetUnit()) {
    7695             :     case eCSSUnit_Null:
    7696         408 :       break;
    7697             : 
    7698             :     case eCSSUnit_Initial:
    7699             :     case eCSSUnit_Unset:
    7700             :     case eCSSUnit_None:
    7701         236 :       border->ClearBorderColors(side);
    7702         236 :       break;
    7703             : 
    7704             :     case eCSSUnit_Inherit: {
    7705           0 :       conditions.SetUncacheable();
    7706           0 :       border->ClearBorderColors(side);
    7707           0 :       if (parentContext) {
    7708             :         nsBorderColors *parentColors;
    7709           0 :         parentBorder->GetCompositeColors(side, &parentColors);
    7710           0 :         if (parentColors) {
    7711           0 :           border->EnsureBorderColors();
    7712           0 :           border->mBorderColors[side] = parentColors->Clone();
    7713             :         }
    7714             :       }
    7715           0 :       break;
    7716             :     }
    7717             : 
    7718             :     case eCSSUnit_List:
    7719             :     case eCSSUnit_ListDep: {
    7720             :       // Some composite border color information has been specified for this
    7721             :       // border side.
    7722           0 :       border->EnsureBorderColors();
    7723           0 :       border->ClearBorderColors(side);
    7724           0 :       const nsCSSValueList* list = value.GetListValue();
    7725           0 :       while (list) {
    7726           0 :         if (SetColor(list->mValue, unused, mPresContext,
    7727             :                      aContext, borderColor, conditions))
    7728           0 :           border->AppendBorderColor(side, borderColor);
    7729             :         else {
    7730           0 :           NS_NOTREACHED("unexpected item in -moz-border-*-colors list");
    7731             :         }
    7732           0 :         list = list->mNext;
    7733             :       }
    7734           0 :       break;
    7735             :     }
    7736             : 
    7737             :     default:
    7738           0 :       MOZ_ASSERT(false, "unrecognized border color unit");
    7739             :     }
    7740             :   }
    7741             : 
    7742             :   // border-color, border-*-color: color, string, enum, inherit
    7743             :   {
    7744             :     const nsCSSPropertyID* subprops =
    7745         161 :       nsCSSProps::SubpropertyEntryFor(eCSSProperty_border_color);
    7746         805 :     NS_FOR_CSS_SIDES(side) {
    7747        1288 :       SetComplexColor<eUnsetInitial>(*aRuleData->ValueFor(subprops[side]),
    7748         644 :                                      parentBorder->mBorderColor[side],
    7749        1288 :                                      StyleComplexColor::CurrentColor(),
    7750         644 :                                      mPresContext,
    7751        1288 :                                      border->mBorderColor[side], conditions);
    7752             :     }
    7753             :   }
    7754             : 
    7755             :   // border-radius: length, percent, inherit
    7756             :   {
    7757             :     const nsCSSPropertyID* subprops =
    7758         161 :       nsCSSProps::SubpropertyEntryFor(eCSSProperty_border_radius);
    7759         805 :     NS_FOR_CSS_FULL_CORNERS(corner) {
    7760         644 :       int cx = FullToHalfCorner(corner, false);
    7761         644 :       int cy = FullToHalfCorner(corner, true);
    7762         644 :       const nsCSSValue& radius = *aRuleData->ValueFor(subprops[corner]);
    7763        1288 :       nsStyleCoord parentX = parentBorder->mBorderRadius.Get(cx);
    7764        1288 :       nsStyleCoord parentY = parentBorder->mBorderRadius.Get(cy);
    7765        1288 :       nsStyleCoord coordX, coordY;
    7766             : 
    7767         644 :       if (SetPairCoords(radius, coordX, coordY, parentX, parentY,
    7768             :                         SETCOORD_LPH | SETCOORD_INITIAL_ZERO |
    7769             :                           SETCOORD_STORE_CALC | SETCOORD_UNSET_INITIAL,
    7770         644 :                         aContext, mPresContext, conditions)) {
    7771         357 :         border->mBorderRadius.Set(cx, coordX);
    7772         357 :         border->mBorderRadius.Set(cy, coordY);
    7773             :       }
    7774             :     }
    7775             :   }
    7776             : 
    7777             :   // float-edge: enum, inherit, initial
    7778         161 :   SetValue(*aRuleData->ValueForFloatEdge(),
    7779             :            border->mFloatEdge, conditions,
    7780             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    7781         161 :            parentBorder->mFloatEdge,
    7782         161 :            StyleFloatEdge::ContentBox);
    7783             : 
    7784             :   // border-image-source
    7785         161 :   const nsCSSValue* borderImageSource = aRuleData->ValueForBorderImageSource();
    7786         161 :   if (borderImageSource->GetUnit() == eCSSUnit_Inherit) {
    7787           0 :     conditions.SetUncacheable();
    7788           0 :     border->mBorderImageSource = parentBorder->mBorderImageSource;
    7789             :   } else {
    7790         161 :     SetStyleImage(aContext,
    7791             :                   *borderImageSource,
    7792             :                   border->mBorderImageSource,
    7793         161 :                   conditions);
    7794             :   }
    7795             : 
    7796         322 :   nsCSSValue borderImageSliceValue;
    7797         322 :   nsCSSValue borderImageSliceFill;
    7798         161 :   SetBorderImageSlice(*aRuleData->ValueForBorderImageSlice(),
    7799         161 :                       borderImageSliceValue, borderImageSliceFill);
    7800             : 
    7801             :   // border-image-slice: fill
    7802         161 :   SetValue(borderImageSliceFill,
    7803             :            border->mBorderImageFill,
    7804             :            conditions,
    7805             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    7806         161 :            parentBorder->mBorderImageFill,
    7807         161 :            NS_STYLE_BORDER_IMAGE_SLICE_NOFILL);
    7808             : 
    7809         322 :   nsCSSRect borderImageSlice;
    7810         161 :   SetBorderImageRect(borderImageSliceValue, borderImageSlice);
    7811             : 
    7812         322 :   nsCSSRect borderImageWidth;
    7813         161 :   SetBorderImageRect(*aRuleData->ValueForBorderImageWidth(),
    7814         161 :                      borderImageWidth);
    7815             : 
    7816         322 :   nsCSSRect borderImageOutset;
    7817         161 :   SetBorderImageRect(*aRuleData->ValueForBorderImageOutset(),
    7818         161 :                      borderImageOutset);
    7819             : 
    7820         805 :   NS_FOR_CSS_SIDES (side) {
    7821             :     // border-image-slice
    7822        1288 :     if (SetCoord(borderImageSlice.*(nsCSSRect::sides[side]), coord,
    7823        1288 :                  parentBorder->mBorderImageSlice.Get(side),
    7824             :                  SETCOORD_FACTOR | SETCOORD_PERCENT |
    7825             :                    SETCOORD_INHERIT | SETCOORD_INITIAL_HUNDRED_PCT |
    7826             :                    SETCOORD_UNSET_INITIAL,
    7827         644 :                  aContext, mPresContext, conditions)) {
    7828         244 :       border->mBorderImageSlice.Set(side, coord);
    7829             :     }
    7830             : 
    7831             :     // border-image-width
    7832             :     // 'auto' here means "same as slice"
    7833        1288 :     if (SetCoord(borderImageWidth.*(nsCSSRect::sides[side]), coord,
    7834        1288 :                  parentBorder->mBorderImageWidth.Get(side),
    7835             :                  SETCOORD_LPAH | SETCOORD_FACTOR | SETCOORD_INITIAL_FACTOR_ONE |
    7836             :                    SETCOORD_UNSET_INITIAL,
    7837         644 :                  aContext, mPresContext, conditions)) {
    7838         244 :       border->mBorderImageWidth.Set(side, coord);
    7839             :     }
    7840             : 
    7841             :     // border-image-outset
    7842        1288 :     if (SetCoord(borderImageOutset.*(nsCSSRect::sides[side]), coord,
    7843        1288 :                  parentBorder->mBorderImageOutset.Get(side),
    7844             :                  SETCOORD_LENGTH | SETCOORD_FACTOR |
    7845             :                    SETCOORD_INHERIT | SETCOORD_INITIAL_FACTOR_ZERO |
    7846             :                    SETCOORD_UNSET_INITIAL,
    7847         644 :                  aContext, mPresContext, conditions)) {
    7848         244 :       border->mBorderImageOutset.Set(side, coord);
    7849             :     }
    7850             :   }
    7851             : 
    7852             :   // border-image-repeat
    7853         322 :   nsCSSValuePair borderImageRepeat;
    7854         161 :   SetBorderImagePair(*aRuleData->ValueForBorderImageRepeat(),
    7855         161 :                      borderImageRepeat);
    7856             : 
    7857         161 :   SetValue(borderImageRepeat.mXValue,
    7858             :            border->mBorderImageRepeatH,
    7859             :            conditions,
    7860             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    7861         161 :            parentBorder->mBorderImageRepeatH,
    7862         161 :            NS_STYLE_BORDER_IMAGE_REPEAT_STRETCH);
    7863             : 
    7864         161 :   SetValue(borderImageRepeat.mYValue,
    7865             :            border->mBorderImageRepeatV,
    7866             :            conditions,
    7867             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    7868         161 :            parentBorder->mBorderImageRepeatV,
    7869         161 :            NS_STYLE_BORDER_IMAGE_REPEAT_STRETCH);
    7870             : 
    7871         322 :   COMPUTE_END_RESET(Border, border)
    7872             : }
    7873             : 
    7874             : const void*
    7875         145 : nsRuleNode::ComputePaddingData(void* aStartStruct,
    7876             :                                const nsRuleData* aRuleData,
    7877             :                                GeckoStyleContext* aContext,
    7878             :                                nsRuleNode* aHighestNode,
    7879             :                                const RuleDetail aRuleDetail,
    7880             :                                const RuleNodeCacheConditions aConditions)
    7881             : {
    7882         290 :   COMPUTE_START_RESET(Padding, padding, parentPadding)
    7883             : 
    7884             :   // padding: length, percent, calc, inherit
    7885             :   const nsCSSPropertyID* subprops =
    7886         145 :     nsCSSProps::SubpropertyEntryFor(eCSSProperty_padding);
    7887         290 :   nsStyleCoord coord;
    7888         725 :   NS_FOR_CSS_SIDES(side) {
    7889        1160 :     nsStyleCoord parentCoord = parentPadding->mPadding.Get(side);
    7890         580 :     if (SetCoord(*aRuleData->ValueFor(subprops[side]),
    7891             :                  coord, parentCoord,
    7892             :                  SETCOORD_LPH | SETCOORD_INITIAL_ZERO | SETCOORD_STORE_CALC |
    7893             :                    SETCOORD_UNSET_INITIAL,
    7894         580 :                  aContext, mPresContext, conditions)) {
    7895         455 :       padding->mPadding.Set(side, coord);
    7896             :     }
    7897             :   }
    7898             : 
    7899         290 :   COMPUTE_END_RESET(Padding, padding)
    7900             : }
    7901             : 
    7902             : const void*
    7903          26 : nsRuleNode::ComputeOutlineData(void* aStartStruct,
    7904             :                                const nsRuleData* aRuleData,
    7905             :                                GeckoStyleContext* aContext,
    7906             :                                nsRuleNode* aHighestNode,
    7907             :                                const RuleDetail aRuleDetail,
    7908             :                                const RuleNodeCacheConditions aConditions)
    7909             : {
    7910          52 :   COMPUTE_START_RESET(Outline, outline, parentOutline)
    7911             : 
    7912             :   // outline-width: length, enum, inherit
    7913             :   Maybe<nscoord> coord =
    7914             :     ComputeLineWidthValue<eUnsetInitial>(
    7915          26 :       *aRuleData->ValueForOutlineWidth(), parentOutline->mOutlineWidth,
    7916             :       nsPresContext::GetBorderWidthForKeyword(NS_STYLE_BORDER_WIDTH_MEDIUM),
    7917          78 :       aContext, mPresContext, conditions);
    7918          26 :   if (coord.isSome()) {
    7919           0 :     outline->mOutlineWidth = *coord;
    7920             :   }
    7921             : 
    7922             :   // outline-offset: length, inherit
    7923          52 :   nsStyleCoord tempCoord;
    7924          26 :   const nsCSSValue* outlineOffsetValue = aRuleData->ValueForOutlineOffset();
    7925          52 :   if (SetCoord(*outlineOffsetValue, tempCoord,
    7926          52 :                nsStyleCoord(parentOutline->mOutlineOffset,
    7927             :                             nsStyleCoord::CoordConstructor),
    7928             :                SETCOORD_LH | SETCOORD_INITIAL_ZERO | SETCOORD_CALC_LENGTH_ONLY |
    7929             :                  SETCOORD_UNSET_INITIAL,
    7930          26 :                aContext, mPresContext, conditions)) {
    7931           0 :     outline->mOutlineOffset = tempCoord.GetCoordValue();
    7932             :   } else {
    7933          26 :     NS_ASSERTION(outlineOffsetValue->GetUnit() == eCSSUnit_Null,
    7934             :                  "unexpected unit");
    7935             :   }
    7936             : 
    7937             :   // outline-color: color, string, enum, inherit
    7938          52 :   SetComplexColor<eUnsetInitial>(*aRuleData->ValueForOutlineColor(),
    7939             :                                  parentOutline->mOutlineColor,
    7940          52 :                                  StyleComplexColor::CurrentColor(),
    7941          26 :                                  mPresContext,
    7942          26 :                                  outline->mOutlineColor, conditions);
    7943             : 
    7944             :   // -moz-outline-radius: length, percent, inherit
    7945             :   {
    7946             :     const nsCSSPropertyID* subprops =
    7947          26 :       nsCSSProps::SubpropertyEntryFor(eCSSProperty__moz_outline_radius);
    7948         130 :     NS_FOR_CSS_FULL_CORNERS(corner) {
    7949         104 :       int cx = FullToHalfCorner(corner, false);
    7950         104 :       int cy = FullToHalfCorner(corner, true);
    7951         104 :       const nsCSSValue& radius = *aRuleData->ValueFor(subprops[corner]);
    7952         208 :       nsStyleCoord parentX = parentOutline->mOutlineRadius.Get(cx);
    7953         208 :       nsStyleCoord parentY = parentOutline->mOutlineRadius.Get(cy);
    7954         208 :       nsStyleCoord coordX, coordY;
    7955             : 
    7956         104 :       if (SetPairCoords(radius, coordX, coordY, parentX, parentY,
    7957             :                         SETCOORD_LPH | SETCOORD_INITIAL_ZERO |
    7958             :                           SETCOORD_STORE_CALC | SETCOORD_UNSET_INITIAL,
    7959         104 :                         aContext, mPresContext, conditions)) {
    7960           0 :         outline->mOutlineRadius.Set(cx, coordX);
    7961           0 :         outline->mOutlineRadius.Set(cy, coordY);
    7962             :       }
    7963             :     }
    7964             :   }
    7965             : 
    7966             :   // outline-style: enum, inherit, initial
    7967             :   // cannot use SetValue because of SetOutlineStyle
    7968          26 :   const nsCSSValue* outlineStyleValue = aRuleData->ValueForOutlineStyle();
    7969          26 :   nsCSSUnit unit = outlineStyleValue->GetUnit();
    7970          26 :   MOZ_ASSERT(eCSSUnit_None != unit && eCSSUnit_Auto != unit,
    7971             :              "'none' and 'auto' should be handled as enumerated values");
    7972          26 :   if (eCSSUnit_Enumerated == unit) {
    7973           0 :     outline->mOutlineStyle = outlineStyleValue->GetIntValue();
    7974          26 :   } else if (eCSSUnit_Initial == unit ||
    7975             :              eCSSUnit_Unset == unit) {
    7976           0 :     outline->mOutlineStyle = NS_STYLE_BORDER_STYLE_NONE;
    7977          26 :   } else if (eCSSUnit_Inherit == unit) {
    7978           0 :     conditions.SetUncacheable();
    7979           0 :     outline->mOutlineStyle = parentOutline->mOutlineStyle;
    7980             :   }
    7981             : 
    7982          26 :   outline->RecalcData();
    7983          52 :   COMPUTE_END_RESET(Outline, outline)
    7984             : }
    7985             : 
    7986             : const void*
    7987         130 : nsRuleNode::ComputeListData(void* aStartStruct,
    7988             :                             const nsRuleData* aRuleData,
    7989             :                             GeckoStyleContext* aContext,
    7990             :                             nsRuleNode* aHighestNode,
    7991             :                             const RuleDetail aRuleDetail,
    7992             :                             const RuleNodeCacheConditions aConditions)
    7993             : {
    7994         260 :   COMPUTE_START_INHERITED(List, list, parentList)
    7995             : 
    7996             :   // quotes: inherit, initial, none, [string string]+
    7997         130 :   const nsCSSValue* quotesValue = aRuleData->ValueForQuotes();
    7998         130 :   switch (quotesValue->GetUnit()) {
    7999             :   case eCSSUnit_Null:
    8000         130 :     break;
    8001             :   case eCSSUnit_Inherit:
    8002             :   case eCSSUnit_Unset:
    8003           0 :     conditions.SetUncacheable();
    8004           0 :     list->SetQuotesInherit(parentList);
    8005           0 :     break;
    8006             :   case eCSSUnit_Initial:
    8007           0 :     list->SetQuotesInitial();
    8008           0 :     break;
    8009             :   case eCSSUnit_None:
    8010           0 :     list->SetQuotesNone();
    8011           0 :     break;
    8012             :   case eCSSUnit_PairList:
    8013             :   case eCSSUnit_PairListDep: {
    8014           0 :     const nsCSSValuePairList* ourQuotes = quotesValue->GetPairListValue();
    8015             : 
    8016           0 :     nsStyleQuoteValues::QuotePairArray quotePairs;
    8017           0 :     quotePairs.SetLength(ListLength(ourQuotes));
    8018             : 
    8019           0 :     size_t index = 0;
    8020           0 :     nsAutoString buffer;
    8021           0 :     while (ourQuotes) {
    8022           0 :       MOZ_ASSERT(ourQuotes->mXValue.GetUnit() == eCSSUnit_String &&
    8023             :                  ourQuotes->mYValue.GetUnit() == eCSSUnit_String,
    8024             :                  "improper list contents for quotes");
    8025           0 :       quotePairs[index].first  = ourQuotes->mXValue.GetStringValue(buffer);
    8026           0 :       quotePairs[index].second = ourQuotes->mYValue.GetStringValue(buffer);
    8027           0 :       ++index;
    8028           0 :       ourQuotes = ourQuotes->mNext;
    8029             :     }
    8030           0 :     list->SetQuotes(Move(quotePairs));
    8031           0 :     break;
    8032             :   }
    8033             :   default:
    8034           0 :     MOZ_ASSERT(false, "unexpected value unit");
    8035             :   }
    8036             : 
    8037             :   // list-style-type: string, none, inherit, initial
    8038         130 :   const nsCSSValue* typeValue = aRuleData->ValueForListStyleType();
    8039           0 :   auto setListStyleType = [this, list](nsIAtom* type) {
    8040           0 :     list->mCounterStyle = mPresContext->
    8041           0 :       CounterStyleManager()->BuildCounterStyle(type);
    8042         130 :   };
    8043         130 :   switch (typeValue->GetUnit()) {
    8044             :     case eCSSUnit_Unset:
    8045             :     case eCSSUnit_Inherit: {
    8046           0 :       conditions.SetUncacheable();
    8047           0 :       list->mCounterStyle = parentList->mCounterStyle;
    8048           0 :       break;
    8049             :     }
    8050             :     case eCSSUnit_Initial:
    8051           0 :       setListStyleType(nsGkAtoms::disc);
    8052           0 :       break;
    8053             :     case eCSSUnit_AtomIdent: {
    8054           0 :       setListStyleType(typeValue->GetAtomValue());
    8055           0 :       break;
    8056             :     }
    8057             :     case eCSSUnit_String: {
    8058           0 :       nsString str;
    8059           0 :       typeValue->GetStringValue(str);
    8060           0 :       list->mCounterStyle = new AnonymousCounterStyle(str);
    8061           0 :       break;
    8062             :     }
    8063             :     case eCSSUnit_Enumerated: {
    8064             :       // For compatibility with html attribute map.
    8065             :       // This branch should never be called for value from CSS.
    8066           0 :       int32_t intValue = typeValue->GetIntValue();
    8067           0 :       nsCOMPtr<nsIAtom> name;
    8068           0 :       switch (intValue) {
    8069             :         case NS_STYLE_LIST_STYLE_LOWER_ROMAN:
    8070           0 :           name = nsGkAtoms::lowerRoman;
    8071           0 :           break;
    8072             :         case NS_STYLE_LIST_STYLE_UPPER_ROMAN:
    8073           0 :           name = nsGkAtoms::upperRoman;
    8074           0 :           break;
    8075             :         case NS_STYLE_LIST_STYLE_LOWER_ALPHA:
    8076           0 :           name = nsGkAtoms::lowerAlpha;
    8077           0 :           break;
    8078             :         case NS_STYLE_LIST_STYLE_UPPER_ALPHA:
    8079           0 :           name = nsGkAtoms::upperAlpha;
    8080           0 :           break;
    8081             :         default:
    8082           0 :           name = NS_Atomize(nsCSSProps::ValueToKeyword(
    8083           0 :                   intValue, nsCSSProps::kListStyleKTable));
    8084           0 :           break;
    8085             :       }
    8086           0 :       setListStyleType(name);
    8087           0 :       break;
    8088             :     }
    8089             :     case eCSSUnit_Symbols:
    8090             :       list->mCounterStyle =
    8091           0 :         new AnonymousCounterStyle(typeValue->GetArrayValue());
    8092           0 :       break;
    8093             :     case eCSSUnit_Null:
    8094         130 :       break;
    8095             :     default:
    8096           0 :       NS_NOTREACHED("Unexpected value unit");
    8097             :   }
    8098             : 
    8099             :   // list-style-image: url, none, inherit
    8100         130 :   const nsCSSValue* imageValue = aRuleData->ValueForListStyleImage();
    8101         130 :   if (eCSSUnit_Image == imageValue->GetUnit()) {
    8102         234 :     list->mListStyleImage = CreateStyleImageRequest(
    8103         234 :       mPresContext, *imageValue, nsStyleImageRequest::Mode(0));
    8104             :   }
    8105          13 :   else if (eCSSUnit_None == imageValue->GetUnit() ||
    8106           0 :            eCSSUnit_Initial == imageValue->GetUnit()) {
    8107          13 :     list->mListStyleImage = nullptr;
    8108             :   }
    8109           0 :   else if (eCSSUnit_Inherit == imageValue->GetUnit() ||
    8110           0 :            eCSSUnit_Unset == imageValue->GetUnit()) {
    8111           0 :     conditions.SetUncacheable();
    8112           0 :     list->mListStyleImage = parentList->mListStyleImage;
    8113             :   }
    8114             : 
    8115             :   // list-style-position: enum, inherit, initial
    8116         130 :   SetValue(*aRuleData->ValueForListStylePosition(),
    8117             :            list->mListStylePosition, conditions,
    8118             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    8119         130 :            parentList->mListStylePosition,
    8120         130 :            NS_STYLE_LIST_STYLE_POSITION_OUTSIDE);
    8121             : 
    8122             :   // image region property: length, auto, inherit
    8123         130 :   const nsCSSValue* imageRegionValue = aRuleData->ValueForImageRegion();
    8124         130 :   switch (imageRegionValue->GetUnit()) {
    8125             :   case eCSSUnit_Inherit:
    8126             :   case eCSSUnit_Unset:
    8127           0 :     conditions.SetUncacheable();
    8128           0 :     list->mImageRegion = parentList->mImageRegion;
    8129           0 :     break;
    8130             : 
    8131             :   case eCSSUnit_Initial:
    8132             :   case eCSSUnit_Auto:
    8133          14 :     list->mImageRegion.SetRect(0,0,0,0);
    8134          14 :     break;
    8135             : 
    8136             :   case eCSSUnit_Null:
    8137         109 :     break;
    8138             : 
    8139             :   case eCSSUnit_Rect: {
    8140           7 :     const nsCSSRect& rgnRect = imageRegionValue->GetRectValue();
    8141             : 
    8142           7 :     if (rgnRect.mTop.GetUnit() == eCSSUnit_Auto)
    8143           0 :       list->mImageRegion.y = 0;
    8144           7 :     else if (rgnRect.mTop.IsLengthUnit())
    8145           7 :       list->mImageRegion.y =
    8146           7 :         CalcLength(rgnRect.mTop, aContext, mPresContext, conditions);
    8147             : 
    8148           7 :     if (rgnRect.mBottom.GetUnit() == eCSSUnit_Auto)
    8149           0 :       list->mImageRegion.height = 0;
    8150           7 :     else if (rgnRect.mBottom.IsLengthUnit())
    8151           7 :       list->mImageRegion.height =
    8152           7 :         CalcLength(rgnRect.mBottom, aContext, mPresContext,
    8153           7 :                    conditions) - list->mImageRegion.y;
    8154             : 
    8155           7 :     if (rgnRect.mLeft.GetUnit() == eCSSUnit_Auto)
    8156           0 :       list->mImageRegion.x = 0;
    8157           7 :     else if (rgnRect.mLeft.IsLengthUnit())
    8158           7 :       list->mImageRegion.x =
    8159           7 :         CalcLength(rgnRect.mLeft, aContext, mPresContext, conditions);
    8160             : 
    8161           7 :     if (rgnRect.mRight.GetUnit() == eCSSUnit_Auto)
    8162           0 :       list->mImageRegion.width = 0;
    8163           7 :     else if (rgnRect.mRight.IsLengthUnit())
    8164           7 :       list->mImageRegion.width =
    8165           7 :         CalcLength(rgnRect.mRight, aContext, mPresContext,
    8166           7 :                    conditions) - list->mImageRegion.x;
    8167           7 :     break;
    8168             :   }
    8169             : 
    8170             :   default:
    8171           0 :     MOZ_ASSERT(false, "unrecognized image-region unit");
    8172             :   }
    8173             : 
    8174         260 :   COMPUTE_END_INHERITED(List, list)
    8175             : }
    8176             : 
    8177             : static void
    8178           0 : SetGridTrackBreadth(const nsCSSValue& aValue,
    8179             :                     nsStyleCoord& aResult,
    8180             :                     GeckoStyleContext* aStyleContext,
    8181             :                     nsPresContext* aPresContext,
    8182             :                     RuleNodeCacheConditions& aConditions)
    8183             : {
    8184           0 :   nsCSSUnit unit = aValue.GetUnit();
    8185           0 :   if (unit == eCSSUnit_FlexFraction) {
    8186           0 :     aResult.SetFlexFractionValue(aValue.GetFloatValue());
    8187           0 :   } else if (unit == eCSSUnit_Auto) {
    8188           0 :     aResult.SetAutoValue();
    8189           0 :   } else if (unit == eCSSUnit_None) {
    8190             :     // For fit-content().
    8191           0 :     aResult.SetNoneValue();
    8192             :   } else {
    8193           0 :     MOZ_ASSERT(unit != eCSSUnit_Inherit && unit != eCSSUnit_Unset,
    8194             :                "Unexpected value that would use dummyParentCoord");
    8195           0 :     const nsStyleCoord dummyParentCoord;
    8196             :     DebugOnly<bool> stored =
    8197           0 :       SetCoord(aValue, aResult, dummyParentCoord,
    8198             :                SETCOORD_LPE | SETCOORD_STORE_CALC,
    8199           0 :                aStyleContext, aPresContext, aConditions);
    8200           0 :     MOZ_ASSERT(stored, "invalid <track-size> value");
    8201             :   }
    8202           0 : }
    8203             : 
    8204             : static void
    8205           0 : SetGridTrackSize(const nsCSSValue& aValue,
    8206             :                  nsStyleCoord& aResultMin,
    8207             :                  nsStyleCoord& aResultMax,
    8208             :                  GeckoStyleContext* aStyleContext,
    8209             :                  nsPresContext* aPresContext,
    8210             :                  RuleNodeCacheConditions& aConditions)
    8211             : {
    8212           0 :   if (aValue.GetUnit() == eCSSUnit_Function) {
    8213           0 :     nsCSSValue::Array* func = aValue.GetArrayValue();
    8214           0 :     auto funcName = func->Item(0).GetKeywordValue();
    8215           0 :     if (funcName == eCSSKeyword_minmax) {
    8216           0 :       SetGridTrackBreadth(func->Item(1), aResultMin,
    8217           0 :                           aStyleContext, aPresContext, aConditions);
    8218           0 :       SetGridTrackBreadth(func->Item(2), aResultMax,
    8219           0 :                           aStyleContext, aPresContext, aConditions);
    8220           0 :     } else if (funcName == eCSSKeyword_fit_content) {
    8221             :       // We represent fit-content(L) as 'none' min-sizing and L max-sizing.
    8222           0 :       SetGridTrackBreadth(nsCSSValue(eCSSUnit_None), aResultMin,
    8223           0 :                           aStyleContext, aPresContext, aConditions);
    8224           0 :       SetGridTrackBreadth(func->Item(1), aResultMax,
    8225           0 :                           aStyleContext, aPresContext, aConditions);
    8226             :     } else {
    8227           0 :       NS_ERROR("Expected minmax() or fit-content(), got another function name");
    8228             :     }
    8229             :   } else {
    8230             :     // A single <track-breadth>,
    8231             :     // specifies identical min and max sizing functions.
    8232             :     SetGridTrackBreadth(aValue, aResultMin,
    8233           0 :                         aStyleContext, aPresContext, aConditions);
    8234           0 :     aResultMax = aResultMin;
    8235             :   }
    8236           0 : }
    8237             : 
    8238             : static void
    8239         562 : SetGridAutoColumnsRows(const nsCSSValue& aValue,
    8240             :                        nsStyleCoord& aResultMin,
    8241             :                        nsStyleCoord& aResultMax,
    8242             :                        const nsStyleCoord& aParentValueMin,
    8243             :                        const nsStyleCoord& aParentValueMax,
    8244             :                        GeckoStyleContext* aStyleContext,
    8245             :                        nsPresContext* aPresContext,
    8246             :                        RuleNodeCacheConditions& aConditions)
    8247             : 
    8248             : {
    8249         562 :   switch (aValue.GetUnit()) {
    8250             :   case eCSSUnit_Null:
    8251         464 :     break;
    8252             : 
    8253             :   case eCSSUnit_Inherit:
    8254          98 :     aConditions.SetUncacheable();
    8255          98 :     aResultMin = aParentValueMin;
    8256          98 :     aResultMax = aParentValueMax;
    8257          98 :     break;
    8258             : 
    8259             :   case eCSSUnit_Initial:
    8260             :   case eCSSUnit_Unset:
    8261             :     // The initial value is 'auto',
    8262             :     // which computes to 'minmax(auto, auto)'.
    8263             :     // (Explicitly-specified 'auto' values are handled in SetGridTrackSize.)
    8264           0 :     aResultMin.SetAutoValue();
    8265           0 :     aResultMax.SetAutoValue();
    8266           0 :     break;
    8267             : 
    8268             :   default:
    8269             :     SetGridTrackSize(aValue, aResultMin, aResultMax,
    8270           0 :                      aStyleContext, aPresContext, aConditions);
    8271             :   }
    8272         562 : }
    8273             : 
    8274             : static void
    8275           0 : AppendGridLineNames(const nsCSSValue& aValue,
    8276             :                     nsTArray<nsString>& aNameList)
    8277             : {
    8278             :   // Compute a <line-names> value
    8279             :   // Null unit means empty list, nothing more to do.
    8280           0 :   if (aValue.GetUnit() != eCSSUnit_Null) {
    8281           0 :     const nsCSSValueList* item = aValue.GetListValue();
    8282           0 :     do {
    8283           0 :       nsString* name = aNameList.AppendElement();
    8284           0 :       item->mValue.GetStringValue(*name);
    8285           0 :       item = item->mNext;
    8286           0 :     } while (item);
    8287             :   }
    8288           0 : }
    8289             : 
    8290             : static void
    8291         562 : SetGridTrackList(const nsCSSValue& aValue,
    8292             :                  nsStyleGridTemplate& aResult,
    8293             :                  const nsStyleGridTemplate& aParentValue,
    8294             :                  GeckoStyleContext* aStyleContext,
    8295             :                  nsPresContext* aPresContext,
    8296             :                  RuleNodeCacheConditions& aConditions)
    8297             : 
    8298             : {
    8299         562 :   switch (aValue.GetUnit()) {
    8300             :   case eCSSUnit_Null:
    8301         464 :     break;
    8302             : 
    8303             :   case eCSSUnit_Inherit:
    8304          98 :     aConditions.SetUncacheable();
    8305          98 :     aResult = aParentValue;
    8306          98 :     break;
    8307             : 
    8308             :   case eCSSUnit_Initial:
    8309             :   case eCSSUnit_Unset:
    8310             :   case eCSSUnit_None:
    8311           0 :     aResult.mIsSubgrid = false;
    8312           0 :     aResult.mLineNameLists.Clear();
    8313           0 :     aResult.mMinTrackSizingFunctions.Clear();
    8314           0 :     aResult.mMaxTrackSizingFunctions.Clear();
    8315           0 :     aResult.mRepeatAutoLineNameListBefore.Clear();
    8316           0 :     aResult.mRepeatAutoLineNameListAfter.Clear();
    8317           0 :     aResult.mRepeatAutoIndex = -1;
    8318           0 :     aResult.mIsAutoFill = false;
    8319           0 :     break;
    8320             : 
    8321             :   default:
    8322           0 :     aResult.mLineNameLists.Clear();
    8323           0 :     aResult.mMinTrackSizingFunctions.Clear();
    8324           0 :     aResult.mMaxTrackSizingFunctions.Clear();
    8325           0 :     aResult.mRepeatAutoLineNameListBefore.Clear();
    8326           0 :     aResult.mRepeatAutoLineNameListAfter.Clear();
    8327           0 :     aResult.mRepeatAutoIndex = -1;
    8328           0 :     aResult.mIsAutoFill = false;
    8329           0 :     const nsCSSValueList* item = aValue.GetListValue();
    8330           0 :     if (item->mValue.GetUnit() == eCSSUnit_Enumerated &&
    8331           0 :         item->mValue.GetIntValue() == NS_STYLE_GRID_TEMPLATE_SUBGRID) {
    8332             :       // subgrid <line-name-list>?
    8333           0 :       aResult.mIsSubgrid = true;
    8334           0 :       item = item->mNext;
    8335           0 :       for (int32_t i = 0; item && i < nsStyleGridLine::kMaxLine; ++i) {
    8336           0 :         if (item->mValue.GetUnit() == eCSSUnit_Pair) {
    8337             :           // This is a 'auto-fill' <name-repeat> expression.
    8338           0 :           const nsCSSValuePair& pair = item->mValue.GetPairValue();
    8339           0 :           MOZ_ASSERT(aResult.mRepeatAutoIndex == -1,
    8340             :                      "can only have one <name-repeat> with auto-fill");
    8341           0 :           aResult.mRepeatAutoIndex = i;
    8342           0 :           aResult.mIsAutoFill = true;
    8343           0 :           MOZ_ASSERT(pair.mXValue.GetIntValue() == NS_STYLE_GRID_REPEAT_AUTO_FILL,
    8344             :                      "unexpected repeat() enum value for subgrid");
    8345           0 :           const nsCSSValueList* list = pair.mYValue.GetListValue();
    8346           0 :           AppendGridLineNames(list->mValue, aResult.mRepeatAutoLineNameListBefore);
    8347             :         } else {
    8348           0 :           AppendGridLineNames(item->mValue,
    8349           0 :                               *aResult.mLineNameLists.AppendElement());
    8350             :         }
    8351           0 :         item = item->mNext;
    8352             :       }
    8353             :     } else {
    8354             :       // <track-list>
    8355             :       // The list is expected to have odd number of items, at least 3
    8356             :       // starting with a <line-names> (sub list of identifiers),
    8357             :       // and alternating between that and <track-size>.
    8358           0 :       aResult.mIsSubgrid = false;
    8359           0 :       for (int32_t line = 1;  ; ++line) {
    8360           0 :         AppendGridLineNames(item->mValue,
    8361           0 :                             *aResult.mLineNameLists.AppendElement());
    8362           0 :         item = item->mNext;
    8363             : 
    8364           0 :         if (!item || line == nsStyleGridLine::kMaxLine) {
    8365             :           break;
    8366             :         }
    8367             : 
    8368           0 :         if (item->mValue.GetUnit() == eCSSUnit_Pair) {
    8369             :           // This is a 'auto-fill' / 'auto-fit' <auto-repeat> expression.
    8370           0 :           const nsCSSValuePair& pair = item->mValue.GetPairValue();
    8371           0 :           MOZ_ASSERT(aResult.mRepeatAutoIndex == -1,
    8372             :                      "can only have one <auto-repeat>");
    8373           0 :           aResult.mRepeatAutoIndex = line - 1;
    8374           0 :           switch (pair.mXValue.GetIntValue()) {
    8375             :             case NS_STYLE_GRID_REPEAT_AUTO_FILL:
    8376           0 :               aResult.mIsAutoFill = true;
    8377           0 :               break;
    8378             :             case NS_STYLE_GRID_REPEAT_AUTO_FIT:
    8379           0 :               aResult.mIsAutoFill = false;
    8380           0 :               break;
    8381             :             default:
    8382           0 :               MOZ_ASSERT_UNREACHABLE("unexpected repeat() enum value");
    8383             :           }
    8384           0 :           const nsCSSValueList* list = pair.mYValue.GetListValue();
    8385           0 :           AppendGridLineNames(list->mValue, aResult.mRepeatAutoLineNameListBefore);
    8386           0 :           list = list->mNext;
    8387           0 :           nsStyleCoord& min = *aResult.mMinTrackSizingFunctions.AppendElement();
    8388           0 :           nsStyleCoord& max = *aResult.mMaxTrackSizingFunctions.AppendElement();
    8389           0 :           SetGridTrackSize(list->mValue, min, max,
    8390           0 :                            aStyleContext, aPresContext, aConditions);
    8391           0 :           list = list->mNext;
    8392           0 :           AppendGridLineNames(list->mValue, aResult.mRepeatAutoLineNameListAfter);
    8393             :         } else {
    8394           0 :           nsStyleCoord& min = *aResult.mMinTrackSizingFunctions.AppendElement();
    8395           0 :           nsStyleCoord& max = *aResult.mMaxTrackSizingFunctions.AppendElement();
    8396           0 :           SetGridTrackSize(item->mValue, min, max,
    8397           0 :                            aStyleContext, aPresContext, aConditions);
    8398             :         }
    8399             : 
    8400           0 :         item = item->mNext;
    8401           0 :         MOZ_ASSERT(item, "Expected a eCSSUnit_List of odd length");
    8402           0 :       }
    8403           0 :       MOZ_ASSERT(!aResult.mMinTrackSizingFunctions.IsEmpty() &&
    8404             :                  aResult.mMinTrackSizingFunctions.Length() ==
    8405             :                  aResult.mMaxTrackSizingFunctions.Length() &&
    8406             :                  aResult.mMinTrackSizingFunctions.Length() + 1 ==
    8407             :                  aResult.mLineNameLists.Length(),
    8408             :                  "Inconstistent array lengths for nsStyleGridTemplate");
    8409             :     }
    8410             :   }
    8411         562 : }
    8412             : 
    8413             : static void
    8414         281 : SetGridTemplateAreas(const nsCSSValue& aValue,
    8415             :                      RefPtr<css::GridTemplateAreasValue>* aResult,
    8416             :                      css::GridTemplateAreasValue* aParentValue,
    8417             :                      RuleNodeCacheConditions& aConditions)
    8418             : {
    8419         281 :   switch (aValue.GetUnit()) {
    8420             :   case eCSSUnit_Null:
    8421         232 :     break;
    8422             : 
    8423             :   case eCSSUnit_Inherit:
    8424          49 :     aConditions.SetUncacheable();
    8425          49 :     *aResult = aParentValue;
    8426          49 :     break;
    8427             : 
    8428             :   case eCSSUnit_Initial:
    8429             :   case eCSSUnit_Unset:
    8430             :   case eCSSUnit_None:
    8431           0 :     *aResult = nullptr;
    8432           0 :     break;
    8433             : 
    8434             :   default:
    8435           0 :     *aResult = aValue.GetGridTemplateAreas();
    8436             :   }
    8437         281 : }
    8438             : 
    8439             : static void
    8440        1124 : SetGridLine(const nsCSSValue& aValue,
    8441             :             nsStyleGridLine& aResult,
    8442             :             const nsStyleGridLine& aParentValue,
    8443             :             RuleNodeCacheConditions& aConditions)
    8444             : 
    8445             : {
    8446        1124 :   switch (aValue.GetUnit()) {
    8447             :   case eCSSUnit_Null:
    8448        1124 :     break;
    8449             : 
    8450             :   case eCSSUnit_Inherit:
    8451           0 :     aConditions.SetUncacheable();
    8452           0 :     aResult = aParentValue;
    8453           0 :     break;
    8454             : 
    8455             :   case eCSSUnit_Initial:
    8456             :   case eCSSUnit_Unset:
    8457             :   case eCSSUnit_Auto:
    8458           0 :     aResult.SetAuto();
    8459           0 :     break;
    8460             : 
    8461             :   default:
    8462           0 :     aResult.SetAuto();  // Reset any existing value.
    8463           0 :     const nsCSSValueList* item = aValue.GetListValue();
    8464           0 :     do {
    8465           0 :       if (item->mValue.GetUnit() == eCSSUnit_Enumerated) {
    8466           0 :         aResult.mHasSpan = true;
    8467           0 :       } else if (item->mValue.GetUnit() == eCSSUnit_Integer) {
    8468           0 :         aResult.mInteger = clamped(item->mValue.GetIntValue(),
    8469             :                                    nsStyleGridLine::kMinLine,
    8470           0 :                                    nsStyleGridLine::kMaxLine);
    8471           0 :       } else if (item->mValue.GetUnit() == eCSSUnit_Ident) {
    8472           0 :         item->mValue.GetStringValue(aResult.mLineName);
    8473             :       } else {
    8474           0 :         NS_ASSERTION(false, "Unexpected unit");
    8475             :       }
    8476           0 :       item = item->mNext;
    8477           0 :     } while (item);
    8478           0 :     MOZ_ASSERT(!aResult.IsAuto(),
    8479             :                "should have set something away from default value");
    8480             :   }
    8481        1124 : }
    8482             : 
    8483             : const void*
    8484         281 : nsRuleNode::ComputePositionData(void* aStartStruct,
    8485             :                                 const nsRuleData* aRuleData,
    8486             :                                 GeckoStyleContext* aContext,
    8487             :                                 nsRuleNode* aHighestNode,
    8488             :                                 const RuleDetail aRuleDetail,
    8489             :                                 const RuleNodeCacheConditions aConditions)
    8490             : {
    8491         562 :   COMPUTE_START_RESET(Position, pos, parentPos)
    8492             : 
    8493             :   // box offsets: length, percent, calc, auto, inherit
    8494             :   static const nsCSSPropertyID offsetProps[] = {
    8495             :     eCSSProperty_top,
    8496             :     eCSSProperty_right,
    8497             :     eCSSProperty_bottom,
    8498             :     eCSSProperty_left
    8499             :   };
    8500         562 :   nsStyleCoord  coord;
    8501        1405 :   NS_FOR_CSS_SIDES(side) {
    8502        2248 :     nsStyleCoord parentCoord = parentPos->mOffset.Get(side);
    8503        1124 :     if (SetCoord(*aRuleData->ValueFor(offsetProps[side]),
    8504             :                  coord, parentCoord,
    8505             :                  SETCOORD_LPAH | SETCOORD_INITIAL_AUTO | SETCOORD_STORE_CALC |
    8506             :                    SETCOORD_UNSET_INITIAL,
    8507        1124 :                  aContext, mPresContext, conditions)) {
    8508           2 :       pos->mOffset.Set(side, coord);
    8509             :     }
    8510             :   }
    8511             : 
    8512             :   // We allow the enumerated box size property values -moz-min-content, etc. to
    8513             :   // be specified on both the {,min-,max-}width properties and the
    8514             :   // {,min-,max-}height properties, regardless of the writing mode.  This is
    8515             :   // because the writing mode is not determined until here, at computed value
    8516             :   // time.  Since we do not support layout behavior of these keywords on the
    8517             :   // block-axis properties, we turn them into unset if we find them in
    8518             :   // that case.
    8519             : 
    8520         281 :   WritingMode wm(aContext);
    8521         281 :   bool vertical = wm.IsVertical();
    8522             : 
    8523         281 :   const nsCSSValue* width = aRuleData->ValueForWidth();
    8524         281 :   if (width->GetUnit() == eCSSUnit_Enumerated) {
    8525           0 :     conditions.SetWritingModeDependency(wm.GetBits());
    8526             :   }
    8527         562 :   SetCoord(width->GetUnit() == eCSSUnit_Enumerated && vertical ?
    8528             :              nsCSSValue(eCSSUnit_Unset) : *width,
    8529             :            pos->mWidth, parentPos->mWidth,
    8530             :            SETCOORD_LPAEH | SETCOORD_INITIAL_AUTO | SETCOORD_STORE_CALC |
    8531             :              SETCOORD_UNSET_INITIAL,
    8532         562 :            aContext, mPresContext, conditions);
    8533             : 
    8534         281 :   const nsCSSValue* minWidth = aRuleData->ValueForMinWidth();
    8535         281 :   if (minWidth->GetUnit() == eCSSUnit_Enumerated) {
    8536           0 :     conditions.SetWritingModeDependency(wm.GetBits());
    8537             :   }
    8538         562 :   SetCoord(minWidth->GetUnit() == eCSSUnit_Enumerated && vertical ?
    8539             :              nsCSSValue(eCSSUnit_Unset) : *minWidth,
    8540             :            pos->mMinWidth, parentPos->mMinWidth,
    8541             :            SETCOORD_LPAEH | SETCOORD_INITIAL_AUTO | SETCOORD_STORE_CALC |
    8542             :              SETCOORD_UNSET_INITIAL,
    8543         562 :            aContext, mPresContext, conditions);
    8544             : 
    8545         281 :   const nsCSSValue* maxWidth = aRuleData->ValueForMaxWidth();
    8546         281 :   if (maxWidth->GetUnit() == eCSSUnit_Enumerated) {
    8547           0 :     conditions.SetWritingModeDependency(wm.GetBits());
    8548             :   }
    8549         562 :   SetCoord(maxWidth->GetUnit() == eCSSUnit_Enumerated && vertical ?
    8550             :              nsCSSValue(eCSSUnit_Unset) : *maxWidth,
    8551             :            pos->mMaxWidth, parentPos->mMaxWidth,
    8552             :            SETCOORD_LPOEH | SETCOORD_INITIAL_NONE | SETCOORD_STORE_CALC |
    8553             :              SETCOORD_UNSET_INITIAL,
    8554         562 :            aContext, mPresContext, conditions);
    8555             : 
    8556         281 :   const nsCSSValue* height = aRuleData->ValueForHeight();
    8557         281 :   if (height->GetUnit() == eCSSUnit_Enumerated) {
    8558           0 :     conditions.SetWritingModeDependency(wm.GetBits());
    8559             :   }
    8560         562 :   SetCoord(height->GetUnit() == eCSSUnit_Enumerated && !vertical ?
    8561             :              nsCSSValue(eCSSUnit_Unset) : *height,
    8562             :            pos->mHeight, parentPos->mHeight,
    8563             :            SETCOORD_LPAEH | SETCOORD_INITIAL_AUTO | SETCOORD_STORE_CALC |
    8564             :              SETCOORD_UNSET_INITIAL,
    8565         562 :            aContext, mPresContext, conditions);
    8566             : 
    8567         281 :   const nsCSSValue* minHeight = aRuleData->ValueForMinHeight();
    8568         281 :   if (minHeight->GetUnit() == eCSSUnit_Enumerated) {
    8569           0 :     conditions.SetWritingModeDependency(wm.GetBits());
    8570             :   }
    8571         562 :   SetCoord(minHeight->GetUnit() == eCSSUnit_Enumerated && !vertical ?
    8572             :              nsCSSValue(eCSSUnit_Unset) : *minHeight,
    8573             :            pos->mMinHeight, parentPos->mMinHeight,
    8574             :            SETCOORD_LPAEH | SETCOORD_INITIAL_AUTO | SETCOORD_STORE_CALC |
    8575             :              SETCOORD_UNSET_INITIAL,
    8576         562 :            aContext, mPresContext, conditions);
    8577             : 
    8578         281 :   const nsCSSValue* maxHeight = aRuleData->ValueForMaxHeight();
    8579         281 :   if (maxHeight->GetUnit() == eCSSUnit_Enumerated) {
    8580           0 :     conditions.SetWritingModeDependency(wm.GetBits());
    8581             :   }
    8582         562 :   SetCoord(maxHeight->GetUnit() == eCSSUnit_Enumerated && !vertical ?
    8583             :              nsCSSValue(eCSSUnit_Unset) : *maxHeight,
    8584             :            pos->mMaxHeight, parentPos->mMaxHeight,
    8585             :            SETCOORD_LPOEH | SETCOORD_INITIAL_NONE | SETCOORD_STORE_CALC |
    8586             :              SETCOORD_UNSET_INITIAL,
    8587         562 :            aContext, mPresContext, conditions);
    8588             : 
    8589             :   // box-sizing: enum, inherit, initial
    8590         281 :   SetValue(*aRuleData->ValueForBoxSizing(),
    8591             :            pos->mBoxSizing, conditions,
    8592             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    8593         281 :            parentPos->mBoxSizing,
    8594         281 :            StyleBoxSizing::Content);
    8595             : 
    8596             :   // align-content: enum, inherit, initial
    8597         281 :   SetValue(*aRuleData->ValueForAlignContent(),
    8598             :            pos->mAlignContent, conditions,
    8599             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    8600         281 :            parentPos->mAlignContent,
    8601         281 :            NS_STYLE_ALIGN_NORMAL);
    8602             : 
    8603             :   // align-items: enum, inherit, initial
    8604         281 :   SetValue(*aRuleData->ValueForAlignItems(),
    8605             :            pos->mAlignItems, conditions,
    8606             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    8607         281 :            parentPos->mAlignItems,
    8608         281 :            NS_STYLE_ALIGN_NORMAL);
    8609             : 
    8610             :   // align-self: enum, inherit, initial
    8611         281 :   SetValue(*aRuleData->ValueForAlignSelf(),
    8612             :            pos->mAlignSelf, conditions,
    8613             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    8614         281 :            parentPos->mAlignSelf,
    8615         281 :            NS_STYLE_ALIGN_AUTO);
    8616             : 
    8617             :   // justify-content: enum, inherit, initial
    8618         281 :   SetValue(*aRuleData->ValueForJustifyContent(),
    8619             :            pos->mJustifyContent, conditions,
    8620             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    8621         281 :            parentPos->mJustifyContent,
    8622         281 :            NS_STYLE_JUSTIFY_NORMAL);
    8623             : 
    8624             :   // justify-items: enum, inherit, initial
    8625         281 :   const auto& justifyItemsValue = *aRuleData->ValueForJustifyItems();
    8626         281 :   if (MOZ_UNLIKELY(justifyItemsValue.GetUnit() == eCSSUnit_Inherit)) {
    8627          49 :     if (MOZ_LIKELY(parentContext)) {
    8628          49 :       pos->mJustifyItems =
    8629          49 :         parentPos->ComputedJustifyItems(parentContext->GetParentAllowServo());
    8630             :     } else {
    8631           0 :       pos->mJustifyItems = NS_STYLE_JUSTIFY_NORMAL;
    8632             :     }
    8633          49 :     conditions.SetUncacheable();
    8634             :   } else {
    8635         232 :     SetValue(justifyItemsValue,
    8636             :              pos->mJustifyItems, conditions,
    8637             :              SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    8638         232 :              parentPos->mJustifyItems, // unused, we handle 'inherit' above
    8639         232 :              NS_STYLE_JUSTIFY_AUTO);
    8640             :   }
    8641             : 
    8642             :   // justify-self: enum, inherit, initial
    8643         281 :   SetValue(*aRuleData->ValueForJustifySelf(),
    8644             :            pos->mJustifySelf, conditions,
    8645             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    8646         281 :            parentPos->mJustifySelf,
    8647         281 :            NS_STYLE_JUSTIFY_AUTO);
    8648             : 
    8649             :   // flex-basis: auto, length, percent, enum, calc, inherit, initial
    8650             :   // (Note: The flags here should match those used for 'width' property above.)
    8651         281 :   SetCoord(*aRuleData->ValueForFlexBasis(), pos->mFlexBasis, parentPos->mFlexBasis,
    8652             :            SETCOORD_LPAEH | SETCOORD_INITIAL_AUTO | SETCOORD_STORE_CALC |
    8653             :              SETCOORD_UNSET_INITIAL,
    8654         562 :            aContext, mPresContext, conditions);
    8655             : 
    8656             :   // flex-direction: enum, inherit, initial
    8657         281 :   SetValue(*aRuleData->ValueForFlexDirection(),
    8658             :            pos->mFlexDirection, conditions,
    8659             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    8660         281 :            parentPos->mFlexDirection,
    8661         281 :            NS_STYLE_FLEX_DIRECTION_ROW);
    8662             : 
    8663             :   // flex-grow: float, inherit, initial
    8664         281 :   SetFactor(*aRuleData->ValueForFlexGrow(),
    8665             :             pos->mFlexGrow, conditions,
    8666         281 :             parentPos->mFlexGrow, 0.0f,
    8667         281 :             SETFCT_UNSET_INITIAL);
    8668             : 
    8669             :   // flex-shrink: float, inherit, initial
    8670         281 :   SetFactor(*aRuleData->ValueForFlexShrink(),
    8671             :             pos->mFlexShrink, conditions,
    8672         281 :             parentPos->mFlexShrink, 1.0f,
    8673         281 :             SETFCT_UNSET_INITIAL);
    8674             : 
    8675             :   // flex-wrap: enum, inherit, initial
    8676         281 :   SetValue(*aRuleData->ValueForFlexWrap(),
    8677             :            pos->mFlexWrap, conditions,
    8678             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    8679         281 :            parentPos->mFlexWrap,
    8680         281 :            NS_STYLE_FLEX_WRAP_NOWRAP);
    8681             : 
    8682             :   // order: integer, inherit, initial
    8683         281 :   SetValue(*aRuleData->ValueForOrder(),
    8684             :            pos->mOrder, conditions,
    8685             :            SETVAL_INTEGER | SETVAL_UNSET_INITIAL,
    8686         281 :            parentPos->mOrder,
    8687         281 :            NS_STYLE_ORDER_INITIAL);
    8688             : 
    8689             :   // object-fit: enum, inherit, initial
    8690         281 :   SetValue(*aRuleData->ValueForObjectFit(),
    8691             :            pos->mObjectFit, conditions,
    8692             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    8693         281 :            parentPos->mObjectFit,
    8694         281 :            NS_STYLE_OBJECT_FIT_FILL);
    8695             : 
    8696             :   // object-position
    8697         281 :   const nsCSSValue& objectPosition = *aRuleData->ValueForObjectPosition();
    8698         281 :   switch (objectPosition.GetUnit()) {
    8699             :     case eCSSUnit_Null:
    8700         281 :       break;
    8701             :     case eCSSUnit_Inherit:
    8702           0 :       conditions.SetUncacheable();
    8703           0 :       pos->mObjectPosition = parentPos->mObjectPosition;
    8704           0 :       break;
    8705             :     case eCSSUnit_Initial:
    8706             :     case eCSSUnit_Unset:
    8707           0 :       pos->mObjectPosition.SetInitialPercentValues(0.5f);
    8708           0 :       break;
    8709             :     default:
    8710           0 :       ComputePositionValue(aContext, objectPosition,
    8711           0 :                            pos->mObjectPosition, conditions);
    8712             :   }
    8713             : 
    8714             :   // grid-auto-flow
    8715         281 :   const nsCSSValue& gridAutoFlow = *aRuleData->ValueForGridAutoFlow();
    8716         281 :   switch (gridAutoFlow.GetUnit()) {
    8717             :     case eCSSUnit_Null:
    8718         232 :       break;
    8719             :     case eCSSUnit_Inherit:
    8720          49 :       conditions.SetUncacheable();
    8721          49 :       pos->mGridAutoFlow = parentPos->mGridAutoFlow;
    8722          49 :       break;
    8723             :     case eCSSUnit_Initial:
    8724             :     case eCSSUnit_Unset:
    8725           0 :       pos->mGridAutoFlow = NS_STYLE_GRID_AUTO_FLOW_ROW;
    8726           0 :       break;
    8727             :     default:
    8728           0 :       NS_ASSERTION(gridAutoFlow.GetUnit() == eCSSUnit_Enumerated,
    8729             :                    "Unexpected unit");
    8730           0 :       pos->mGridAutoFlow = gridAutoFlow.GetIntValue();
    8731             :   }
    8732             : 
    8733             :   // grid-auto-columns
    8734         281 :   SetGridAutoColumnsRows(*aRuleData->ValueForGridAutoColumns(),
    8735             :                          pos->mGridAutoColumnsMin,
    8736             :                          pos->mGridAutoColumnsMax,
    8737             :                          parentPos->mGridAutoColumnsMin,
    8738             :                          parentPos->mGridAutoColumnsMax,
    8739         562 :                          aContext, mPresContext, conditions);
    8740             : 
    8741             :   // grid-auto-rows
    8742         281 :   SetGridAutoColumnsRows(*aRuleData->ValueForGridAutoRows(),
    8743             :                          pos->mGridAutoRowsMin,
    8744             :                          pos->mGridAutoRowsMax,
    8745             :                          parentPos->mGridAutoRowsMin,
    8746             :                          parentPos->mGridAutoRowsMax,
    8747         562 :                          aContext, mPresContext, conditions);
    8748             : 
    8749             :   // grid-template-columns
    8750         281 :   SetGridTrackList(*aRuleData->ValueForGridTemplateColumns(),
    8751             :                    pos->mGridTemplateColumns, parentPos->mGridTemplateColumns,
    8752         562 :                    aContext, mPresContext, conditions);
    8753             : 
    8754             :   // grid-template-rows
    8755         281 :   SetGridTrackList(*aRuleData->ValueForGridTemplateRows(),
    8756             :                    pos->mGridTemplateRows, parentPos->mGridTemplateRows,
    8757         562 :                    aContext, mPresContext, conditions);
    8758             : 
    8759             :   // grid-tempate-areas
    8760         281 :   SetGridTemplateAreas(*aRuleData->ValueForGridTemplateAreas(),
    8761             :                        &pos->mGridTemplateAreas,
    8762             :                        parentPos->mGridTemplateAreas,
    8763         281 :                        conditions);
    8764             : 
    8765             :   // grid-column-start
    8766         281 :   SetGridLine(*aRuleData->ValueForGridColumnStart(),
    8767             :               pos->mGridColumnStart,
    8768             :               parentPos->mGridColumnStart,
    8769         281 :               conditions);
    8770             : 
    8771             :   // grid-column-end
    8772         281 :   SetGridLine(*aRuleData->ValueForGridColumnEnd(),
    8773             :               pos->mGridColumnEnd,
    8774             :               parentPos->mGridColumnEnd,
    8775         281 :               conditions);
    8776             : 
    8777             :   // grid-row-start
    8778         281 :   SetGridLine(*aRuleData->ValueForGridRowStart(),
    8779             :               pos->mGridRowStart,
    8780             :               parentPos->mGridRowStart,
    8781         281 :               conditions);
    8782             : 
    8783             :   // grid-row-end
    8784         281 :   SetGridLine(*aRuleData->ValueForGridRowEnd(),
    8785             :               pos->mGridRowEnd,
    8786             :               parentPos->mGridRowEnd,
    8787         281 :               conditions);
    8788             : 
    8789             :   // grid-column-gap
    8790         281 :   if (SetCoord(*aRuleData->ValueForGridColumnGap(),
    8791             :                pos->mGridColumnGap, parentPos->mGridColumnGap,
    8792             :                SETCOORD_LPH | SETCOORD_INITIAL_ZERO | SETCOORD_STORE_CALC |
    8793             :                SETCOORD_CALC_CLAMP_NONNEGATIVE | SETCOORD_UNSET_INITIAL,
    8794         281 :                aContext, mPresContext, conditions)) {
    8795             :   } else {
    8796         232 :     MOZ_ASSERT(aRuleData->ValueForGridColumnGap()->GetUnit() == eCSSUnit_Null,
    8797             :                "unexpected unit");
    8798             :   }
    8799             : 
    8800             :   // grid-row-gap
    8801         281 :   if (SetCoord(*aRuleData->ValueForGridRowGap(),
    8802             :                pos->mGridRowGap, parentPos->mGridRowGap,
    8803             :                SETCOORD_LPH | SETCOORD_INITIAL_ZERO | SETCOORD_STORE_CALC |
    8804             :                SETCOORD_CALC_CLAMP_NONNEGATIVE | SETCOORD_UNSET_INITIAL,
    8805         281 :                aContext, mPresContext, conditions)) {
    8806             :   } else {
    8807         232 :     MOZ_ASSERT(aRuleData->ValueForGridRowGap()->GetUnit() == eCSSUnit_Null,
    8808             :                "unexpected unit");
    8809             :   }
    8810             : 
    8811             :   // z-index
    8812         281 :   const nsCSSValue* zIndexValue = aRuleData->ValueForZIndex();
    8813         281 :   if (! SetCoord(*zIndexValue, pos->mZIndex, parentPos->mZIndex,
    8814             :                  SETCOORD_IA | SETCOORD_INITIAL_AUTO | SETCOORD_UNSET_INITIAL,
    8815             :                  aContext, nullptr, conditions)) {
    8816         261 :     if (eCSSUnit_Inherit == zIndexValue->GetUnit()) {
    8817             :       // handle inherit, because it's ok to inherit 'auto' here
    8818           0 :       conditions.SetUncacheable();
    8819           0 :       pos->mZIndex = parentPos->mZIndex;
    8820             :     }
    8821             :   }
    8822             : 
    8823         562 :   COMPUTE_END_RESET(Position, pos)
    8824             : }
    8825             : 
    8826             : const void*
    8827           0 : nsRuleNode::ComputeTableData(void* aStartStruct,
    8828             :                              const nsRuleData* aRuleData,
    8829             :                              GeckoStyleContext* aContext,
    8830             :                              nsRuleNode* aHighestNode,
    8831             :                              const RuleDetail aRuleDetail,
    8832             :                              const RuleNodeCacheConditions aConditions)
    8833             : {
    8834           0 :   COMPUTE_START_RESET(Table, table, parentTable)
    8835             : 
    8836             :   // table-layout: enum, inherit, initial
    8837           0 :   SetValue(*aRuleData->ValueForTableLayout(),
    8838             :            table->mLayoutStrategy, conditions,
    8839             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    8840           0 :            parentTable->mLayoutStrategy,
    8841           0 :            NS_STYLE_TABLE_LAYOUT_AUTO);
    8842             : 
    8843             :   // span: pixels (not a real CSS prop)
    8844           0 :   const nsCSSValue* spanValue = aRuleData->ValueForSpan();
    8845           0 :   if (eCSSUnit_Enumerated == spanValue->GetUnit() ||
    8846           0 :       eCSSUnit_Integer == spanValue->GetUnit())
    8847           0 :     table->mSpan = spanValue->GetIntValue();
    8848             : 
    8849           0 :   COMPUTE_END_RESET(Table, table)
    8850             : }
    8851             : 
    8852             : const void*
    8853           0 : nsRuleNode::ComputeTableBorderData(void* aStartStruct,
    8854             :                                    const nsRuleData* aRuleData,
    8855             :                                    GeckoStyleContext* aContext,
    8856             :                                    nsRuleNode* aHighestNode,
    8857             :                                    const RuleDetail aRuleDetail,
    8858             :                                    const RuleNodeCacheConditions aConditions)
    8859             : {
    8860           0 :   COMPUTE_START_INHERITED(TableBorder, table, parentTable)
    8861             : 
    8862             :   // border-collapse: enum, inherit, initial
    8863           0 :   SetValue(*aRuleData->ValueForBorderCollapse(), table->mBorderCollapse,
    8864             :            conditions,
    8865             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    8866           0 :            parentTable->mBorderCollapse,
    8867           0 :            NS_STYLE_BORDER_SEPARATE);
    8868             : 
    8869           0 :   const nsCSSValue* borderSpacingValue = aRuleData->ValueForBorderSpacing();
    8870             :   // border-spacing: pair(length), inherit
    8871           0 :   if (borderSpacingValue->GetUnit() != eCSSUnit_Null) {
    8872           0 :     nsStyleCoord parentCol(parentTable->mBorderSpacingCol,
    8873           0 :                            nsStyleCoord::CoordConstructor);
    8874           0 :     nsStyleCoord parentRow(parentTable->mBorderSpacingRow,
    8875           0 :                            nsStyleCoord::CoordConstructor);
    8876           0 :     nsStyleCoord coordCol, coordRow;
    8877             : 
    8878             : #ifdef DEBUG
    8879             :     bool result =
    8880             : #endif
    8881             :       SetPairCoords(*borderSpacingValue,
    8882             :                     coordCol, coordRow, parentCol, parentRow,
    8883             :                     SETCOORD_LH | SETCOORD_INITIAL_ZERO |
    8884             :                       SETCOORD_CALC_LENGTH_ONLY |
    8885             :                       SETCOORD_CALC_CLAMP_NONNEGATIVE | SETCOORD_UNSET_INHERIT,
    8886           0 :                     aContext, mPresContext, conditions);
    8887           0 :     NS_ASSERTION(result, "malformed table border value");
    8888           0 :     table->mBorderSpacingCol = coordCol.GetCoordValue();
    8889           0 :     table->mBorderSpacingRow = coordRow.GetCoordValue();
    8890             :   }
    8891             : 
    8892             :   // caption-side: enum, inherit, initial
    8893           0 :   SetValue(*aRuleData->ValueForCaptionSide(),
    8894             :            table->mCaptionSide, conditions,
    8895             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    8896           0 :            parentTable->mCaptionSide,
    8897           0 :            NS_STYLE_CAPTION_SIDE_TOP);
    8898             : 
    8899             :   // empty-cells: enum, inherit, initial
    8900           0 :   SetValue(*aRuleData->ValueForEmptyCells(),
    8901             :            table->mEmptyCells, conditions,
    8902             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    8903           0 :            parentTable->mEmptyCells,
    8904           0 :            NS_STYLE_TABLE_EMPTY_CELLS_SHOW);
    8905             : 
    8906           0 :   COMPUTE_END_INHERITED(TableBorder, table)
    8907             : }
    8908             : 
    8909             : const void*
    8910          34 : nsRuleNode::ComputeContentData(void* aStartStruct,
    8911             :                                const nsRuleData* aRuleData,
    8912             :                                GeckoStyleContext* aContext,
    8913             :                                nsRuleNode* aHighestNode,
    8914             :                                const RuleDetail aRuleDetail,
    8915             :                                const RuleNodeCacheConditions aConditions)
    8916             : {
    8917             :   uint32_t count;
    8918          68 :   nsAutoString buffer;
    8919             : 
    8920          68 :   COMPUTE_START_RESET(Content, content, parentContent)
    8921             : 
    8922             :   // content: [string, url, counter, attr, enum]+, normal, none, inherit
    8923          34 :   const nsCSSValue* contentValue = aRuleData->ValueForContent();
    8924          34 :   switch (contentValue->GetUnit()) {
    8925             :   case eCSSUnit_Null:
    8926          26 :     break;
    8927             : 
    8928             :   case eCSSUnit_Normal:
    8929             :   case eCSSUnit_None:
    8930             :   case eCSSUnit_Initial:
    8931             :   case eCSSUnit_Unset:
    8932             :     // "normal", "none", "initial" and "unset" all mean no content
    8933           0 :     content->AllocateContents(0);
    8934           0 :     break;
    8935             : 
    8936             :   case eCSSUnit_Inherit:
    8937           0 :     conditions.SetUncacheable();
    8938           0 :     count = parentContent->ContentCount();
    8939           0 :     content->AllocateContents(count);
    8940           0 :     while (0 < count--) {
    8941           0 :       content->ContentAt(count) = parentContent->ContentAt(count);
    8942             :     }
    8943           0 :     break;
    8944             : 
    8945             :   case eCSSUnit_Enumerated: {
    8946           0 :     MOZ_ASSERT(contentValue->GetIntValue() == NS_STYLE_CONTENT_ALT_CONTENT,
    8947             :                "unrecognized solitary content keyword");
    8948           0 :     content->AllocateContents(1);
    8949           0 :     content->ContentAt(0).SetKeyword(eStyleContentType_AltContent);
    8950           0 :     break;
    8951             :   }
    8952             : 
    8953             :   case eCSSUnit_List:
    8954             :   case eCSSUnit_ListDep: {
    8955           8 :     const nsCSSValueList* contentValueList = contentValue->GetListValue();
    8956           8 :     count = 0;
    8957          24 :     while (contentValueList) {
    8958           8 :       count++;
    8959           8 :       contentValueList = contentValueList->mNext;
    8960             :     }
    8961           8 :     content->AllocateContents(count);
    8962          16 :     const nsAutoString nullStr;
    8963           8 :     count = 0;
    8964           8 :     contentValueList = contentValue->GetListValue();
    8965          24 :     while (contentValueList) {
    8966           8 :       const nsCSSValue& value = contentValueList->mValue;
    8967           8 :       nsCSSUnit unit = value.GetUnit();
    8968           8 :       nsStyleContentData& data = content->ContentAt(count++);
    8969           8 :       switch (unit) {
    8970             :         case eCSSUnit_Image:
    8971           0 :           data.SetImageRequest(CreateStyleImageRequest(mPresContext, value));
    8972           0 :           break;
    8973             :         case eCSSUnit_String:
    8974             :         case eCSSUnit_Attr: {
    8975             :           nsStyleContentType type =
    8976           8 :             unit == eCSSUnit_String ? eStyleContentType_String
    8977           8 :                                     : eStyleContentType_Attr;
    8978           8 :           value.GetStringValue(buffer);
    8979           8 :           data.SetString(type, buffer.get());
    8980           8 :           break;
    8981             :         }
    8982             :         case eCSSUnit_Counter:
    8983             :         case eCSSUnit_Counters: {
    8984             :           nsStyleContentType type =
    8985           0 :             unit == eCSSUnit_Counter ? eStyleContentType_Counter
    8986           0 :                                      : eStyleContentType_Counters;
    8987             :           RefPtr<nsStyleContentData::CounterFunction>
    8988           0 :             counterFunc = new nsStyleContentData::CounterFunction();
    8989           0 :           nsCSSValue::Array* arrayValue = value.GetArrayValue();
    8990           0 :           arrayValue->Item(0).GetStringValue(counterFunc->mIdent);
    8991           0 :           if (unit == eCSSUnit_Counters) {
    8992           0 :             arrayValue->Item(1).GetStringValue(counterFunc->mSeparator);
    8993             :           }
    8994             :           const nsCSSValue& style =
    8995           0 :             value.GetArrayValue()->Item(unit == eCSSUnit_Counters ? 2 : 1);
    8996           0 :           if (style.GetUnit() == eCSSUnit_AtomIdent) {
    8997           0 :             counterFunc->mCounterStyle = mPresContext->
    8998           0 :               CounterStyleManager()->BuildCounterStyle(style.GetAtomValue());
    8999           0 :           } else if (style.GetUnit() == eCSSUnit_Symbols) {
    9000           0 :             counterFunc->mCounterStyle =
    9001           0 :               new AnonymousCounterStyle(style.GetArrayValue());
    9002             :           } else {
    9003           0 :             MOZ_ASSERT_UNREACHABLE("Unknown counter style");
    9004             :             counterFunc->mCounterStyle = CounterStyleManager::GetDecimalStyle();
    9005             :           }
    9006           0 :           data.SetCounters(type, counterFunc.forget());
    9007           0 :           break;
    9008             :         }
    9009             :         case eCSSUnit_Enumerated:
    9010           0 :           switch (value.GetIntValue()) {
    9011             :             case NS_STYLE_CONTENT_OPEN_QUOTE:
    9012           0 :               data.SetKeyword(eStyleContentType_OpenQuote);
    9013           0 :               break;
    9014             :             case NS_STYLE_CONTENT_CLOSE_QUOTE:
    9015           0 :               data.SetKeyword(eStyleContentType_CloseQuote);
    9016           0 :               break;
    9017             :             case NS_STYLE_CONTENT_NO_OPEN_QUOTE:
    9018           0 :               data.SetKeyword(eStyleContentType_NoOpenQuote);
    9019           0 :               break;
    9020             :             case NS_STYLE_CONTENT_NO_CLOSE_QUOTE:
    9021           0 :               data.SetKeyword(eStyleContentType_NoCloseQuote);
    9022           0 :               break;
    9023             :             default:
    9024           0 :               NS_ERROR("bad content value");
    9025           0 :               break;
    9026             :           }
    9027           0 :           break;
    9028             :         default:
    9029           0 :           NS_ERROR("bad content type");
    9030           0 :           break;
    9031             :       }
    9032           8 :       contentValueList = contentValueList->mNext;
    9033             :     }
    9034           8 :     break;
    9035             :   }
    9036             : 
    9037             :   default:
    9038           0 :     MOZ_ASSERT(false, "unrecognized content unit");
    9039             :   }
    9040             : 
    9041             :   // counter-increment: [string [int]]+, none, inherit
    9042             :   const nsCSSValue* counterIncrementValue =
    9043          34 :     aRuleData->ValueForCounterIncrement();
    9044          34 :   switch (counterIncrementValue->GetUnit()) {
    9045             :   case eCSSUnit_Null:
    9046          34 :     break;
    9047             : 
    9048             :   case eCSSUnit_None:
    9049             :   case eCSSUnit_Initial:
    9050             :   case eCSSUnit_Unset:
    9051           0 :     content->AllocateCounterIncrements(0);
    9052           0 :     break;
    9053             : 
    9054             :   case eCSSUnit_Inherit:
    9055           0 :     conditions.SetUncacheable();
    9056           0 :     count = parentContent->CounterIncrementCount();
    9057           0 :     content->AllocateCounterIncrements(count);
    9058           0 :     while (count--) {
    9059           0 :       const nsStyleCounterData& data = parentContent->CounterIncrementAt(count);
    9060           0 :       content->SetCounterIncrementAt(count, data.mCounter, data.mValue);
    9061             :     }
    9062           0 :     break;
    9063             : 
    9064             :   case eCSSUnit_PairList:
    9065             :   case eCSSUnit_PairListDep: {
    9066             :     const nsCSSValuePairList* ourIncrement =
    9067           0 :       counterIncrementValue->GetPairListValue();
    9068           0 :     MOZ_ASSERT(ourIncrement->mXValue.GetUnit() == eCSSUnit_Ident,
    9069             :                "unexpected value unit");
    9070           0 :     count = ListLength(ourIncrement);
    9071           0 :     content->AllocateCounterIncrements(count);
    9072             : 
    9073           0 :     count = 0;
    9074           0 :     for (const nsCSSValuePairList* p = ourIncrement; p; p = p->mNext, count++) {
    9075           0 :       MOZ_ASSERT(p->mYValue.GetUnit() == eCSSUnit_Integer);
    9076           0 :       p->mXValue.GetStringValue(buffer);
    9077           0 :       content->SetCounterIncrementAt(count, buffer, p->mYValue.GetIntValue());
    9078             :     }
    9079           0 :     break;
    9080             :   }
    9081             : 
    9082             :   default:
    9083           0 :     MOZ_ASSERT(false, "unexpected value unit");
    9084             :   }
    9085             : 
    9086             :   // counter-reset: [string [int]]+, none, inherit
    9087          34 :   const nsCSSValue* counterResetValue = aRuleData->ValueForCounterReset();
    9088          34 :   switch (counterResetValue->GetUnit()) {
    9089             :   case eCSSUnit_Null:
    9090          34 :     break;
    9091             : 
    9092             :   case eCSSUnit_None:
    9093             :   case eCSSUnit_Initial:
    9094             :   case eCSSUnit_Unset:
    9095           0 :     content->AllocateCounterResets(0);
    9096           0 :     break;
    9097             : 
    9098             :   case eCSSUnit_Inherit:
    9099           0 :     conditions.SetUncacheable();
    9100           0 :     count = parentContent->CounterResetCount();
    9101           0 :     content->AllocateCounterResets(count);
    9102           0 :     while (0 < count--) {
    9103           0 :       const nsStyleCounterData& data = parentContent->CounterResetAt(count);
    9104           0 :       content->SetCounterResetAt(count, data.mCounter, data.mValue);
    9105             :     }
    9106           0 :     break;
    9107             : 
    9108             :   case eCSSUnit_PairList:
    9109             :   case eCSSUnit_PairListDep: {
    9110             :     const nsCSSValuePairList* ourReset =
    9111           0 :       counterResetValue->GetPairListValue();
    9112           0 :     MOZ_ASSERT(ourReset->mXValue.GetUnit() == eCSSUnit_Ident,
    9113             :                "unexpected value unit");
    9114           0 :     count = ListLength(ourReset);
    9115           0 :     content->AllocateCounterResets(count);
    9116           0 :     count = 0;
    9117           0 :     for (const nsCSSValuePairList* p = ourReset; p; p = p->mNext, count++) {
    9118           0 :       MOZ_ASSERT(p->mYValue.GetUnit() == eCSSUnit_Integer);
    9119           0 :       p->mXValue.GetStringValue(buffer);
    9120           0 :       content->SetCounterResetAt(count, buffer, p->mYValue.GetIntValue());
    9121             :     }
    9122           0 :     break;
    9123             :   }
    9124             : 
    9125             :   default:
    9126           0 :     MOZ_ASSERT(false, "unexpected value unit");
    9127             :   }
    9128             : 
    9129          68 :   COMPUTE_END_RESET(Content, content)
    9130             : }
    9131             : 
    9132             : const void*
    9133         158 : nsRuleNode::ComputeXULData(void* aStartStruct,
    9134             :                            const nsRuleData* aRuleData,
    9135             :                            GeckoStyleContext* aContext,
    9136             :                            nsRuleNode* aHighestNode,
    9137             :                            const RuleDetail aRuleDetail,
    9138             :                            const RuleNodeCacheConditions aConditions)
    9139             : {
    9140         316 :   COMPUTE_START_RESET(XUL, xul, parentXUL)
    9141             : 
    9142             :   // box-align: enum, inherit, initial
    9143         158 :   SetValue(*aRuleData->ValueForBoxAlign(),
    9144             :            xul->mBoxAlign, conditions,
    9145             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    9146         158 :            parentXUL->mBoxAlign,
    9147         158 :            StyleBoxAlign::Stretch);
    9148             : 
    9149             :   // box-direction: enum, inherit, initial
    9150         158 :   SetValue(*aRuleData->ValueForBoxDirection(),
    9151             :            xul->mBoxDirection, conditions,
    9152             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    9153         158 :            parentXUL->mBoxDirection,
    9154         158 :            StyleBoxDirection::Normal);
    9155             : 
    9156             :   // box-flex: factor, inherit
    9157         158 :   SetFactor(*aRuleData->ValueForBoxFlex(),
    9158             :             xul->mBoxFlex, conditions,
    9159         158 :             parentXUL->mBoxFlex, 0.0f,
    9160         158 :             SETFCT_UNSET_INITIAL);
    9161             : 
    9162             :   // box-orient: enum, inherit, initial
    9163         158 :   SetValue(*aRuleData->ValueForBoxOrient(),
    9164             :            xul->mBoxOrient, conditions,
    9165             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    9166         158 :            parentXUL->mBoxOrient,
    9167         158 :            StyleBoxOrient::Horizontal);
    9168             : 
    9169             :   // box-pack: enum, inherit, initial
    9170         158 :   SetValue(*aRuleData->ValueForBoxPack(),
    9171             :            xul->mBoxPack, conditions,
    9172             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    9173         158 :            parentXUL->mBoxPack,
    9174         158 :            StyleBoxPack::Start);
    9175             : 
    9176             :   // box-ordinal-group: integer, inherit, initial
    9177         158 :   SetValue(*aRuleData->ValueForBoxOrdinalGroup(),
    9178             :            xul->mBoxOrdinal, conditions,
    9179             :            SETVAL_INTEGER | SETVAL_UNSET_INITIAL,
    9180         316 :            parentXUL->mBoxOrdinal, 1);
    9181             : 
    9182         158 :   SetValue(*aRuleData->ValueForStackSizing(),
    9183             :            xul->mStackSizing, conditions,
    9184             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    9185         158 :            parentXUL->mStackSizing,
    9186         158 :            StyleStackSizing::StretchToFit);
    9187             : 
    9188         316 :   COMPUTE_END_RESET(XUL, xul)
    9189             : }
    9190             : 
    9191             : const void*
    9192          32 : nsRuleNode::ComputeColumnData(void* aStartStruct,
    9193             :                               const nsRuleData* aRuleData,
    9194             :                               GeckoStyleContext* aContext,
    9195             :                               nsRuleNode* aHighestNode,
    9196             :                               const RuleDetail aRuleDetail,
    9197             :                               const RuleNodeCacheConditions aConditions)
    9198             : {
    9199          64 :   COMPUTE_START_RESET(Column, column, parent)
    9200             : 
    9201             :   // column-width: length, auto, inherit
    9202          32 :   SetCoord(*aRuleData->ValueForColumnWidth(),
    9203             :            column->mColumnWidth, parent->mColumnWidth,
    9204             :            SETCOORD_LAH | SETCOORD_INITIAL_AUTO |
    9205             :              SETCOORD_CALC_LENGTH_ONLY | SETCOORD_CALC_CLAMP_NONNEGATIVE |
    9206             :              SETCOORD_UNSET_INITIAL,
    9207          64 :            aContext, mPresContext, conditions);
    9208             : 
    9209             :   // column-gap: length, inherit, normal
    9210          32 :   SetCoord(*aRuleData->ValueForColumnGap(),
    9211             :            column->mColumnGap, parent->mColumnGap,
    9212             :            SETCOORD_LH | SETCOORD_NORMAL | SETCOORD_INITIAL_NORMAL |
    9213             :              SETCOORD_CALC_LENGTH_ONLY | SETCOORD_UNSET_INITIAL,
    9214          64 :            aContext, mPresContext, conditions);
    9215             :   // clamp negative calc() to 0
    9216          32 :   if (column->mColumnGap.GetUnit() == eStyleUnit_Coord) {
    9217           0 :     column->mColumnGap.SetCoordValue(
    9218           0 :       std::max(column->mColumnGap.GetCoordValue(), 0));
    9219             :   }
    9220             : 
    9221             :   // column-count: auto, integer, inherit
    9222          32 :   const nsCSSValue* columnCountValue = aRuleData->ValueForColumnCount();
    9223          96 :   if (eCSSUnit_Auto == columnCountValue->GetUnit() ||
    9224          64 :       eCSSUnit_Initial == columnCountValue->GetUnit() ||
    9225          32 :       eCSSUnit_Unset == columnCountValue->GetUnit()) {
    9226           0 :     column->mColumnCount = NS_STYLE_COLUMN_COUNT_AUTO;
    9227          32 :   } else if (eCSSUnit_Integer == columnCountValue->GetUnit()) {
    9228           0 :     column->mColumnCount = columnCountValue->GetIntValue();
    9229             :     // Max kMaxColumnCount columns - wallpaper for bug 345583.
    9230           0 :     column->mColumnCount = std::min(column->mColumnCount,
    9231           0 :                                     nsStyleColumn::kMaxColumnCount);
    9232          32 :   } else if (eCSSUnit_Inherit == columnCountValue->GetUnit()) {
    9233          25 :     conditions.SetUncacheable();
    9234          25 :     column->mColumnCount = parent->mColumnCount;
    9235             :   }
    9236             : 
    9237             :   // column-rule-width: length, enum, inherit
    9238             :   Maybe<nscoord> coord =
    9239             :     ComputeLineWidthValue<eUnsetInitial>(
    9240          32 :       *aRuleData->ValueForColumnRuleWidth(),
    9241             :       parent->GetComputedColumnRuleWidth(),
    9242             :       nsPresContext::GetBorderWidthForKeyword(NS_STYLE_BORDER_WIDTH_MEDIUM),
    9243          96 :       aContext, mPresContext, conditions);
    9244          32 :   if (coord.isSome()) {
    9245          25 :     column->SetColumnRuleWidth(*coord);
    9246             :   }
    9247             : 
    9248             :   // column-rule-style: enum, inherit
    9249          32 :   const nsCSSValue& styleValue = *aRuleData->ValueForColumnRuleStyle();
    9250          32 :   MOZ_ASSERT(eCSSUnit_None != styleValue.GetUnit(),
    9251             :              "'none' should be handled as enumerated value");
    9252          32 :   if (eCSSUnit_Enumerated == styleValue.GetUnit()) {
    9253           0 :     column->mColumnRuleStyle = styleValue.GetIntValue();
    9254             :   }
    9255          64 :   else if (eCSSUnit_Initial == styleValue.GetUnit() ||
    9256          32 :            eCSSUnit_Unset == styleValue.GetUnit()) {
    9257           0 :     column->mColumnRuleStyle = NS_STYLE_BORDER_STYLE_NONE;
    9258             :   }
    9259          32 :   else if (eCSSUnit_Inherit == styleValue.GetUnit()) {
    9260          25 :     conditions.SetUncacheable();
    9261          25 :     column->mColumnRuleStyle = parent->mColumnRuleStyle;
    9262             :   }
    9263             : 
    9264             :   // column-rule-color: color, inherit
    9265          64 :   SetComplexColor<eUnsetInitial>(*aRuleData->ValueForColumnRuleColor(),
    9266             :                                  parent->mColumnRuleColor,
    9267          64 :                                  StyleComplexColor::CurrentColor(),
    9268          32 :                                  mPresContext,
    9269          32 :                                  column->mColumnRuleColor, conditions);
    9270             : 
    9271             :   // column-fill: enum
    9272          32 :   SetValue(*aRuleData->ValueForColumnFill(),
    9273             :            column->mColumnFill, conditions,
    9274             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    9275          32 :            parent->mColumnFill,
    9276          32 :            NS_STYLE_COLUMN_FILL_BALANCE);
    9277             : 
    9278             :   // column-span: enum
    9279          32 :   SetValue(*aRuleData->ValueForColumnSpan(),
    9280             :            column->mColumnSpan, conditions,
    9281             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
    9282          32 :            parent->mColumnSpan,
    9283          32 :            NS_STYLE_COLUMN_SPAN_NONE);
    9284             : 
    9285          64 :   COMPUTE_END_RESET(Column, column)
    9286             : }
    9287             : 
    9288             : static void
    9289         132 : SetSVGPaint(const nsCSSValue& aValue, const nsStyleSVGPaint& parentPaint,
    9290             :             nsPresContext* aPresContext, GeckoStyleContext *aContext,
    9291             :             nsStyleSVGPaint& aResult, nsStyleSVGPaintType aInitialPaintType,
    9292             :             RuleNodeCacheConditions& aConditions)
    9293             : {
    9294         132 :   MOZ_ASSERT(aInitialPaintType == eStyleSVGPaintType_None ||
    9295             :              aInitialPaintType == eStyleSVGPaintType_Color,
    9296             :              "SetSVGPaint only supports initial values being either 'black' "
    9297             :              "(represented by eStyleSVGPaintType_Color) or none (by "
    9298             :              "eStyleSVGPaintType_None)");
    9299             : 
    9300             :   nscolor color;
    9301             : 
    9302         264 :   if (aValue.GetUnit() == eCSSUnit_Inherit ||
    9303         132 :       aValue.GetUnit() == eCSSUnit_Unset) {
    9304           0 :     aResult = parentPaint;
    9305           0 :     aConditions.SetUncacheable();
    9306         132 :   } else if (aValue.GetUnit() == eCSSUnit_None) {
    9307           1 :     aResult.SetNone();
    9308         131 :   } else if (aValue.GetUnit() == eCSSUnit_Initial) {
    9309           0 :     if (aInitialPaintType == eStyleSVGPaintType_None) {
    9310           0 :       aResult.SetNone();
    9311             :     } else {
    9312           0 :       aResult.SetColor(NS_RGB(0, 0, 0));
    9313             :     }
    9314         131 :   } else if (aValue.GetUnit() == eCSSUnit_URL) {
    9315           0 :     aResult.SetPaintServer(aValue.GetURLStructValue());
    9316         131 :   } else if (aValue.GetUnit() == eCSSUnit_Enumerated) {
    9317          22 :     switch (aValue.GetIntValue()) {
    9318             :     case NS_COLOR_CONTEXT_FILL:
    9319          22 :       aResult.SetContextValue(eStyleSVGPaintType_ContextFill);
    9320          22 :       break;
    9321             :     case NS_COLOR_CONTEXT_STROKE:
    9322           0 :       aResult.SetContextValue(eStyleSVGPaintType_ContextStroke);
    9323           0 :       break;
    9324             :     default:
    9325           0 :       NS_NOTREACHED("unknown keyword as paint server value");
    9326             :     }
    9327         109 :   } else if (SetColor(aValue, NS_RGB(0, 0, 0), aPresContext, aContext,
    9328             :                       color, aConditions)) {
    9329          44 :     aResult.SetColor(color);
    9330          65 :   } else if (aValue.GetUnit() == eCSSUnit_Pair) {
    9331           0 :     const nsCSSValuePair& pair = aValue.GetPairValue();
    9332             : 
    9333             :     nsStyleSVGFallbackType fallbackType;
    9334             :     nscolor fallback;
    9335           0 :     if (pair.mYValue.GetUnit() == eCSSUnit_None) {
    9336           0 :       fallbackType = eStyleSVGFallbackType_None;
    9337           0 :       fallback = NS_RGBA(0, 0, 0, 0);
    9338             :     } else {
    9339           0 :       MOZ_ASSERT(pair.mYValue.GetUnit() != eCSSUnit_Inherit,
    9340             :                  "cannot inherit fallback colour");
    9341           0 :       fallbackType = eStyleSVGFallbackType_Color;
    9342           0 :       SetColor(pair.mYValue, NS_RGB(0, 0, 0), aPresContext, aContext,
    9343           0 :                fallback, aConditions);
    9344             :     }
    9345             : 
    9346           0 :     if (pair.mXValue.GetUnit() == eCSSUnit_URL) {
    9347           0 :       aResult.SetPaintServer(pair.mXValue.GetURLStructValue(),
    9348           0 :                              fallbackType, fallback);
    9349           0 :     } else if (pair.mXValue.GetUnit() == eCSSUnit_Enumerated) {
    9350             : 
    9351           0 :       switch (pair.mXValue.GetIntValue()) {
    9352             :       case NS_COLOR_CONTEXT_FILL:
    9353           0 :         aResult.SetContextValue(eStyleSVGPaintType_ContextFill,
    9354           0 :                                 fallbackType, fallback);
    9355           0 :         break;
    9356             :       case NS_COLOR_CONTEXT_STROKE:
    9357           0 :         aResult.SetContextValue(eStyleSVGPaintType_ContextStroke,
    9358           0 :                                 fallbackType, fallback);
    9359           0 :         break;
    9360             :       default:
    9361           0 :         NS_NOTREACHED("unknown keyword as paint server value");
    9362             :       }
    9363             : 
    9364             :     } else {
    9365           0 :       NS_NOTREACHED("malformed paint server value");
    9366             :     }
    9367             : 
    9368             :   } else {
    9369          65 :     MOZ_ASSERT(aValue.GetUnit() == eCSSUnit_Null,
    9370             :                "malformed paint server value");
    9371             :   }
    9372         132 : }
    9373             : 
    9374             : static void
    9375         132 : SetSVGOpacity(const nsCSSValue& aValue,
    9376             :               float& aOpacityField, nsStyleSVGOpacitySource& aOpacityTypeField,
    9377             :               RuleNodeCacheConditions& aConditions,
    9378             :               float aParentOpacity, nsStyleSVGOpacitySource aParentOpacityType)
    9379             : {
    9380         132 :   if (eCSSUnit_Enumerated == aValue.GetUnit()) {
    9381           3 :     switch (aValue.GetIntValue()) {
    9382             :     case NS_STYLE_CONTEXT_FILL_OPACITY:
    9383           3 :       aOpacityTypeField = eStyleSVGOpacitySource_ContextFillOpacity;
    9384           3 :       break;
    9385             :     case NS_STYLE_CONTEXT_STROKE_OPACITY:
    9386           0 :       aOpacityTypeField = eStyleSVGOpacitySource_ContextStrokeOpacity;
    9387           0 :       break;
    9388             :     default:
    9389           0 :       NS_NOTREACHED("SetSVGOpacity: Unknown keyword");
    9390             :     }
    9391             :     // Fall back on fully opaque
    9392           3 :     aOpacityField = 1.0f;
    9393         258 :   } else if (eCSSUnit_Inherit == aValue.GetUnit() ||
    9394         129 :              eCSSUnit_Unset == aValue.GetUnit()) {
    9395           0 :     aConditions.SetUncacheable();
    9396           0 :     aOpacityField = aParentOpacity;
    9397           0 :     aOpacityTypeField = aParentOpacityType;
    9398         129 :   } else if (eCSSUnit_Null != aValue.GetUnit()) {
    9399             :     SetFactor(aValue, aOpacityField, aConditions,
    9400           8 :               aParentOpacity, 1.0f, SETFCT_OPACITY);
    9401           8 :     aOpacityTypeField = eStyleSVGOpacitySource_Normal;
    9402             :   }
    9403         132 : }
    9404             : 
    9405             : /* static */
    9406             : void
    9407           0 : nsRuleNode::FillAllMaskLists(nsStyleImageLayers& aMask,
    9408             :                              uint32_t aMaxItemCount)
    9409             : {
    9410             : 
    9411             :   // Delete any extra items.  We need to keep layers in which any
    9412             :   // property was specified.
    9413           0 :   aMask.mLayers.TruncateLengthNonZero(aMaxItemCount);
    9414             : 
    9415           0 :   uint32_t fillCount = aMask.mImageCount;
    9416             : 
    9417           0 :   FillImageLayerList(aMask.mLayers,
    9418             :                      &nsStyleImageLayers::Layer::mImage,
    9419           0 :                      aMask.mImageCount, fillCount);
    9420           0 :   FillImageLayerList(aMask.mLayers,
    9421             :                      &nsStyleImageLayers::Layer::mRepeat,
    9422           0 :                      aMask.mRepeatCount, fillCount);
    9423           0 :   FillImageLayerList(aMask.mLayers,
    9424             :                      &nsStyleImageLayers::Layer::mClip,
    9425           0 :                      aMask.mClipCount, fillCount);
    9426           0 :   FillImageLayerList(aMask.mLayers,
    9427             :                      &nsStyleImageLayers::Layer::mOrigin,
    9428           0 :                      aMask.mOriginCount, fillCount);
    9429           0 :   FillImageLayerPositionCoordList(aMask.mLayers,
    9430             :                                   &Position::mXPosition,
    9431           0 :                                   aMask.mPositionXCount, fillCount);
    9432           0 :   FillImageLayerPositionCoordList(aMask.mLayers,
    9433             :                                   &Position::mYPosition,
    9434           0 :                                   aMask.mPositionYCount, fillCount);
    9435           0 :   FillImageLayerList(aMask.mLayers,
    9436             :                      &nsStyleImageLayers::Layer::mSize,
    9437           0 :                      aMask.mSizeCount, fillCount);
    9438           0 :   FillImageLayerList(aMask.mLayers,
    9439             :                      &nsStyleImageLayers::Layer::mMaskMode,
    9440           0 :                      aMask.mMaskModeCount, fillCount);
    9441           0 :   FillImageLayerList(aMask.mLayers,
    9442             :                      &nsStyleImageLayers::Layer::mComposite,
    9443           0 :                      aMask.mCompositeCount, fillCount);
    9444           0 : }
    9445             : 
    9446             : const void*
    9447          66 : nsRuleNode::ComputeSVGData(void* aStartStruct,
    9448             :                            const nsRuleData* aRuleData,
    9449             :                            GeckoStyleContext* aContext,
    9450             :                            nsRuleNode* aHighestNode,
    9451             :                            const RuleDetail aRuleDetail,
    9452             :                            const RuleNodeCacheConditions aConditions)
    9453             : {
    9454         132 :   COMPUTE_START_INHERITED(SVG, svg, parentSVG)
    9455             : 
    9456             :   // clip-rule: enum, inherit, initial
    9457          66 :   SetValue(*aRuleData->ValueForClipRule(),
    9458             :            svg->mClipRule, conditions,
    9459             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    9460          66 :            parentSVG->mClipRule,
    9461          66 :            StyleFillRule::Nonzero);
    9462             : 
    9463             :   // color-interpolation: enum, inherit, initial
    9464          66 :   SetValue(*aRuleData->ValueForColorInterpolation(),
    9465             :            svg->mColorInterpolation, conditions,
    9466             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    9467          66 :            parentSVG->mColorInterpolation,
    9468          66 :            NS_STYLE_COLOR_INTERPOLATION_SRGB);
    9469             : 
    9470             :   // color-interpolation-filters: enum, inherit, initial
    9471          66 :   SetValue(*aRuleData->ValueForColorInterpolationFilters(),
    9472             :            svg->mColorInterpolationFilters, conditions,
    9473             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    9474          66 :            parentSVG->mColorInterpolationFilters,
    9475          66 :            NS_STYLE_COLOR_INTERPOLATION_LINEARRGB);
    9476             : 
    9477             :   // fill:
    9478         132 :   SetSVGPaint(*aRuleData->ValueForFill(),
    9479          66 :               parentSVG->mFill, mPresContext, aContext,
    9480          66 :               svg->mFill, eStyleSVGPaintType_Color, conditions);
    9481             : 
    9482             :   // fill-opacity: factor, inherit, initial,
    9483             :   // context-fill-opacity, context-stroke-opacity
    9484          66 :   nsStyleSVGOpacitySource contextFillOpacity = svg->FillOpacitySource();
    9485         132 :   SetSVGOpacity(*aRuleData->ValueForFillOpacity(),
    9486             :                 svg->mFillOpacity, contextFillOpacity, conditions,
    9487         198 :                 parentSVG->mFillOpacity, parentSVG->FillOpacitySource());
    9488          66 :   svg->SetFillOpacitySource(contextFillOpacity);
    9489             : 
    9490             :   // fill-rule: enum, inherit, initial
    9491          66 :   SetValue(*aRuleData->ValueForFillRule(),
    9492             :            svg->mFillRule, conditions,
    9493             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    9494          66 :            parentSVG->mFillRule,
    9495          66 :            StyleFillRule::Nonzero);
    9496             : 
    9497             :   // marker-end: url, none, inherit
    9498          66 :   const nsCSSValue* markerEndValue = aRuleData->ValueForMarkerEnd();
    9499          66 :   if (eCSSUnit_URL == markerEndValue->GetUnit()) {
    9500           0 :     svg->mMarkerEnd = markerEndValue->GetURLStructValue();
    9501         132 :   } else if (eCSSUnit_None == markerEndValue->GetUnit() ||
    9502          66 :              eCSSUnit_Initial == markerEndValue->GetUnit()) {
    9503           0 :     svg->mMarkerEnd = nullptr;
    9504         132 :   } else if (eCSSUnit_Inherit == markerEndValue->GetUnit() ||
    9505          66 :              eCSSUnit_Unset == markerEndValue->GetUnit()) {
    9506           0 :     conditions.SetUncacheable();
    9507           0 :     svg->mMarkerEnd = parentSVG->mMarkerEnd;
    9508             :   }
    9509             : 
    9510             :   // marker-mid: url, none, inherit
    9511          66 :   const nsCSSValue* markerMidValue = aRuleData->ValueForMarkerMid();
    9512          66 :   if (eCSSUnit_URL == markerMidValue->GetUnit()) {
    9513           0 :     svg->mMarkerMid = markerMidValue->GetURLStructValue();
    9514         132 :   } else if (eCSSUnit_None == markerMidValue->GetUnit() ||
    9515          66 :              eCSSUnit_Initial == markerMidValue->GetUnit()) {
    9516           0 :     svg->mMarkerMid = nullptr;
    9517         132 :   } else if (eCSSUnit_Inherit == markerMidValue->GetUnit() ||
    9518          66 :              eCSSUnit_Unset == markerMidValue->GetUnit()) {
    9519           0 :     conditions.SetUncacheable();
    9520           0 :     svg->mMarkerMid = parentSVG->mMarkerMid;
    9521             :   }
    9522             : 
    9523             :   // marker-start: url, none, inherit
    9524          66 :   const nsCSSValue* markerStartValue = aRuleData->ValueForMarkerStart();
    9525          66 :   if (eCSSUnit_URL == markerStartValue->GetUnit()) {
    9526           0 :     svg->mMarkerStart = markerStartValue->GetURLStructValue();
    9527         132 :   } else if (eCSSUnit_None == markerStartValue->GetUnit() ||
    9528          66 :              eCSSUnit_Initial == markerStartValue->GetUnit()) {
    9529           0 :     svg->mMarkerStart = nullptr;
    9530         132 :   } else if (eCSSUnit_Inherit == markerStartValue->GetUnit() ||
    9531          66 :              eCSSUnit_Unset == markerStartValue->GetUnit()) {
    9532           0 :     conditions.SetUncacheable();
    9533           0 :     svg->mMarkerStart = parentSVG->mMarkerStart;
    9534             :   }
    9535             : 
    9536             :   // paint-order: enum (bit field), inherit, initial
    9537          66 :   const nsCSSValue* paintOrderValue = aRuleData->ValueForPaintOrder();
    9538          66 :   switch (paintOrderValue->GetUnit()) {
    9539             :     case eCSSUnit_Null:
    9540          66 :       break;
    9541             : 
    9542             :     case eCSSUnit_Enumerated:
    9543             :       static_assert
    9544             :         (NS_STYLE_PAINT_ORDER_BITWIDTH * NS_STYLE_PAINT_ORDER_LAST_VALUE <= 8,
    9545             :          "SVGStyleStruct::mPaintOrder not big enough");
    9546           0 :       svg->mPaintOrder = static_cast<uint8_t>(paintOrderValue->GetIntValue());
    9547           0 :       break;
    9548             : 
    9549             :     case eCSSUnit_Inherit:
    9550             :     case eCSSUnit_Unset:
    9551           0 :       conditions.SetUncacheable();
    9552           0 :       svg->mPaintOrder = parentSVG->mPaintOrder;
    9553           0 :       break;
    9554             : 
    9555             :     case eCSSUnit_Initial:
    9556           0 :       svg->mPaintOrder = NS_STYLE_PAINT_ORDER_NORMAL;
    9557           0 :       break;
    9558             : 
    9559             :     default:
    9560           0 :       NS_NOTREACHED("unexpected unit");
    9561             :   }
    9562             : 
    9563             :   // shape-rendering: enum, inherit
    9564          66 :   SetValue(*aRuleData->ValueForShapeRendering(),
    9565             :            svg->mShapeRendering, conditions,
    9566             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    9567          66 :            parentSVG->mShapeRendering,
    9568          66 :            NS_STYLE_SHAPE_RENDERING_AUTO);
    9569             : 
    9570             :   // stroke:
    9571         132 :   SetSVGPaint(*aRuleData->ValueForStroke(),
    9572          66 :               parentSVG->mStroke, mPresContext, aContext,
    9573          66 :               svg->mStroke, eStyleSVGPaintType_None, conditions);
    9574             : 
    9575             :   // stroke-dasharray: <dasharray>, none, inherit, context-value
    9576          66 :   const nsCSSValue* strokeDasharrayValue = aRuleData->ValueForStrokeDasharray();
    9577          66 :   switch (strokeDasharrayValue->GetUnit()) {
    9578             :   case eCSSUnit_Null:
    9579          66 :     break;
    9580             : 
    9581             :   case eCSSUnit_Inherit:
    9582             :   case eCSSUnit_Unset:
    9583           0 :     conditions.SetUncacheable();
    9584           0 :     svg->SetStrokeDasharrayFromObject(parentSVG->StrokeDasharrayFromObject());
    9585           0 :     svg->mStrokeDasharray = parentSVG->mStrokeDasharray;
    9586           0 :     break;
    9587             : 
    9588             :   case eCSSUnit_Enumerated:
    9589           0 :     MOZ_ASSERT(strokeDasharrayValue->GetIntValue() ==
    9590             :                      NS_STYLE_STROKE_PROP_CONTEXT_VALUE,
    9591             :                "Unknown keyword for stroke-dasharray");
    9592           0 :     svg->SetStrokeDasharrayFromObject(true);
    9593           0 :     svg->mStrokeDasharray.Clear();
    9594           0 :     break;
    9595             : 
    9596             :   case eCSSUnit_Initial:
    9597             :   case eCSSUnit_None:
    9598           0 :     svg->SetStrokeDasharrayFromObject(false);
    9599           0 :     svg->mStrokeDasharray.Clear();
    9600           0 :     break;
    9601             : 
    9602             :   case eCSSUnit_List:
    9603             :   case eCSSUnit_ListDep: {
    9604           0 :     svg->SetStrokeDasharrayFromObject(false);
    9605           0 :     svg->mStrokeDasharray.Clear();
    9606             : 
    9607             :     // count number of values
    9608           0 :     const nsCSSValueList *value = strokeDasharrayValue->GetListValue();
    9609           0 :     uint32_t strokeDasharrayLength = ListLength(value);
    9610             : 
    9611           0 :     MOZ_ASSERT(strokeDasharrayLength != 0, "no dasharray items");
    9612             : 
    9613           0 :     svg->mStrokeDasharray.SetLength(strokeDasharrayLength);
    9614             : 
    9615           0 :     uint32_t i = 0;
    9616           0 :     while (nullptr != value) {
    9617           0 :       SetCoord(value->mValue,
    9618           0 :                svg->mStrokeDasharray[i++], nsStyleCoord(),
    9619             :                SETCOORD_LP | SETCOORD_FACTOR,
    9620           0 :                aContext, mPresContext, conditions);
    9621           0 :       value = value->mNext;
    9622             :     }
    9623           0 :     break;
    9624             :   }
    9625             : 
    9626             :   default:
    9627           0 :     MOZ_ASSERT(false, "unrecognized dasharray unit");
    9628             :   }
    9629             : 
    9630             :   // stroke-dashoffset: <dashoffset>, inherit
    9631             :   const nsCSSValue *strokeDashoffsetValue =
    9632          66 :     aRuleData->ValueForStrokeDashoffset();
    9633          66 :   svg->SetStrokeDashoffsetFromObject(
    9634          66 :     strokeDashoffsetValue->GetUnit() == eCSSUnit_Enumerated &&
    9635          66 :     strokeDashoffsetValue->GetIntValue() == NS_STYLE_STROKE_PROP_CONTEXT_VALUE);
    9636          66 :   if (svg->StrokeDashoffsetFromObject()) {
    9637           0 :     svg->mStrokeDashoffset.SetCoordValue(0);
    9638             :   } else {
    9639          66 :     SetCoord(*aRuleData->ValueForStrokeDashoffset(),
    9640             :              svg->mStrokeDashoffset, parentSVG->mStrokeDashoffset,
    9641             :              SETCOORD_LPH | SETCOORD_FACTOR | SETCOORD_INITIAL_ZERO |
    9642             :                SETCOORD_UNSET_INHERIT,
    9643         132 :              aContext, mPresContext, conditions);
    9644             :   }
    9645             : 
    9646             :   // stroke-linecap: enum, inherit, initial
    9647          66 :   SetValue(*aRuleData->ValueForStrokeLinecap(),
    9648             :            svg->mStrokeLinecap, conditions,
    9649             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    9650          66 :            parentSVG->mStrokeLinecap,
    9651          66 :            NS_STYLE_STROKE_LINECAP_BUTT);
    9652             : 
    9653             :   // stroke-linejoin: enum, inherit, initial
    9654          66 :   SetValue(*aRuleData->ValueForStrokeLinejoin(),
    9655             :            svg->mStrokeLinejoin, conditions,
    9656             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    9657          66 :            parentSVG->mStrokeLinejoin,
    9658          66 :            NS_STYLE_STROKE_LINEJOIN_MITER);
    9659             : 
    9660             :   // stroke-miterlimit: <miterlimit>, inherit
    9661          66 :   SetFactor(*aRuleData->ValueForStrokeMiterlimit(),
    9662             :             svg->mStrokeMiterlimit,
    9663             :             conditions,
    9664          66 :             parentSVG->mStrokeMiterlimit, 4.0f,
    9665          66 :             SETFCT_UNSET_INHERIT);
    9666             : 
    9667             :   // stroke-opacity:
    9668          66 :   nsStyleSVGOpacitySource contextStrokeOpacity = svg->StrokeOpacitySource();
    9669         132 :   SetSVGOpacity(*aRuleData->ValueForStrokeOpacity(),
    9670             :                 svg->mStrokeOpacity, contextStrokeOpacity, conditions,
    9671         198 :                 parentSVG->mStrokeOpacity, parentSVG->StrokeOpacitySource());
    9672          66 :   svg->SetStrokeOpacitySource(contextStrokeOpacity);
    9673             : 
    9674             :   // stroke-width:
    9675          66 :   const nsCSSValue* strokeWidthValue = aRuleData->ValueForStrokeWidth();
    9676          66 :   switch (strokeWidthValue->GetUnit()) {
    9677             :   case eCSSUnit_Enumerated:
    9678           0 :     MOZ_ASSERT(strokeWidthValue->GetIntValue() ==
    9679             :                  NS_STYLE_STROKE_PROP_CONTEXT_VALUE,
    9680             :                "Unrecognized keyword for stroke-width");
    9681           0 :     svg->SetStrokeWidthFromObject(true);
    9682           0 :     svg->mStrokeWidth.SetCoordValue(nsPresContext::CSSPixelsToAppUnits(1));
    9683           0 :     break;
    9684             : 
    9685             :   case eCSSUnit_Initial:
    9686           0 :     svg->SetStrokeWidthFromObject(false);
    9687           0 :     svg->mStrokeWidth.SetCoordValue(nsPresContext::CSSPixelsToAppUnits(1));
    9688           0 :     break;
    9689             : 
    9690             :   default:
    9691          66 :     svg->SetStrokeWidthFromObject(false);
    9692          66 :     SetCoord(*strokeWidthValue,
    9693             :              svg->mStrokeWidth, parentSVG->mStrokeWidth,
    9694             :              SETCOORD_LPH | SETCOORD_FACTOR | SETCOORD_UNSET_INHERIT,
    9695         132 :              aContext, mPresContext, conditions);
    9696             :   }
    9697             : 
    9698             :   // text-anchor: enum, inherit, initial
    9699          66 :   SetValue(*aRuleData->ValueForTextAnchor(),
    9700             :            svg->mTextAnchor, conditions,
    9701             :            SETVAL_ENUMERATED | SETVAL_UNSET_INHERIT,
    9702          66 :            parentSVG->mTextAnchor,
    9703          66 :            NS_STYLE_TEXT_ANCHOR_START);
    9704             : 
    9705             :   // -moz-context-properties:
    9706          66 :   const nsCSSValue* contextPropsValue = aRuleData->ValueForContextProperties();
    9707          66 :   switch (contextPropsValue->GetUnit()) {
    9708             :   case eCSSUnit_Null:
    9709          38 :     break;
    9710             : 
    9711             :   case eCSSUnit_List:
    9712             :   case eCSSUnit_ListDep: {
    9713          28 :     svg->mContextProps.Clear();
    9714          28 :     svg->mContextPropsBits = 0;
    9715          59 :     for (const nsCSSValueList* item = contextPropsValue->GetListValue();
    9716          90 :          item; item = item->mNext)
    9717             :     {
    9718          31 :       nsIAtom* atom = item->mValue.GetAtomValue();
    9719          31 :       svg->mContextProps.AppendElement(atom);
    9720          31 :       if (atom == nsGkAtoms::fill) {
    9721          28 :         svg->mContextPropsBits |= NS_STYLE_CONTEXT_PROPERTY_FILL;
    9722           3 :       } else if (atom == nsGkAtoms::stroke) {
    9723           0 :         svg->mContextPropsBits |= NS_STYLE_CONTEXT_PROPERTY_STROKE;
    9724           3 :       } else if (atom == nsGkAtoms::fill_opacity) {
    9725           3 :         svg->mContextPropsBits |= NS_STYLE_CONTEXT_PROPERTY_FILL_OPACITY;
    9726           0 :       } else if (atom == nsGkAtoms::stroke_opacity) {
    9727           0 :         svg->mContextPropsBits |= NS_STYLE_CONTEXT_PROPERTY_STROKE_OPACITY;
    9728             :       }
    9729             :     }
    9730          28 :     break;
    9731             :   }
    9732             : 
    9733             :   case eCSSUnit_Inherit:
    9734             :   case eCSSUnit_Unset:
    9735           0 :     svg->mContextProps = parentSVG->mContextProps;
    9736           0 :     svg->mContextPropsBits = parentSVG->mContextPropsBits;
    9737           0 :     conditions.SetUncacheable();
    9738           0 :     break;
    9739             : 
    9740             :   case eCSSUnit_Initial:
    9741             :   case eCSSUnit_None:
    9742           0 :     svg->mContextProps.Clear();
    9743           0 :     svg->mContextPropsBits = 0;
    9744           0 :     break;
    9745             : 
    9746             :   default:
    9747           0 :     MOZ_ASSERT(false, "unrecognized -moz-context-properties value");
    9748             :   }
    9749             : 
    9750         132 :   COMPUTE_END_INHERITED(SVG, svg)
    9751             : }
    9752             : 
    9753             : static already_AddRefed<StyleBasicShape>
    9754           0 : GetStyleBasicShapeFromCSSValue(const nsCSSValue& aValue,
    9755             :                                GeckoStyleContext* aStyleContext,
    9756             :                                nsPresContext* aPresContext,
    9757             :                                RuleNodeCacheConditions& aConditions)
    9758             : {
    9759           0 :   RefPtr<StyleBasicShape> basicShape;
    9760             : 
    9761           0 :   nsCSSValue::Array* shapeFunction = aValue.GetArrayValue();
    9762             :   nsCSSKeyword functionName =
    9763           0 :     (nsCSSKeyword)shapeFunction->Item(0).GetIntValue();
    9764             : 
    9765           0 :   if (functionName == eCSSKeyword_polygon) {
    9766           0 :     MOZ_ASSERT(!basicShape, "did not expect value");
    9767           0 :     basicShape = new StyleBasicShape(StyleBasicShapeType::Polygon);
    9768           0 :     MOZ_ASSERT(shapeFunction->Count() > 1,
    9769             :                "polygon has wrong number of arguments");
    9770           0 :     size_t j = 1;
    9771           0 :     if (shapeFunction->Item(j).GetUnit() == eCSSUnit_Enumerated) {
    9772             :       StyleFillRule rule;
    9773           0 :       SetEnumValueHelper::SetEnumeratedValue(rule, shapeFunction->Item(j));
    9774           0 :       basicShape->SetFillRule(rule);
    9775           0 :       ++j;
    9776             :     }
    9777             :     const int32_t mask = SETCOORD_PERCENT | SETCOORD_LENGTH |
    9778           0 :       SETCOORD_STORE_CALC;
    9779             :     const nsCSSValuePairList* curPair =
    9780           0 :       shapeFunction->Item(j).GetPairListValue();
    9781           0 :     nsTArray<nsStyleCoord>& coordinates = basicShape->Coordinates();
    9782           0 :     while (curPair) {
    9783           0 :       nsStyleCoord xCoord, yCoord;
    9784           0 :       DebugOnly<bool> didSetCoordX = SetCoord(curPair->mXValue, xCoord,
    9785           0 :                                               nsStyleCoord(), mask,
    9786             :                                               aStyleContext, aPresContext,
    9787           0 :                                               aConditions);
    9788           0 :       coordinates.AppendElement(xCoord);
    9789           0 :       MOZ_ASSERT(didSetCoordX, "unexpected x coordinate unit");
    9790           0 :       DebugOnly<bool> didSetCoordY = SetCoord(curPair->mYValue, yCoord,
    9791           0 :                                               nsStyleCoord(), mask,
    9792             :                                               aStyleContext, aPresContext,
    9793           0 :                                               aConditions);
    9794           0 :       coordinates.AppendElement(yCoord);
    9795           0 :       MOZ_ASSERT(didSetCoordY, "unexpected y coordinate unit");
    9796           0 :       curPair = curPair->mNext;
    9797             :     }
    9798           0 :   } else if (functionName == eCSSKeyword_circle ||
    9799             :              functionName == eCSSKeyword_ellipse) {
    9800           0 :     StyleBasicShapeType type = functionName == eCSSKeyword_circle ?
    9801             :       StyleBasicShapeType::Circle :
    9802           0 :       StyleBasicShapeType::Ellipse;
    9803           0 :     MOZ_ASSERT(!basicShape, "did not expect value");
    9804           0 :     basicShape = new StyleBasicShape(type);
    9805             :     const int32_t mask = SETCOORD_PERCENT | SETCOORD_LENGTH |
    9806           0 :       SETCOORD_STORE_CALC | SETCOORD_ENUMERATED;
    9807           0 :     size_t count = type == StyleBasicShapeType::Circle ? 2 : 3;
    9808           0 :     MOZ_ASSERT(shapeFunction->Count() == count + 1,
    9809             :                "unexpected arguments count");
    9810           0 :     MOZ_ASSERT(type == StyleBasicShapeType::Circle ||
    9811             :                (shapeFunction->Item(1).GetUnit() == eCSSUnit_Null) ==
    9812             :                (shapeFunction->Item(2).GetUnit() == eCSSUnit_Null),
    9813             :                "ellipse should have two radii or none");
    9814           0 :     for (size_t j = 1; j < count; ++j) {
    9815           0 :       const nsCSSValue& val = shapeFunction->Item(j);
    9816           0 :       nsStyleCoord radius;
    9817           0 :       if (val.GetUnit() != eCSSUnit_Null) {
    9818           0 :         DebugOnly<bool> didSetRadius = SetCoord(val, radius,
    9819           0 :                                                 nsStyleCoord(), mask,
    9820             :                                                 aStyleContext,
    9821             :                                                 aPresContext,
    9822           0 :                                                 aConditions);
    9823           0 :         MOZ_ASSERT(didSetRadius, "unexpected radius unit");
    9824             :       } else {
    9825           0 :         radius.SetEnumValue(StyleShapeRadius::ClosestSide);
    9826             :       }
    9827           0 :       basicShape->Coordinates().AppendElement(radius);
    9828             :     }
    9829           0 :     const nsCSSValue& positionVal = shapeFunction->Item(count);
    9830           0 :     if (positionVal.GetUnit() == eCSSUnit_Array) {
    9831           0 :       ComputePositionValue(aStyleContext, positionVal,
    9832             :                            basicShape->GetPosition(),
    9833           0 :                            aConditions);
    9834             :     } else {
    9835           0 :       MOZ_ASSERT(positionVal.GetUnit() == eCSSUnit_Null,
    9836             :                  "expected no value");
    9837           0 :     }
    9838           0 :   } else if (functionName == eCSSKeyword_inset) {
    9839           0 :     MOZ_ASSERT(!basicShape, "did not expect value");
    9840           0 :     basicShape = new StyleBasicShape(StyleBasicShapeType::Inset);
    9841           0 :     MOZ_ASSERT(shapeFunction->Count() == 6,
    9842             :                "inset function has wrong number of arguments");
    9843           0 :     MOZ_ASSERT(shapeFunction->Item(1).GetUnit() != eCSSUnit_Null,
    9844             :                "no shape arguments defined");
    9845             :     const int32_t mask = SETCOORD_PERCENT | SETCOORD_LENGTH |
    9846           0 :       SETCOORD_STORE_CALC;
    9847           0 :     nsTArray<nsStyleCoord>& coords = basicShape->Coordinates();
    9848           0 :     for (size_t j = 1; j <= 4; ++j) {
    9849           0 :       const nsCSSValue& val = shapeFunction->Item(j);
    9850           0 :       nsStyleCoord inset;
    9851             :       // Fill missing values to get 4 at the end.
    9852           0 :       if (val.GetUnit() == eCSSUnit_Null) {
    9853           0 :         if (j == 4) {
    9854           0 :           inset = coords[1];
    9855             :         } else {
    9856           0 :           MOZ_ASSERT(j != 1, "first argument not specified");
    9857           0 :           inset = coords[0];
    9858             :         }
    9859             :       } else {
    9860           0 :         DebugOnly<bool> didSetInset = SetCoord(val, inset,
    9861           0 :                                                nsStyleCoord(), mask,
    9862             :                                                aStyleContext, aPresContext,
    9863           0 :                                                aConditions);
    9864           0 :         MOZ_ASSERT(didSetInset, "unexpected inset unit");
    9865             :       }
    9866           0 :       coords.AppendElement(inset);
    9867             :     }
    9868             : 
    9869           0 :     nsStyleCorners& insetRadius = basicShape->GetRadius();
    9870           0 :     if (shapeFunction->Item(5).GetUnit() == eCSSUnit_Array) {
    9871           0 :       nsCSSValue::Array* radiiArray = shapeFunction->Item(5).GetArrayValue();
    9872           0 :       NS_FOR_CSS_FULL_CORNERS(corner) {
    9873           0 :         int cx = FullToHalfCorner(corner, false);
    9874           0 :         int cy = FullToHalfCorner(corner, true);
    9875           0 :         const nsCSSValue& radius = radiiArray->Item(corner);
    9876           0 :         nsStyleCoord coordX, coordY;
    9877           0 :         DebugOnly<bool> didSetRadii = SetPairCoords(radius, coordX, coordY,
    9878           0 :                                                     nsStyleCoord(),
    9879           0 :                                                     nsStyleCoord(), mask,
    9880             :                                                     aStyleContext,
    9881             :                                                     aPresContext,
    9882           0 :                                                     aConditions);
    9883           0 :         MOZ_ASSERT(didSetRadii, "unexpected radius unit");
    9884           0 :         insetRadius.Set(cx, coordX);
    9885           0 :         insetRadius.Set(cy, coordY);
    9886             :       }
    9887             :     } else {
    9888           0 :       MOZ_ASSERT(shapeFunction->Item(5).GetUnit() == eCSSUnit_Null,
    9889             :                  "unexpected value");
    9890             :       // Initialize border-radius
    9891           0 :       nsStyleCoord zero;
    9892           0 :       zero.SetCoordValue(0);
    9893           0 :       NS_FOR_CSS_HALF_CORNERS(j) {
    9894           0 :         insetRadius.Set(j, zero);
    9895             :       }
    9896             :     }
    9897             :   } else {
    9898           0 :     NS_NOTREACHED("unexpected basic shape function");
    9899             :   }
    9900             : 
    9901           0 :   return basicShape.forget();
    9902             : }
    9903             : 
    9904             : static void
    9905           0 : SetStyleShapeSourceToCSSValue(
    9906             :   StyleShapeSource* aShapeSource,
    9907             :   const nsCSSValue* aValue,
    9908             :   GeckoStyleContext* aStyleContext,
    9909             :   nsPresContext* aPresContext,
    9910             :   RuleNodeCacheConditions& aConditions)
    9911             : {
    9912           0 :   MOZ_ASSERT(aValue->GetUnit() == eCSSUnit_Array,
    9913             :              "expected a basic shape or reference box");
    9914             : 
    9915           0 :   const nsCSSValue::Array* array = aValue->GetArrayValue();
    9916           0 :   MOZ_ASSERT(array->Count() == 1 || array->Count() == 2,
    9917             :              "Expect one or both of a shape function and a reference box");
    9918             : 
    9919           0 :   StyleGeometryBox referenceBox = StyleGeometryBox::NoBox;
    9920           0 :   RefPtr<StyleBasicShape> basicShape;
    9921             : 
    9922           0 :   for (size_t i = 0; i < array->Count(); ++i) {
    9923           0 :     const nsCSSValue& item = array->Item(i);
    9924           0 :     if (item.GetUnit() == eCSSUnit_Enumerated) {
    9925           0 :       referenceBox = static_cast<StyleGeometryBox>(item.GetIntValue());
    9926           0 :     } else if (item.GetUnit() == eCSSUnit_Function) {
    9927           0 :       basicShape = GetStyleBasicShapeFromCSSValue(item, aStyleContext,
    9928           0 :                                                   aPresContext, aConditions);
    9929             :     } else {
    9930           0 :       MOZ_ASSERT_UNREACHABLE("Unexpected unit!");
    9931             :       return;
    9932             :     }
    9933             :   }
    9934             : 
    9935           0 :   if (basicShape) {
    9936           0 :     aShapeSource->SetBasicShape(basicShape, referenceBox);
    9937             :   } else {
    9938           0 :     aShapeSource->SetReferenceBox(referenceBox);
    9939             :   }
    9940           0 : }
    9941             : 
    9942             : // Returns true if the nsStyleFilter was successfully set using the nsCSSValue.
    9943             : static bool
    9944           0 : SetStyleFilterToCSSValue(nsStyleFilter* aStyleFilter,
    9945             :                          const nsCSSValue& aValue,
    9946             :                          GeckoStyleContext* aStyleContext,
    9947             :                          nsPresContext* aPresContext,
    9948             :                          RuleNodeCacheConditions& aConditions)
    9949             : {
    9950           0 :   nsCSSUnit unit = aValue.GetUnit();
    9951           0 :   if (unit == eCSSUnit_URL) {
    9952           0 :     return aStyleFilter->SetURL(aValue.GetURLStructValue());
    9953             :   }
    9954             : 
    9955           0 :   MOZ_ASSERT(unit == eCSSUnit_Function, "expected a filter function");
    9956             : 
    9957           0 :   nsCSSValue::Array* filterFunction = aValue.GetArrayValue();
    9958             :   nsCSSKeyword functionName =
    9959           0 :     (nsCSSKeyword)filterFunction->Item(0).GetIntValue();
    9960             : 
    9961             :   int32_t type;
    9962             :   DebugOnly<bool> foundKeyword =
    9963           0 :     nsCSSProps::FindKeyword(functionName,
    9964             :                             nsCSSProps::kFilterFunctionKTable,
    9965           0 :                             type);
    9966           0 :   MOZ_ASSERT(foundKeyword, "unknown filter type");
    9967           0 :   if (type == NS_STYLE_FILTER_DROP_SHADOW) {
    9968           0 :     RefPtr<nsCSSShadowArray> shadowArray = GetShadowData(
    9969           0 :       filterFunction->Item(1).GetListValue(),
    9970             :       aStyleContext,
    9971             :       false,
    9972             :       aPresContext,
    9973           0 :       aConditions);
    9974           0 :     aStyleFilter->SetDropShadow(shadowArray);
    9975           0 :     return true;
    9976             :   }
    9977             : 
    9978           0 :   int32_t mask = SETCOORD_PERCENT | SETCOORD_FACTOR;
    9979           0 :   if (type == NS_STYLE_FILTER_BLUR) {
    9980           0 :     mask = SETCOORD_LENGTH |
    9981             :            SETCOORD_CALC_LENGTH_ONLY |
    9982             :            SETCOORD_CALC_CLAMP_NONNEGATIVE;
    9983           0 :   } else if (type == NS_STYLE_FILTER_HUE_ROTATE) {
    9984           0 :     mask = SETCOORD_ANGLE;
    9985             :   }
    9986             : 
    9987           0 :   MOZ_ASSERT(filterFunction->Count() == 2,
    9988             :              "all filter functions should have exactly one argument");
    9989             : 
    9990           0 :   nsCSSValue& arg = filterFunction->Item(1);
    9991           0 :   nsStyleCoord filterParameter;
    9992           0 :   DebugOnly<bool> didSetCoord = SetCoord(arg, filterParameter,
    9993           0 :                                          nsStyleCoord(), mask,
    9994             :                                          aStyleContext, aPresContext,
    9995           0 :                                          aConditions);
    9996           0 :   aStyleFilter->SetFilterParameter(filterParameter, type);
    9997           0 :   MOZ_ASSERT(didSetCoord, "unexpected unit");
    9998           0 :   return true;
    9999             : }
   10000             : 
   10001             : const void*
   10002          30 : nsRuleNode::ComputeSVGResetData(void* aStartStruct,
   10003             :                                 const nsRuleData* aRuleData,
   10004             :                                 GeckoStyleContext* aContext,
   10005             :                                 nsRuleNode* aHighestNode,
   10006             :                                 const RuleDetail aRuleDetail,
   10007             :                                 const RuleNodeCacheConditions aConditions)
   10008             : {
   10009          60 :   COMPUTE_START_RESET(SVGReset, svgReset, parentSVGReset)
   10010             : 
   10011             :   // stop-color:
   10012          30 :   const nsCSSValue* stopColorValue = aRuleData->ValueForStopColor();
   10013          60 :   if (eCSSUnit_Initial == stopColorValue->GetUnit() ||
   10014          30 :       eCSSUnit_Unset == stopColorValue->GetUnit()) {
   10015           0 :     svgReset->mStopColor = NS_RGB(0, 0, 0);
   10016             :   } else {
   10017          60 :     SetColor(*stopColorValue, parentSVGReset->mStopColor,
   10018          60 :              mPresContext, aContext, svgReset->mStopColor, conditions);
   10019             :   }
   10020             : 
   10021             :   // flood-color:
   10022          30 :   const nsCSSValue* floodColorValue = aRuleData->ValueForFloodColor();
   10023          60 :   if (eCSSUnit_Initial == floodColorValue->GetUnit() ||
   10024          30 :       eCSSUnit_Unset == floodColorValue->GetUnit()) {
   10025           0 :     svgReset->mFloodColor = NS_RGB(0, 0, 0);
   10026             :   } else {
   10027          60 :     SetColor(*floodColorValue, parentSVGReset->mFloodColor,
   10028          60 :              mPresContext, aContext, svgReset->mFloodColor, conditions);
   10029             :   }
   10030             : 
   10031             :   // lighting-color:
   10032          30 :   const nsCSSValue* lightingColorValue = aRuleData->ValueForLightingColor();
   10033          60 :   if (eCSSUnit_Initial == lightingColorValue->GetUnit() ||
   10034          30 :       eCSSUnit_Unset == lightingColorValue->GetUnit()) {
   10035           0 :     svgReset->mLightingColor = NS_RGB(255, 255, 255);
   10036             :   } else {
   10037          60 :     SetColor(*lightingColorValue, parentSVGReset->mLightingColor,
   10038          30 :              mPresContext, aContext, svgReset->mLightingColor,
   10039          30 :              conditions);
   10040             :   }
   10041             : 
   10042             :   // clip-path: url, <basic-shape> || <geometry-box>, none, inherit
   10043          30 :   const nsCSSValue* clipPathValue = aRuleData->ValueForClipPath();
   10044          30 :   switch (clipPathValue->GetUnit()) {
   10045             :     case eCSSUnit_Null:
   10046          28 :       break;
   10047             :     case eCSSUnit_None:
   10048             :     case eCSSUnit_Initial:
   10049             :     case eCSSUnit_Unset:
   10050           0 :       svgReset->mClipPath = StyleShapeSource();
   10051           0 :       break;
   10052             :     case eCSSUnit_Inherit:
   10053           0 :       conditions.SetUncacheable();
   10054           0 :       svgReset->mClipPath = parentSVGReset->mClipPath;
   10055           0 :       break;
   10056             :     case eCSSUnit_URL: {
   10057           2 :       svgReset->mClipPath = StyleShapeSource();
   10058           2 :       svgReset->mClipPath.SetURL(clipPathValue->GetURLStructValue());
   10059           2 :       break;
   10060             :     }
   10061             :     case eCSSUnit_Array: {
   10062           0 :       svgReset->mClipPath = StyleShapeSource();
   10063           0 :       SetStyleShapeSourceToCSSValue(&svgReset->mClipPath, clipPathValue, aContext,
   10064           0 :                                     mPresContext, conditions);
   10065           0 :       break;
   10066             :     }
   10067             :     default:
   10068           0 :       NS_NOTREACHED("unexpected unit");
   10069             :   }
   10070             : 
   10071             :   // stop-opacity:
   10072          30 :   SetFactor(*aRuleData->ValueForStopOpacity(),
   10073             :             svgReset->mStopOpacity, conditions,
   10074          30 :             parentSVGReset->mStopOpacity, 1.0f,
   10075          30 :             SETFCT_OPACITY | SETFCT_UNSET_INITIAL);
   10076             : 
   10077             :   // flood-opacity:
   10078          30 :   SetFactor(*aRuleData->ValueForFloodOpacity(),
   10079             :             svgReset->mFloodOpacity, conditions,
   10080          30 :             parentSVGReset->mFloodOpacity, 1.0f,
   10081          30 :             SETFCT_OPACITY | SETFCT_UNSET_INITIAL);
   10082             : 
   10083             :   // dominant-baseline: enum, inherit, initial
   10084          30 :   SetValue(*aRuleData->ValueForDominantBaseline(),
   10085             :            svgReset->mDominantBaseline,
   10086             :            conditions,
   10087             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
   10088          30 :            parentSVGReset->mDominantBaseline,
   10089          30 :            NS_STYLE_DOMINANT_BASELINE_AUTO);
   10090             : 
   10091             :   // vector-effect: enum, inherit, initial
   10092          30 :   SetValue(*aRuleData->ValueForVectorEffect(),
   10093             :            svgReset->mVectorEffect,
   10094             :            conditions,
   10095             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
   10096          30 :            parentSVGReset->mVectorEffect,
   10097          30 :            NS_STYLE_VECTOR_EFFECT_NONE);
   10098             : 
   10099             :   // mask-type: enum, inherit, initial
   10100          30 :   SetValue(*aRuleData->ValueForMaskType(),
   10101             :            svgReset->mMaskType,
   10102             :            conditions,
   10103             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
   10104          30 :            parentSVGReset->mMaskType,
   10105          30 :            NS_STYLE_MASK_TYPE_LUMINANCE);
   10106             : 
   10107             : #ifdef MOZ_ENABLE_MASK_AS_SHORTHAND
   10108          30 :   uint32_t maxItemCount = 1;
   10109          30 :   bool rebuild = false;
   10110             : 
   10111             :   // mask-image: none | <url> | <image-list> | <element-reference>  | <gradient>
   10112          60 :   nsStyleImage initialImage;
   10113          90 :   SetImageLayerList(aContext, *aRuleData->ValueForMaskImage(),
   10114             :                     svgReset->mMask.mLayers,
   10115             :                     parentSVGReset->mMask.mLayers,
   10116             :                     &nsStyleImageLayers::Layer::mImage,
   10117          30 :                     initialImage, parentSVGReset->mMask.mImageCount,
   10118             :                     svgReset->mMask.mImageCount,
   10119          30 :                     maxItemCount, rebuild, conditions);
   10120             : 
   10121             :   // mask-repeat: enum, inherit, initial [pair list]
   10122          30 :   nsStyleImageLayers::Repeat initialRepeat;
   10123          30 :   initialRepeat.SetInitialValues();
   10124          60 :   SetImageLayerPairList(aContext, *aRuleData->ValueForMaskRepeat(),
   10125             :                         svgReset->mMask.mLayers,
   10126             :                         parentSVGReset->mMask.mLayers,
   10127             :                         &nsStyleImageLayers::Layer::mRepeat,
   10128          30 :                         initialRepeat, parentSVGReset->mMask.mRepeatCount,
   10129             :                         svgReset->mMask.mRepeatCount, maxItemCount, rebuild,
   10130          30 :                         conditions);
   10131             : 
   10132             :   // mask-clip: enum, inherit, initial [list]
   10133          60 :   SetImageLayerList(aContext, *aRuleData->ValueForMaskClip(),
   10134             :                     svgReset->mMask.mLayers,
   10135             :                     parentSVGReset->mMask.mLayers,
   10136             :                     &nsStyleImageLayers::Layer::mClip,
   10137             :                     StyleGeometryBox::BorderBox,
   10138          30 :                     parentSVGReset->mMask.mClipCount,
   10139             :                     svgReset->mMask.mClipCount, maxItemCount, rebuild,
   10140          30 :                     conditions);
   10141             : 
   10142             :   // mask-origin: enum, inherit, initial [list]
   10143          60 :   SetImageLayerList(aContext, *aRuleData->ValueForMaskOrigin(),
   10144             :                     svgReset->mMask.mLayers,
   10145             :                     parentSVGReset->mMask.mLayers,
   10146             :                     &nsStyleImageLayers::Layer::mOrigin,
   10147             :                     StyleGeometryBox::BorderBox,
   10148          30 :                     parentSVGReset->mMask.mOriginCount,
   10149             :                     svgReset->mMask.mOriginCount, maxItemCount, rebuild,
   10150          30 :                     conditions);
   10151             : 
   10152             :   // mask-position-x/y: enum, length, percent (flags), inherit [list]
   10153             :   Position::Coord initialPositionCoord;
   10154          30 :   initialPositionCoord.mPercent = 0.0f;
   10155          30 :   initialPositionCoord.mLength = 0;
   10156          30 :   initialPositionCoord.mHasPercent = true;
   10157             : 
   10158          60 :   SetImageLayerPositionCoordList(
   10159          30 :                     aContext, *aRuleData->ValueForMaskPositionX(),
   10160             :                     svgReset->mMask.mLayers,
   10161             :                     parentSVGReset->mMask.mLayers,
   10162             :                     &Position::mXPosition,
   10163          30 :                     initialPositionCoord, parentSVGReset->mMask.mPositionXCount,
   10164             :                     svgReset->mMask.mPositionXCount, maxItemCount, rebuild,
   10165          30 :                     conditions);
   10166          60 :   SetImageLayerPositionCoordList(
   10167          30 :                     aContext, *aRuleData->ValueForMaskPositionY(),
   10168             :                     svgReset->mMask.mLayers,
   10169             :                     parentSVGReset->mMask.mLayers,
   10170             :                     &Position::mYPosition,
   10171          30 :                     initialPositionCoord, parentSVGReset->mMask.mPositionYCount,
   10172             :                     svgReset->mMask.mPositionYCount, maxItemCount, rebuild,
   10173          30 :                     conditions);
   10174             : 
   10175             :   // mask-size: enum, length, auto, inherit, initial [pair list]
   10176          30 :   nsStyleImageLayers::Size initialSize;
   10177          30 :   initialSize.SetInitialValues();
   10178          60 :   SetImageLayerPairList(aContext, *aRuleData->ValueForMaskSize(),
   10179             :                         svgReset->mMask.mLayers,
   10180             :                         parentSVGReset->mMask.mLayers,
   10181             :                         &nsStyleImageLayers::Layer::mSize,
   10182          30 :                         initialSize, parentSVGReset->mMask.mSizeCount,
   10183             :                         svgReset->mMask.mSizeCount, maxItemCount, rebuild,
   10184          30 :                         conditions);
   10185             : 
   10186             :   // mask-mode: enum, inherit, initial [list]
   10187          60 :   SetImageLayerList(aContext, *aRuleData->ValueForMaskMode(),
   10188             :                     svgReset->mMask.mLayers,
   10189             :                     parentSVGReset->mMask.mLayers,
   10190             :                     &nsStyleImageLayers::Layer::mMaskMode,
   10191             :                     uint8_t(NS_STYLE_MASK_MODE_MATCH_SOURCE),
   10192          30 :                     parentSVGReset->mMask.mMaskModeCount,
   10193          30 :                     svgReset->mMask.mMaskModeCount, maxItemCount, rebuild, conditions);
   10194             : 
   10195             :   // mask-composite: enum, inherit, initial [list]
   10196          60 :   SetImageLayerList(aContext, *aRuleData->ValueForMaskComposite(),
   10197             :                     svgReset->mMask.mLayers,
   10198             :                     parentSVGReset->mMask.mLayers,
   10199             :                     &nsStyleImageLayers::Layer::mComposite,
   10200             :                     uint8_t(NS_STYLE_MASK_COMPOSITE_ADD),
   10201          30 :                     parentSVGReset->mMask.mCompositeCount,
   10202          30 :                     svgReset->mMask.mCompositeCount, maxItemCount, rebuild, conditions);
   10203             : 
   10204          30 :   if (rebuild) {
   10205           2 :     FillAllBackgroundLists(svgReset->mMask, maxItemCount);
   10206             :   }
   10207             : #else
   10208             :   // mask: none | <url>
   10209             :   const nsCSSValue* maskValue = aRuleData->ValueForMask();
   10210             :   if (eCSSUnit_URL == maskValue->GetUnit()) {
   10211             :     svgReset->mMask.mLayers[0].mSourceURI = maskValue->GetURLStructValue();
   10212             :   } else if (eCSSUnit_None == maskValue->GetUnit() ||
   10213             :              eCSSUnit_Initial == maskValue->GetUnit() ||
   10214             :              eCSSUnit_Unset == maskValue->GetUnit()) {
   10215             :     svgReset->mMask.mLayers[0].mSourceURI = nullptr;
   10216             :   } else if (eCSSUnit_Inherit == maskValue->GetUnit()) {
   10217             :     conditions.SetUncacheable();
   10218             :     svgReset->mMask.mLayers[0].mSourceURI =
   10219             :       parentSVGReset->mMask.mLayers[0].mSourceURI;
   10220             :   }
   10221             : #endif
   10222             : 
   10223          60 :   COMPUTE_END_RESET(SVGReset, svgReset)
   10224             : }
   10225             : 
   10226             : const void*
   10227          12 : nsRuleNode::ComputeVariablesData(void* aStartStruct,
   10228             :                                  const nsRuleData* aRuleData,
   10229             :                                  GeckoStyleContext* aContext,
   10230             :                                  nsRuleNode* aHighestNode,
   10231             :                                  const RuleDetail aRuleDetail,
   10232             :                                  const RuleNodeCacheConditions aConditions)
   10233             : {
   10234          24 :   COMPUTE_START_INHERITED(Variables, variables, parentVariables)
   10235             : 
   10236          12 :   MOZ_ASSERT(aRuleData->mVariables,
   10237             :              "shouldn't be in ComputeVariablesData if there were no variable "
   10238             :              "declarations specified");
   10239             : 
   10240          24 :   CSSVariableResolver resolver(&variables->mVariables);
   10241          12 :   resolver.Resolve(&parentVariables->mVariables,
   10242          24 :                    aRuleData->mVariables);
   10243          12 :   conditions.SetUncacheable();
   10244             : 
   10245          24 :   COMPUTE_END_INHERITED(Variables, variables)
   10246             : }
   10247             : 
   10248             : const void*
   10249          87 : nsRuleNode::ComputeEffectsData(void* aStartStruct,
   10250             :                                const nsRuleData* aRuleData,
   10251             :                                GeckoStyleContext* aContext,
   10252             :                                nsRuleNode* aHighestNode,
   10253             :                                const RuleDetail aRuleDetail,
   10254             :                                const RuleNodeCacheConditions aConditions)
   10255             : {
   10256         174 :   COMPUTE_START_RESET(Effects, effects, parentEffects)
   10257             : 
   10258             :   // filter: url, none, inherit
   10259          87 :   const nsCSSValue* filterValue = aRuleData->ValueForFilter();
   10260          87 :   switch (filterValue->GetUnit()) {
   10261             :     case eCSSUnit_Null:
   10262          87 :       break;
   10263             :     case eCSSUnit_None:
   10264             :     case eCSSUnit_Initial:
   10265             :     case eCSSUnit_Unset:
   10266           0 :       effects->mFilters.Clear();
   10267           0 :       break;
   10268             :     case eCSSUnit_Inherit:
   10269           0 :       conditions.SetUncacheable();
   10270           0 :       effects->mFilters = parentEffects->mFilters;
   10271           0 :       break;
   10272             :     case eCSSUnit_List:
   10273             :     case eCSSUnit_ListDep: {
   10274           0 :       effects->mFilters.Clear();
   10275           0 :       const nsCSSValueList* cur = filterValue->GetListValue();
   10276           0 :       while (cur) {
   10277           0 :         nsStyleFilter styleFilter;
   10278           0 :         if (!SetStyleFilterToCSSValue(&styleFilter, cur->mValue, aContext,
   10279           0 :                                       mPresContext, conditions)) {
   10280           0 :           effects->mFilters.Clear();
   10281           0 :           break;
   10282             :         }
   10283           0 :         MOZ_ASSERT(styleFilter.GetType() != NS_STYLE_FILTER_NONE,
   10284             :                    "filter should be set");
   10285           0 :         effects->mFilters.AppendElement(styleFilter);
   10286           0 :         cur = cur->mNext;
   10287             :       }
   10288           0 :       break;
   10289             :     }
   10290             :     default:
   10291           0 :       NS_NOTREACHED("unexpected unit");
   10292             :   }
   10293             : 
   10294             :   // box-shadow: none, list, inherit, initial
   10295          87 :   const nsCSSValue* boxShadowValue = aRuleData->ValueForBoxShadow();
   10296          87 :   switch (boxShadowValue->GetUnit()) {
   10297             :   case eCSSUnit_Null:
   10298          81 :     break;
   10299             : 
   10300             :   case eCSSUnit_Initial:
   10301             :   case eCSSUnit_Unset:
   10302             :   case eCSSUnit_None:
   10303           0 :     effects->mBoxShadow = nullptr;
   10304           0 :     break;
   10305             : 
   10306             :   case eCSSUnit_Inherit:
   10307           0 :     effects->mBoxShadow = parentEffects->mBoxShadow;
   10308           0 :     conditions.SetUncacheable();
   10309           0 :     break;
   10310             : 
   10311             :   case eCSSUnit_List:
   10312             :   case eCSSUnit_ListDep:
   10313          12 :     effects->mBoxShadow = GetShadowData(boxShadowValue->GetListValue(),
   10314          12 :                                         aContext, true, mPresContext, conditions);
   10315           6 :     break;
   10316             : 
   10317             :   default:
   10318           0 :     MOZ_ASSERT(false, "unrecognized shadow unit");
   10319             :   }
   10320             : 
   10321             :   // clip property: length, auto, inherit
   10322          87 :   const nsCSSValue* clipValue = aRuleData->ValueForClip();
   10323          87 :   switch (clipValue->GetUnit()) {
   10324             :   case eCSSUnit_Inherit:
   10325           0 :     conditions.SetUncacheable();
   10326           0 :     effects->mClipFlags = parentEffects->mClipFlags;
   10327           0 :     effects->mClip = parentEffects->mClip;
   10328           0 :     break;
   10329             : 
   10330             :   case eCSSUnit_Initial:
   10331             :   case eCSSUnit_Unset:
   10332             :   case eCSSUnit_Auto:
   10333           0 :     effects->mClipFlags = NS_STYLE_CLIP_AUTO;
   10334           0 :     effects->mClip.SetRect(0,0,0,0);
   10335           0 :     break;
   10336             : 
   10337             :   case eCSSUnit_Null:
   10338          87 :     break;
   10339             : 
   10340             :   case eCSSUnit_Rect: {
   10341           0 :     const nsCSSRect& clipRect = clipValue->GetRectValue();
   10342             : 
   10343           0 :     effects->mClipFlags = NS_STYLE_CLIP_RECT;
   10344             : 
   10345           0 :     if (clipRect.mTop.GetUnit() == eCSSUnit_Auto) {
   10346           0 :       effects->mClip.y = 0;
   10347           0 :       effects->mClipFlags |= NS_STYLE_CLIP_TOP_AUTO;
   10348             :     }
   10349           0 :     else if (clipRect.mTop.IsLengthUnit()) {
   10350           0 :       effects->mClip.y = CalcLength(clipRect.mTop, aContext,
   10351           0 :                                     mPresContext, conditions);
   10352             :     }
   10353             : 
   10354           0 :     if (clipRect.mBottom.GetUnit() == eCSSUnit_Auto) {
   10355             :       // Setting to NS_MAXSIZE for the 'auto' case ensures that
   10356             :       // the clip rect is nonempty. It is important that mClip be
   10357             :       // nonempty if the actual clip rect could be nonempty.
   10358           0 :       effects->mClip.height = NS_MAXSIZE;
   10359           0 :       effects->mClipFlags |= NS_STYLE_CLIP_BOTTOM_AUTO;
   10360             :     }
   10361           0 :     else if (clipRect.mBottom.IsLengthUnit()) {
   10362           0 :       effects->mClip.height = CalcLength(clipRect.mBottom, aContext,
   10363           0 :                                          mPresContext, conditions) -
   10364           0 :                               effects->mClip.y;
   10365             :     }
   10366             : 
   10367           0 :     if (clipRect.mLeft.GetUnit() == eCSSUnit_Auto) {
   10368           0 :       effects->mClip.x = 0;
   10369           0 :       effects->mClipFlags |= NS_STYLE_CLIP_LEFT_AUTO;
   10370             :     }
   10371           0 :     else if (clipRect.mLeft.IsLengthUnit()) {
   10372           0 :       effects->mClip.x = CalcLength(clipRect.mLeft, aContext,
   10373           0 :                                     mPresContext, conditions);
   10374             :     }
   10375             : 
   10376           0 :     if (clipRect.mRight.GetUnit() == eCSSUnit_Auto) {
   10377             :       // Setting to NS_MAXSIZE for the 'auto' case ensures that
   10378             :       // the clip rect is nonempty. It is important that mClip be
   10379             :       // nonempty if the actual clip rect could be nonempty.
   10380           0 :       effects->mClip.width = NS_MAXSIZE;
   10381           0 :       effects->mClipFlags |= NS_STYLE_CLIP_RIGHT_AUTO;
   10382             :     }
   10383           0 :     else if (clipRect.mRight.IsLengthUnit()) {
   10384           0 :       effects->mClip.width = CalcLength(clipRect.mRight, aContext,
   10385           0 :                                         mPresContext, conditions) -
   10386           0 :                              effects->mClip.x;
   10387             :     }
   10388           0 :     break;
   10389             :   }
   10390             : 
   10391             :   default:
   10392           0 :     MOZ_ASSERT(false, "unrecognized clip unit");
   10393             :   }
   10394             : 
   10395             :   // opacity: factor, inherit, initial
   10396          87 :   SetFactor(*aRuleData->ValueForOpacity(), effects->mOpacity, conditions,
   10397          87 :             parentEffects->mOpacity, 1.0f,
   10398          87 :             SETFCT_OPACITY | SETFCT_UNSET_INITIAL);
   10399             : 
   10400             :   // mix-blend-mode: enum, inherit, initial
   10401          87 :   SetValue(*aRuleData->ValueForMixBlendMode(), effects->mMixBlendMode,
   10402             :            conditions,
   10403             :            SETVAL_ENUMERATED | SETVAL_UNSET_INITIAL,
   10404         174 :            parentEffects->mMixBlendMode, NS_STYLE_BLEND_NORMAL);
   10405             : 
   10406         174 :   COMPUTE_END_RESET(Effects, effects)
   10407             : }
   10408             : 
   10409             : const void*
   10410         827 : nsRuleNode::GetStyleData(nsStyleStructID aSID,
   10411             :                          GeckoStyleContext* aContext,
   10412             :                          bool aComputeData)
   10413             : {
   10414         827 :   NS_ASSERTION(IsUsedDirectly(),
   10415             :                "if we ever call this on rule nodes that aren't used "
   10416             :                "directly, we should adjust handling of mDependentBits "
   10417             :                "in some way.");
   10418         827 :   MOZ_ASSERT(!aContext->GetCachedStyleData(aSID),
   10419             :              "style context should not have cached data for struct");
   10420             : 
   10421             :   const void *data;
   10422             : 
   10423             :   // Never use cached data for animated style inside a pseudo-element;
   10424             :   // see comment on cacheability in AnimValuesStyleRule::MapRuleInfoInto.
   10425         827 :   if (!(HasAnimationData() && ParentHasPseudoElementData(aContext))) {
   10426         827 :     data = mStyleData.GetStyleData(aSID, aContext, aComputeData);
   10427         827 :     if (MOZ_LIKELY(data != nullptr)) {
   10428             :       // For inherited structs, mark the struct (which will be set on
   10429             :       // the context by our caller) as not being owned by the context.
   10430         318 :       if (!nsCachedStyleData::IsReset(aSID)) {
   10431           1 :         aContext->AddStyleBit(nsCachedStyleData::GetBitForSID(aSID));
   10432         317 :       } else if (HasAnimationData()) {
   10433             :         // If we have animation data, the struct should be cached on the style
   10434             :         // context so that we can peek the struct.
   10435             :         // See comment in AnimValuesStyleRule::MapRuleInfoInto.
   10436           0 :         StoreStyleOnContext(aContext, aSID, const_cast<void*>(data));
   10437             :       }
   10438             : 
   10439         318 :       return data; // We have a fully specified struct. Just return it.
   10440             :     }
   10441             :   }
   10442             : 
   10443         509 :   if (MOZ_UNLIKELY(!aComputeData))
   10444           0 :     return nullptr;
   10445             : 
   10446             :   // Nothing is cached.  We'll have to delve further and examine our rules.
   10447         509 :   data = WalkRuleTree(aSID, aContext);
   10448             : 
   10449         509 :   MOZ_ASSERT(data, "should have aborted on out-of-memory");
   10450         509 :   return data;
   10451             : }
   10452             : 
   10453             : void
   10454           0 : nsRuleNode::GetDiscretelyAnimatedCSSValue(nsCSSPropertyID aProperty,
   10455             :                                           nsCSSValue* aValue)
   10456             : {
   10457           0 :   for (nsRuleNode* node = this; node; node = node->GetParent()) {
   10458           0 :     nsIStyleRule* rule = node->GetRule();
   10459           0 :     if (!rule) {
   10460           0 :       continue;
   10461             :     }
   10462           0 :     if (rule->GetDiscretelyAnimatedCSSValue(aProperty, aValue)) {
   10463           0 :       return;
   10464             :     }
   10465             :   }
   10466             : }
   10467             : 
   10468             : /* static */ bool
   10469           0 : nsRuleNode::HasAuthorSpecifiedRules(nsStyleContext* aStyleContext,
   10470             :                                     uint32_t ruleTypeMask,
   10471             :                                     bool aAuthorColorsAllowed)
   10472             : {
   10473             : #ifdef MOZ_STYLO
   10474             :   if (aStyleContext->IsServo()) {
   10475             :     NS_WARNING("stylo: nsRuleNode::HasAuthorSpecifiedRules not implemented");
   10476             :     return true;
   10477             :   }
   10478             : #endif
   10479             : 
   10480           0 :   RefPtr<GeckoStyleContext> styleContext = aStyleContext->AsGecko();
   10481             : 
   10482           0 :   uint32_t inheritBits = 0;
   10483           0 :   if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BACKGROUND)
   10484           0 :     inheritBits |= NS_STYLE_INHERIT_BIT(Background);
   10485             : 
   10486           0 :   if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BORDER)
   10487           0 :     inheritBits |= NS_STYLE_INHERIT_BIT(Border);
   10488             : 
   10489           0 :   if (ruleTypeMask & NS_AUTHOR_SPECIFIED_PADDING)
   10490           0 :     inheritBits |= NS_STYLE_INHERIT_BIT(Padding);
   10491             : 
   10492           0 :   if (ruleTypeMask & NS_AUTHOR_SPECIFIED_TEXT_SHADOW)
   10493           0 :     inheritBits |= NS_STYLE_INHERIT_BIT(Text);
   10494             : 
   10495             :   // properties in the SIDS, whether or not we care about them
   10496           0 :   size_t nprops = 0,
   10497             :          backgroundOffset, borderOffset, paddingOffset, textShadowOffset;
   10498             : 
   10499             :   // We put the reset properties the start of the nsCSSValue array....
   10500             : 
   10501           0 :   if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BACKGROUND) {
   10502           0 :     backgroundOffset = nprops;
   10503           0 :     nprops += nsCSSProps::PropertyCountInStruct(eStyleStruct_Background);
   10504             :   }
   10505             : 
   10506           0 :   if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BORDER) {
   10507           0 :     borderOffset = nprops;
   10508           0 :     nprops += nsCSSProps::PropertyCountInStruct(eStyleStruct_Border);
   10509             :   }
   10510             : 
   10511           0 :   if (ruleTypeMask & NS_AUTHOR_SPECIFIED_PADDING) {
   10512           0 :     paddingOffset = nprops;
   10513           0 :     nprops += nsCSSProps::PropertyCountInStruct(eStyleStruct_Padding);
   10514             :   }
   10515             : 
   10516             :   // ...and the inherited properties at the end of the array.
   10517           0 :   size_t inheritedOffset = nprops;
   10518             : 
   10519           0 :   if (ruleTypeMask & NS_AUTHOR_SPECIFIED_TEXT_SHADOW) {
   10520           0 :     textShadowOffset = nprops;
   10521           0 :     nprops += nsCSSProps::PropertyCountInStruct(eStyleStruct_Text);
   10522             :   }
   10523             : 
   10524           0 :   void* dataStorage = alloca(nprops * sizeof(nsCSSValue));
   10525           0 :   AutoCSSValueArray dataArray(dataStorage, nprops);
   10526             : 
   10527             :   /* We're relying on the use of |styleContext| not mutating it! */
   10528             :   nsRuleData ruleData(inheritBits, dataArray.get(),
   10529           0 :                       styleContext->PresContext(), styleContext);
   10530             : 
   10531           0 :   if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BACKGROUND) {
   10532           0 :     ruleData.mValueOffsets[eStyleStruct_Background] = backgroundOffset;
   10533             :   }
   10534             : 
   10535           0 :   if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BORDER) {
   10536           0 :     ruleData.mValueOffsets[eStyleStruct_Border] = borderOffset;
   10537             :   }
   10538             : 
   10539           0 :   if (ruleTypeMask & NS_AUTHOR_SPECIFIED_PADDING) {
   10540           0 :     ruleData.mValueOffsets[eStyleStruct_Padding] = paddingOffset;
   10541             :   }
   10542             : 
   10543           0 :   if (ruleTypeMask & NS_AUTHOR_SPECIFIED_TEXT_SHADOW) {
   10544           0 :     ruleData.mValueOffsets[eStyleStruct_Text] = textShadowOffset;
   10545             :   }
   10546             : 
   10547             :   static const nsCSSPropertyID backgroundValues[] = {
   10548             :     eCSSProperty_background_color,
   10549             :     eCSSProperty_background_image,
   10550             :   };
   10551             : 
   10552             :   static const nsCSSPropertyID borderValues[] = {
   10553             :     eCSSProperty_border_top_color,
   10554             :     eCSSProperty_border_top_style,
   10555             :     eCSSProperty_border_top_width,
   10556             :     eCSSProperty_border_right_color,
   10557             :     eCSSProperty_border_right_style,
   10558             :     eCSSProperty_border_right_width,
   10559             :     eCSSProperty_border_bottom_color,
   10560             :     eCSSProperty_border_bottom_style,
   10561             :     eCSSProperty_border_bottom_width,
   10562             :     eCSSProperty_border_left_color,
   10563             :     eCSSProperty_border_left_style,
   10564             :     eCSSProperty_border_left_width,
   10565             :     eCSSProperty_border_top_left_radius,
   10566             :     eCSSProperty_border_top_right_radius,
   10567             :     eCSSProperty_border_bottom_right_radius,
   10568             :     eCSSProperty_border_bottom_left_radius,
   10569             :   };
   10570             : 
   10571             :   static const nsCSSPropertyID paddingValues[] = {
   10572             :     eCSSProperty_padding_top,
   10573             :     eCSSProperty_padding_right,
   10574             :     eCSSProperty_padding_bottom,
   10575             :     eCSSProperty_padding_left,
   10576             :   };
   10577             : 
   10578             :   static const nsCSSPropertyID textShadowValues[] = {
   10579             :     eCSSProperty_text_shadow
   10580             :   };
   10581             : 
   10582             :   // Number of properties we care about
   10583           0 :   size_t nValues = 0;
   10584             : 
   10585             :   nsCSSValue* values[MOZ_ARRAY_LENGTH(backgroundValues) +
   10586             :                      MOZ_ARRAY_LENGTH(borderValues) +
   10587             :                      MOZ_ARRAY_LENGTH(paddingValues) +
   10588             :                      MOZ_ARRAY_LENGTH(textShadowValues)];
   10589             : 
   10590             :   nsCSSPropertyID properties[MOZ_ARRAY_LENGTH(backgroundValues) +
   10591             :                            MOZ_ARRAY_LENGTH(borderValues) +
   10592             :                            MOZ_ARRAY_LENGTH(paddingValues) +
   10593             :                            MOZ_ARRAY_LENGTH(textShadowValues)];
   10594             : 
   10595           0 :   if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BACKGROUND) {
   10596           0 :     for (uint32_t i = 0, i_end = ArrayLength(backgroundValues);
   10597           0 :          i < i_end; ++i) {
   10598           0 :       properties[nValues] = backgroundValues[i];
   10599           0 :       values[nValues++] = ruleData.ValueFor(backgroundValues[i]);
   10600             :     }
   10601             :   }
   10602             : 
   10603           0 :   if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BORDER) {
   10604           0 :     for (uint32_t i = 0, i_end = ArrayLength(borderValues);
   10605           0 :          i < i_end; ++i) {
   10606           0 :       properties[nValues] = borderValues[i];
   10607           0 :       values[nValues++] = ruleData.ValueFor(borderValues[i]);
   10608             :     }
   10609             :   }
   10610             : 
   10611           0 :   if (ruleTypeMask & NS_AUTHOR_SPECIFIED_PADDING) {
   10612           0 :     for (uint32_t i = 0, i_end = ArrayLength(paddingValues);
   10613           0 :          i < i_end; ++i) {
   10614           0 :       properties[nValues] = paddingValues[i];
   10615           0 :       values[nValues++] = ruleData.ValueFor(paddingValues[i]);
   10616             :     }
   10617             :   }
   10618             : 
   10619           0 :   if (ruleTypeMask & NS_AUTHOR_SPECIFIED_TEXT_SHADOW) {
   10620           0 :     for (uint32_t i = 0, i_end = ArrayLength(textShadowValues);
   10621           0 :          i < i_end; ++i) {
   10622           0 :       properties[nValues] = textShadowValues[i];
   10623           0 :       values[nValues++] = ruleData.ValueFor(textShadowValues[i]);
   10624             :     }
   10625             :   }
   10626             : 
   10627           0 :   GeckoStyleContext* styleContextRef = styleContext;
   10628             : 
   10629             :   // We need to be careful not to count styles covered up by user-important or
   10630             :   // UA-important declarations.  But we do want to catch explicit inherit
   10631             :   // styling in those and check our parent style context to see whether we have
   10632             :   // user styling for those properties.  Note that we don't care here about
   10633             :   // inheritance due to lack of a specified value, since all the properties we
   10634             :   // care about are reset properties.
   10635             :   bool haveExplicitUAInherit;
   10636           0 :   do {
   10637           0 :     haveExplicitUAInherit = false;
   10638           0 :     for (nsRuleNode* ruleNode = styleContextRef->RuleNode(); ruleNode;
   10639             :          ruleNode = ruleNode->GetParent()) {
   10640           0 :       nsIStyleRule *rule = ruleNode->GetRule();
   10641           0 :       if (rule) {
   10642           0 :         ruleData.mLevel = ruleNode->GetLevel();
   10643           0 :         ruleData.mIsImportantRule = ruleNode->IsImportantRule();
   10644             : 
   10645           0 :         rule->MapRuleInfoInto(&ruleData);
   10646             : 
   10647           0 :         if (ruleData.mLevel == SheetType::Agent ||
   10648           0 :             ruleData.mLevel == SheetType::User) {
   10649             :           // This is a rule whose effect we want to ignore, so if any of
   10650             :           // the properties we care about were set, set them to the dummy
   10651             :           // value that they'll never otherwise get.
   10652           0 :           for (uint32_t i = 0; i < nValues; ++i) {
   10653           0 :             nsCSSUnit unit = values[i]->GetUnit();
   10654           0 :             if (unit != eCSSUnit_Null &&
   10655           0 :                 unit != eCSSUnit_Dummy &&
   10656             :                 unit != eCSSUnit_DummyInherit) {
   10657           0 :               if (unit == eCSSUnit_Inherit ||
   10658           0 :                   (i >= inheritedOffset && unit == eCSSUnit_Unset)) {
   10659           0 :                 haveExplicitUAInherit = true;
   10660           0 :                 values[i]->SetDummyInheritValue();
   10661             :               } else {
   10662           0 :                 values[i]->SetDummyValue();
   10663             :               }
   10664             :             }
   10665           0 :           }
   10666             :         } else {
   10667             :           // If any of the values we care about was set by the above rule,
   10668             :           // we have author style.
   10669           0 :           for (uint32_t i = 0; i < nValues; ++i) {
   10670           0 :             if (values[i]->GetUnit() != eCSSUnit_Null &&
   10671           0 :                 values[i]->GetUnit() != eCSSUnit_Dummy && // see above
   10672           0 :                 values[i]->GetUnit() != eCSSUnit_DummyInherit) {
   10673             :               // If author colors are not allowed, only claim to have
   10674             :               // author-specified rules if we're looking at a non-color
   10675             :               // property or if we're looking at the background color and it's
   10676             :               // set to transparent.  Anything else should get set to a dummy
   10677             :               // value instead.
   10678           0 :               if (aAuthorColorsAllowed ||
   10679           0 :                   !nsCSSProps::PropHasFlags(properties[i],
   10680           0 :                      CSS_PROPERTY_IGNORED_WHEN_COLORS_DISABLED) ||
   10681           0 :                   (properties[i] == eCSSProperty_background_color &&
   10682           0 :                    !values[i]->IsNonTransparentColor())) {
   10683           0 :                 return true;
   10684             :               }
   10685             : 
   10686           0 :               values[i]->SetDummyValue();
   10687             :             }
   10688             :           }
   10689             :         }
   10690             :       }
   10691             :     }
   10692             : 
   10693           0 :     if (haveExplicitUAInherit) {
   10694             :       // reset all the eCSSUnit_Null values to eCSSUnit_Dummy (since they're
   10695             :       // not styled by the author, or by anyone else), and then reset all the
   10696             :       // eCSSUnit_DummyInherit values to eCSSUnit_Null (so we will be able to
   10697             :       // detect them being styled by the author) and move up to our parent
   10698             :       // style context.
   10699           0 :       for (uint32_t i = 0; i < nValues; ++i)
   10700           0 :         if (values[i]->GetUnit() == eCSSUnit_Null)
   10701           0 :           values[i]->SetDummyValue();
   10702           0 :       for (uint32_t i = 0; i < nValues; ++i)
   10703           0 :         if (values[i]->GetUnit() == eCSSUnit_DummyInherit)
   10704           0 :           values[i]->Reset();
   10705           0 :       styleContextRef = styleContextRef->GetParent();
   10706             :     }
   10707           0 :   } while (haveExplicitUAInherit && styleContext);
   10708             : 
   10709           0 :   return false;
   10710             : }
   10711             : 
   10712             : /* static */ void
   10713           8 : nsRuleNode::ComputePropertiesOverridingAnimation(
   10714             :                               const nsTArray<nsCSSPropertyID>& aProperties,
   10715             :                               GeckoStyleContext* aStyleContext,
   10716             :                               nsCSSPropertyIDSet& aPropertiesOverridden)
   10717             : {
   10718             :   /*
   10719             :    * Set up an nsRuleData with all the structs needed for all of the
   10720             :    * properties in aProperties.
   10721             :    */
   10722           8 :   uint32_t structBits = 0;
   10723           8 :   size_t nprops = 0;
   10724             :   size_t offsets[nsStyleStructID_Length];
   10725          16 :   for (size_t propIdx = 0, propEnd = aProperties.Length();
   10726          16 :        propIdx < propEnd; ++propIdx) {
   10727           8 :     nsCSSPropertyID prop = aProperties[propIdx];
   10728           8 :     nsStyleStructID sid = nsCSSProps::kSIDTable[prop];
   10729           8 :     uint32_t bit = nsCachedStyleData::GetBitForSID(sid);
   10730           8 :     if (!(structBits & bit)) {
   10731           8 :       structBits |= bit;
   10732           8 :       offsets[sid] = nprops;
   10733           8 :       nprops += nsCSSProps::PropertyCountInStruct(sid);
   10734             :     }
   10735             :   }
   10736             : 
   10737           8 :   void* dataStorage = alloca(nprops * sizeof(nsCSSValue));
   10738          16 :   AutoCSSValueArray dataArray(dataStorage, nprops);
   10739             : 
   10740             :   // We're relying on the use of |aStyleContext| not mutating it!
   10741             :   nsRuleData ruleData(structBits, dataArray.get(),
   10742          16 :                       aStyleContext->PresContext(), aStyleContext);
   10743         200 :   for (nsStyleStructID sid = nsStyleStructID(0);
   10744         392 :        sid < nsStyleStructID_Length; sid = nsStyleStructID(sid + 1)) {
   10745         192 :     if (structBits & nsCachedStyleData::GetBitForSID(sid)) {
   10746           8 :       ruleData.mValueOffsets[sid] = offsets[sid];
   10747             :     }
   10748             :   }
   10749             : 
   10750             :   /*
   10751             :    * Actually walk up the rule tree until we're someplace less
   10752             :    * specific than animations.
   10753             :    */
   10754          14 :   for (nsRuleNode* ruleNode = aStyleContext->RuleNode(); ruleNode;
   10755             :        ruleNode = ruleNode->GetParent()) {
   10756          14 :     nsIStyleRule *rule = ruleNode->GetRule();
   10757          14 :     if (rule) {
   10758          14 :       ruleData.mLevel = ruleNode->GetLevel();
   10759          14 :       ruleData.mIsImportantRule = ruleNode->IsImportantRule();
   10760             : 
   10761             :       // Transitions are the only non-!important level overriding
   10762             :       // animations in the cascade ordering.  They also don't actually
   10763             :       // override animations, since transitions are suppressed when both
   10764             :       // are present.  And since we might not have called
   10765             :       // UpdateCascadeResults (which updates when they are suppressed
   10766             :       // due to the presence of animations for the same element and
   10767             :       // property) for transitions yet (which will make their
   10768             :       // MapRuleInfoInto skip the properties that are currently
   10769             :       // animating), we should skip them explicitly.
   10770          14 :       if (ruleData.mLevel == SheetType::Transition) {
   10771           6 :         continue;
   10772             :       }
   10773             : 
   10774           8 :       if (!ruleData.mIsImportantRule) {
   10775             :         // We're now equal to or less than the animation level; stop.
   10776           8 :         break;
   10777             :       }
   10778             : 
   10779           0 :       rule->MapRuleInfoInto(&ruleData);
   10780             :     }
   10781             :   }
   10782             : 
   10783             :   /*
   10784             :    * Fill in which properties were overridden.
   10785             :    */
   10786          16 :   for (size_t propIdx = 0, propEnd = aProperties.Length();
   10787          16 :        propIdx < propEnd; ++propIdx) {
   10788           8 :     nsCSSPropertyID prop = aProperties[propIdx];
   10789           8 :     if (ruleData.ValueFor(prop)->GetUnit() != eCSSUnit_Null) {
   10790           0 :       aPropertiesOverridden.AddProperty(prop);
   10791             :     }
   10792             :   }
   10793           8 : }
   10794             : 
   10795             : /* static */
   10796             : bool
   10797         152 : nsRuleNode::ComputeColor(const nsCSSValue& aValue, nsPresContext* aPresContext,
   10798             :                          nsStyleContext* aStyleContext, nscolor& aResult)
   10799             : {
   10800         152 :   MOZ_ASSERT(aValue.GetUnit() != eCSSUnit_Inherit,
   10801             :              "aValue shouldn't have eCSSUnit_Inherit");
   10802         152 :   MOZ_ASSERT(aValue.GetUnit() != eCSSUnit_Initial,
   10803             :              "aValue shouldn't have eCSSUnit_Initial");
   10804         152 :   MOZ_ASSERT(aValue.GetUnit() != eCSSUnit_Unset,
   10805             :              "aValue shouldn't have eCSSUnit_Unset");
   10806             : 
   10807         152 :   RuleNodeCacheConditions conditions;
   10808             :   bool ok = SetColor(aValue, NS_RGB(0, 0, 0), aPresContext, aStyleContext,
   10809         152 :                      aResult, conditions);
   10810         152 :   MOZ_ASSERT(ok || !(aPresContext && aStyleContext));
   10811         152 :   return ok;
   10812             : }
   10813             : 
   10814             : /* static */ bool
   10815         298 : nsRuleNode::ParentHasPseudoElementData(GeckoStyleContext* aContext)
   10816             : {
   10817         298 :   GeckoStyleContext* parent = aContext->GetParent();
   10818         298 :   return parent && parent->HasPseudoElementData();
   10819             : }
   10820             : 
   10821             : /* static */ void
   10822         130 : nsRuleNode::StoreStyleOnContext(GeckoStyleContext* aContext,
   10823             :                                 nsStyleStructID aSID,
   10824             :                                 void* aStruct)
   10825             : {
   10826         130 :   aContext->AddStyleBit(nsCachedStyleData::GetBitForSID(aSID));
   10827         130 :   aContext->SetStyle(aSID, aStruct);
   10828         130 : }
   10829             : 
   10830             : #ifdef DEBUG
   10831             : bool
   10832      286889 : nsRuleNode::ContextHasCachedData(GeckoStyleContext* aContext,
   10833             :                                  nsStyleStructID aSID)
   10834             : {
   10835      286889 :   return !!aContext->GetCachedStyleData(aSID);
   10836             : }
   10837             : #endif

Generated by: LCOV version 1.13