LCOV - code coverage report
Current view: directory - layout/style - nsRuleNode.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 2953 0 0.0 %
Date: 2012-04-21 Functions: 122 0 0.0 %

       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                 : /* ***** BEGIN LICENSE BLOCK *****
       4                 :  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
       5                 :  *
       6                 :  * The contents of this file are subject to the Mozilla Public License Version
       7                 :  * 1.1 (the "License"); you may not use this file except in compliance with
       8                 :  * the License. You may obtain a copy of the License at
       9                 :  * http://www.mozilla.org/MPL/
      10                 :  *
      11                 :  * Software distributed under the License is distributed on an "AS IS" basis,
      12                 :  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
      13                 :  * for the specific language governing rights and limitations under the
      14                 :  * License.
      15                 :  *
      16                 :  * The Original Code is Mozilla Communicator client code.
      17                 :  *
      18                 :  * The Initial Developer of the Original Code is
      19                 :  * Netscape Communications Corporation.
      20                 :  * Portions created by the Initial Developer are Copyright (C) 1998
      21                 :  * the Initial Developer. All Rights Reserved.
      22                 :  *
      23                 :  * Contributor(s):
      24                 :  *   Original Author: David W. Hyatt (hyatt@netscape.com)
      25                 :  *   Daniel Glazman <glazman@netscape.com>
      26                 :  *   Roger B. Sidje <rbs@maths.uq.edu.au>
      27                 :  *   Mats Palmgren <matspal@gmail.com>
      28                 :  *   L. David Baron <dbaron@dbaron.org>
      29                 :  *   Christian Biesinger <cbiesinger@web.de>
      30                 :  *   Michael Ventnor <m.ventnor@gmail.com>
      31                 :  *   Keith Rarick <kr@xph.us>
      32                 :  *   Jonathon Jongsma <jonathon.jongsma@collabora.co.uk>, Collabora Ltd.
      33                 :  *
      34                 :  * Alternatively, the contents of this file may be used under the terms of
      35                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      36                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      37                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      38                 :  * of those above. If you wish to allow use of your version of this file only
      39                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      40                 :  * use your version of this file under the terms of the MPL, indicate your
      41                 :  * decision by deleting the provisions above and replace them with the notice
      42                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      43                 :  * the provisions above, a recipient may use your version of this file under
      44                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      45                 :  *
      46                 :  * ***** END LICENSE BLOCK ***** */
      47                 : 
      48                 : /*
      49                 :  * a node in the lexicographic tree of rules that match an element,
      50                 :  * responsible for converting the rules' information into computed style
      51                 :  */
      52                 : 
      53                 : #include "nsRuleNode.h"
      54                 : #include "nscore.h"
      55                 : #include "nsIServiceManager.h"
      56                 : #include "nsIWidget.h"
      57                 : #include "mozilla/LookAndFeel.h"
      58                 : #include "nsIPresShell.h"
      59                 : #include "nsFontMetrics.h"
      60                 : #include "gfxFont.h"
      61                 : #include "nsStyleUtil.h"
      62                 : #include "nsCSSPseudoElements.h"
      63                 : #include "nsThemeConstants.h"
      64                 : #include "nsITheme.h"
      65                 : #include "pldhash.h"
      66                 : #include "nsStyleContext.h"
      67                 : #include "nsStyleSet.h"
      68                 : #include "nsSize.h"
      69                 : #include "imgIRequest.h"
      70                 : #include "nsRuleData.h"
      71                 : #include "nsIStyleRule.h"
      72                 : #include "nsBidiUtils.h"
      73                 : #include "nsUnicharUtils.h"
      74                 : #include "nsStyleStructInlines.h"
      75                 : #include "nsStyleTransformMatrix.h"
      76                 : #include "nsCSSKeywords.h"
      77                 : #include "nsCSSProps.h"
      78                 : #include "nsTArray.h"
      79                 : #include "nsContentUtils.h"
      80                 : #include "mozilla/dom/Element.h"
      81                 : #include "CSSCalc.h"
      82                 : #include "nsPrintfCString.h"
      83                 : #include "mozilla/Util.h"
      84                 : 
      85                 : #if defined(_MSC_VER) || defined(__MINGW32__)
      86                 : #include <malloc.h>
      87                 : #ifdef _MSC_VER
      88                 : #define alloca _alloca
      89                 : #endif
      90                 : #endif
      91                 : #ifdef SOLARIS
      92                 : #include <alloca.h>
      93                 : #endif
      94                 : 
      95                 : using namespace mozilla;
      96                 : using namespace mozilla::dom;
      97                 : 
      98                 : #define NS_SET_IMAGE_REQUEST(method_, context_, request_)                   \
      99                 :   if ((context_)->PresContext()->IsDynamic()) {                               \
     100                 :     method_(request_);                                                      \
     101                 :   } else {                                                                  \
     102                 :     nsCOMPtr<imgIRequest> req = nsContentUtils::GetStaticRequest(request_); \
     103                 :     method_(req);                                                           \
     104                 :   }
     105                 : 
     106                 : /*
     107                 :  * For storage of an |nsRuleNode|'s children in a PLDHashTable.
     108                 :  */
     109                 : 
     110                 : struct ChildrenHashEntry : public PLDHashEntryHdr {
     111                 :   // key is |mRuleNode->GetKey()|
     112                 :   nsRuleNode *mRuleNode;
     113                 : };
     114                 : 
     115                 : /* static */ PLDHashNumber
     116               0 : nsRuleNode::ChildrenHashHashKey(PLDHashTable *aTable, const void *aKey)
     117                 : {
     118                 :   const nsRuleNode::Key *key =
     119               0 :     static_cast<const nsRuleNode::Key*>(aKey);
     120                 :   // Disagreement on importance and level for the same rule is extremely
     121                 :   // rare, so hash just on the rule.
     122               0 :   return PL_DHashVoidPtrKeyStub(aTable, key->mRule);
     123                 : }
     124                 : 
     125                 : /* static */ bool
     126               0 : nsRuleNode::ChildrenHashMatchEntry(PLDHashTable *aTable,
     127                 :                                    const PLDHashEntryHdr *aHdr,
     128                 :                                    const void *aKey)
     129                 : {
     130                 :   const ChildrenHashEntry *entry =
     131               0 :     static_cast<const ChildrenHashEntry*>(aHdr);
     132                 :   const nsRuleNode::Key *key =
     133               0 :     static_cast<const nsRuleNode::Key*>(aKey);
     134               0 :   return entry->mRuleNode->GetKey() == *key;
     135                 : }
     136                 : 
     137                 : /* static */ PLDHashTableOps
     138                 : nsRuleNode::ChildrenHashOps = {
     139                 :   // It's probably better to allocate the table itself using malloc and
     140                 :   // free rather than the pres shell's arena because the table doesn't
     141                 :   // grow very often and the pres shell's arena doesn't recycle very
     142                 :   // large size allocations.
     143                 :   PL_DHashAllocTable,
     144                 :   PL_DHashFreeTable,
     145                 :   ChildrenHashHashKey,
     146                 :   ChildrenHashMatchEntry,
     147                 :   PL_DHashMoveEntryStub,
     148                 :   PL_DHashClearEntryStub,
     149                 :   PL_DHashFinalizeStub,
     150                 :   NULL
     151                 : };
     152                 : 
     153                 : 
     154                 : // EnsureBlockDisplay:
     155                 : //  - if the display value (argument) is not a block-type
     156                 : //    then we set it to a valid block display value
     157                 : //  - For enforcing the floated/positioned element CSS2 rules
     158               0 : static void EnsureBlockDisplay(PRUint8& display)
     159                 : {
     160                 :   // see if the display value is already a block
     161               0 :   switch (display) {
     162                 :   case NS_STYLE_DISPLAY_NONE :
     163                 :     // never change display:none *ever*
     164                 :   case NS_STYLE_DISPLAY_TABLE :
     165                 :   case NS_STYLE_DISPLAY_BLOCK :
     166                 :   case NS_STYLE_DISPLAY_LIST_ITEM :
     167                 :     // do not muck with these at all - already blocks
     168                 :     // This is equivalent to nsStyleDisplay::IsBlockOutside.  (XXX Maybe we
     169                 :     // should just call that?)
     170                 :     // This needs to match the check done in
     171                 :     // nsCSSFrameConstructor::FindMathMLData for <math>.
     172               0 :     break;
     173                 : 
     174                 :   case NS_STYLE_DISPLAY_INLINE_TABLE :
     175                 :     // make inline tables into tables
     176               0 :     display = NS_STYLE_DISPLAY_TABLE;
     177               0 :     break;
     178                 : 
     179                 :   default :
     180                 :     // make it a block
     181               0 :     display = NS_STYLE_DISPLAY_BLOCK;
     182                 :   }
     183               0 : }
     184                 : 
     185                 : static nscoord CalcLengthWith(const nsCSSValue& aValue,
     186                 :                               nscoord aFontSize,
     187                 :                               const nsStyleFont* aStyleFont,
     188                 :                               nsStyleContext* aStyleContext,
     189                 :                               nsPresContext* aPresContext,
     190                 :                               bool aUseProvidedRootEmSize,
     191                 :                               bool aUseUserFontSet,
     192                 :                               bool& aCanStoreInRuleTree);
     193                 : 
     194                 : struct CalcLengthCalcOps : public css::BasicCoordCalcOps,
     195                 :                            public css::NumbersAlreadyNormalizedOps
     196                 : {
     197                 :   // All of the parameters to CalcLengthWith except aValue.
     198                 :   const nscoord mFontSize;
     199                 :   const nsStyleFont* const mStyleFont;
     200                 :   nsStyleContext* const mStyleContext;
     201                 :   nsPresContext* const mPresContext;
     202                 :   const bool mUseProvidedRootEmSize;
     203                 :   const bool mUseUserFontSet;
     204                 :   bool& mCanStoreInRuleTree;
     205                 : 
     206               0 :   CalcLengthCalcOps(nscoord aFontSize, const nsStyleFont* aStyleFont,
     207                 :                     nsStyleContext* aStyleContext, nsPresContext* aPresContext,
     208                 :                     bool aUseProvidedRootEmSize, bool aUseUserFontSet,
     209                 :                     bool& aCanStoreInRuleTree)
     210                 :     : mFontSize(aFontSize),
     211                 :       mStyleFont(aStyleFont),
     212                 :       mStyleContext(aStyleContext),
     213                 :       mPresContext(aPresContext),
     214                 :       mUseProvidedRootEmSize(aUseProvidedRootEmSize),
     215                 :       mUseUserFontSet(aUseUserFontSet),
     216               0 :       mCanStoreInRuleTree(aCanStoreInRuleTree)
     217                 :   {
     218               0 :   }
     219                 : 
     220               0 :   result_type ComputeLeafValue(const nsCSSValue& aValue)
     221                 :   {
     222                 :     return CalcLengthWith(aValue, mFontSize, mStyleFont,
     223                 :                           mStyleContext, mPresContext, mUseProvidedRootEmSize,
     224               0 :                           mUseUserFontSet, mCanStoreInRuleTree);
     225                 :   }
     226                 : };
     227                 : 
     228               0 : static inline nscoord ScaleCoord(const nsCSSValue &aValue, float factor)
     229                 : {
     230               0 :   return NSToCoordRoundWithClamp(aValue.GetFloatValue() * factor);
     231                 : }
     232                 : 
     233                 : already_AddRefed<nsFontMetrics>
     234               0 : GetMetricsFor(nsPresContext* aPresContext,
     235                 :               nsStyleContext* aStyleContext,
     236                 :               const nsStyleFont* aStyleFont,
     237                 :               nscoord aFontSize, // overrides value from aStyleFont
     238                 :               bool aUseUserFontSet)
     239                 : {
     240               0 :   nsFont font = aStyleFont->mFont;
     241               0 :   font.size = aFontSize;
     242               0 :   gfxUserFontSet *fs = nsnull;
     243               0 :   if (aUseUserFontSet) {
     244               0 :     fs = aPresContext->GetUserFontSet();
     245                 :   }
     246               0 :   nsRefPtr<nsFontMetrics> fm;
     247                 :   aPresContext->DeviceContext()->GetMetricsFor(font,
     248                 :                                                aStyleFont->mLanguage,
     249               0 :                                                fs, *getter_AddRefs(fm));
     250               0 :   return fm.forget();
     251                 : }
     252                 : 
     253               0 : static nscoord CalcLengthWith(const nsCSSValue& aValue,
     254                 :                               nscoord aFontSize,
     255                 :                               const nsStyleFont* aStyleFont,
     256                 :                               nsStyleContext* aStyleContext,
     257                 :                               nsPresContext* aPresContext,
     258                 :                               bool aUseProvidedRootEmSize,
     259                 :                               // aUseUserFontSet should always be true
     260                 :                               // except when called from
     261                 :                               // CalcLengthWithInitialFont.
     262                 :                               bool aUseUserFontSet,
     263                 :                               bool& aCanStoreInRuleTree)
     264                 : {
     265               0 :   NS_ASSERTION(aValue.IsLengthUnit() || aValue.IsCalcUnit(),
     266                 :                "not a length or calc unit");
     267               0 :   NS_ASSERTION(aStyleFont || aStyleContext,
     268                 :                "Must have style data");
     269               0 :   NS_ASSERTION(!aStyleFont || !aStyleContext,
     270                 :                "Duplicate sources of data");
     271               0 :   NS_ASSERTION(aPresContext, "Must have prescontext");
     272                 : 
     273               0 :   if (aValue.IsFixedLengthUnit()) {
     274               0 :     return aValue.GetFixedLength(aPresContext);
     275                 :   }
     276               0 :   if (aValue.IsPixelLengthUnit()) {
     277               0 :     return aValue.GetPixelLength();
     278                 :   }
     279                 :   // Common code for all units other than pixel-based units and fixed-length
     280                 :   // units:
     281               0 :   aCanStoreInRuleTree = false;
     282                 :   const nsStyleFont *styleFont =
     283               0 :     aStyleFont ? aStyleFont : aStyleContext->GetStyleFont();
     284               0 :   if (aFontSize == -1) {
     285                 :     // XXX Should this be styleFont->mSize instead to avoid taking minfontsize
     286                 :     // prefs into account?
     287               0 :     aFontSize = styleFont->mFont.size;
     288                 :   }
     289               0 :   switch (aValue.GetUnit()) {
     290                 :     case eCSSUnit_RootEM: {
     291                 :       nscoord rootFontSize;
     292                 : 
     293               0 :       if (aUseProvidedRootEmSize) {
     294                 :         // We should use the provided aFontSize as the reference length to
     295                 :         // scale. This only happens when we are calculating font-size or
     296                 :         // an equivalent (scriptminsize or CalcLengthWithInitialFont) on
     297                 :         // the root element, in which case aFontSize is already the
     298                 :         // value we want.
     299               0 :         rootFontSize = aFontSize;
     300               0 :       } else if (aStyleContext && !aStyleContext->GetParent()) {
     301                 :         // This is the root element (XXX we don't really know this, but
     302                 :         // nsRuleNode::SetFont makes the same assumption!), so we should
     303                 :         // use GetStyleFont on this context to get the root element's
     304                 :         // font size.
     305               0 :         rootFontSize = styleFont->mFont.size;
     306                 :       } else {
     307                 :         // This is not the root element or we are calculating something other
     308                 :         // than font size, so rem is relative to the root element's font size.
     309               0 :         nsRefPtr<nsStyleContext> rootStyle;
     310               0 :         const nsStyleFont *rootStyleFont = styleFont;
     311               0 :         Element* docElement = aPresContext->Document()->GetRootElement();
     312                 : 
     313               0 :         if (docElement) {
     314                 :           rootStyle = aPresContext->StyleSet()->ResolveStyleFor(docElement,
     315               0 :                                                                 nsnull);
     316               0 :           if (rootStyle) {
     317               0 :             rootStyleFont = rootStyle->GetStyleFont();
     318                 :           }
     319                 :         }
     320                 : 
     321               0 :         rootFontSize = rootStyleFont->mFont.size;
     322                 :       }
     323                 : 
     324               0 :       return ScaleCoord(aValue, float(rootFontSize));
     325                 :     }
     326                 :     case eCSSUnit_EM: {
     327               0 :       return ScaleCoord(aValue, float(aFontSize));
     328                 :       // XXX scale against font metrics height instead?
     329                 :     }
     330                 :     case eCSSUnit_XHeight: {
     331                 :       nsRefPtr<nsFontMetrics> fm =
     332                 :         GetMetricsFor(aPresContext, aStyleContext, styleFont,
     333               0 :                       aFontSize, aUseUserFontSet);
     334               0 :       return ScaleCoord(aValue, float(fm->XHeight()));
     335                 :     }
     336                 :     case eCSSUnit_Char: {
     337                 :       nsRefPtr<nsFontMetrics> fm =
     338                 :         GetMetricsFor(aPresContext, aStyleContext, styleFont,
     339               0 :                       aFontSize, aUseUserFontSet);
     340               0 :       gfxFloat zeroWidth = (fm->GetThebesFontGroup()->GetFontAt(0)
     341               0 :                             ->GetMetrics().zeroOrAveCharWidth);
     342                 : 
     343               0 :       return ScaleCoord(aValue, ceil(aPresContext->AppUnitsPerDevPixel() *
     344               0 :                                      zeroWidth));
     345                 :     }
     346                 :     // For properties for which lengths are the *only* units accepted in
     347                 :     // calc(), we can handle calc() here and just compute a final
     348                 :     // result.  We ensure that we don't get to this code for other
     349                 :     // properties by not calling CalcLength in those cases:  SetCoord
     350                 :     // only calls CalcLength for a calc when it is appropriate to do so.
     351                 :     case eCSSUnit_Calc:
     352                 :     case eCSSUnit_Calc_Plus:
     353                 :     case eCSSUnit_Calc_Minus:
     354                 :     case eCSSUnit_Calc_Times_L:
     355                 :     case eCSSUnit_Calc_Times_R:
     356                 :     case eCSSUnit_Calc_Divided: {
     357                 :       CalcLengthCalcOps ops(aFontSize, aStyleFont,
     358                 :                             aStyleContext, aPresContext,
     359                 :                             aUseProvidedRootEmSize, aUseUserFontSet,
     360               0 :                             aCanStoreInRuleTree);
     361               0 :       return css::ComputeCalc(aValue, ops);
     362                 :     }
     363                 :     default:
     364               0 :       NS_NOTREACHED("unexpected unit");
     365                 :       break;
     366                 :   }
     367               0 :   return 0;
     368                 : }
     369                 : 
     370                 : /* static */ nscoord
     371               0 : nsRuleNode::CalcLength(const nsCSSValue& aValue,
     372                 :                        nsStyleContext* aStyleContext,
     373                 :                        nsPresContext* aPresContext,
     374                 :                        bool& aCanStoreInRuleTree)
     375                 : {
     376               0 :   NS_ASSERTION(aStyleContext, "Must have style data");
     377                 : 
     378                 :   return CalcLengthWith(aValue, -1, nsnull,
     379                 :                         aStyleContext, aPresContext,
     380               0 :                         false, true, aCanStoreInRuleTree);
     381                 : }
     382                 : 
     383                 : /* Inline helper function to redirect requests to CalcLength. */
     384               0 : static inline nscoord CalcLength(const nsCSSValue& aValue,
     385                 :                                  nsStyleContext* aStyleContext,
     386                 :                                  nsPresContext* aPresContext,
     387                 :                                  bool& aCanStoreInRuleTree)
     388                 : {
     389                 :   return nsRuleNode::CalcLength(aValue, aStyleContext,
     390               0 :                                 aPresContext, aCanStoreInRuleTree);
     391                 : }
     392                 : 
     393                 : /* static */ nscoord
     394               0 : nsRuleNode::CalcLengthWithInitialFont(nsPresContext* aPresContext,
     395                 :                                       const nsCSSValue& aValue)
     396                 : {
     397               0 :   nsStyleFont defaultFont(aPresContext); // FIXME: best language?
     398                 :   bool canStoreInRuleTree;
     399                 :   return CalcLengthWith(aValue, -1, &defaultFont,
     400                 :                         nsnull, aPresContext,
     401               0 :                         true, false, canStoreInRuleTree);
     402                 : }
     403                 : 
     404                 : struct LengthPercentPairCalcOps : public css::NumbersAlreadyNormalizedOps
     405                 : {
     406                 :   typedef nsRuleNode::ComputedCalc result_type;
     407                 : 
     408               0 :   LengthPercentPairCalcOps(nsStyleContext* aContext,
     409                 :                            nsPresContext* aPresContext,
     410                 :                            bool& aCanStoreInRuleTree)
     411                 :     : mContext(aContext),
     412                 :       mPresContext(aPresContext),
     413                 :       mCanStoreInRuleTree(aCanStoreInRuleTree),
     414               0 :       mHasPercent(false) {}
     415                 : 
     416                 :   nsStyleContext* mContext;
     417                 :   nsPresContext* mPresContext;
     418                 :   bool& mCanStoreInRuleTree;
     419                 :   bool mHasPercent;
     420                 : 
     421               0 :   result_type ComputeLeafValue(const nsCSSValue& aValue)
     422                 :   {
     423               0 :     if (aValue.GetUnit() == eCSSUnit_Percent) {
     424               0 :       mHasPercent = true;
     425               0 :       return result_type(0, aValue.GetPercentValue());
     426                 :     }
     427                 :     return result_type(CalcLength(aValue, mContext, mPresContext,
     428                 :                                   mCanStoreInRuleTree),
     429               0 :                        0.0f);
     430                 :   }
     431                 : 
     432                 :   result_type
     433               0 :   MergeAdditive(nsCSSUnit aCalcFunction,
     434                 :                 result_type aValue1, result_type aValue2)
     435                 :   {
     436               0 :     if (aCalcFunction == eCSSUnit_Calc_Plus) {
     437                 :       return result_type(NSCoordSaturatingAdd(aValue1.mLength,
     438                 :                                               aValue2.mLength),
     439               0 :                          aValue1.mPercent + aValue2.mPercent);
     440                 :     }
     441               0 :     NS_ABORT_IF_FALSE(aCalcFunction == eCSSUnit_Calc_Minus,
     442                 :                       "min() and max() are not allowed in calc() on "
     443                 :                       "transform");
     444                 :     return result_type(NSCoordSaturatingSubtract(aValue1.mLength,
     445                 :                                                  aValue2.mLength, 0),
     446               0 :                        aValue1.mPercent - aValue2.mPercent);
     447                 :   }
     448                 : 
     449                 :   result_type
     450               0 :   MergeMultiplicativeL(nsCSSUnit aCalcFunction,
     451                 :                        float aValue1, result_type aValue2)
     452                 :   {
     453               0 :     NS_ABORT_IF_FALSE(aCalcFunction == eCSSUnit_Calc_Times_L,
     454                 :                       "unexpected unit");
     455                 :     return result_type(NSCoordSaturatingMultiply(aValue2.mLength, aValue1),
     456               0 :                        aValue1 * aValue2.mPercent);
     457                 :   }
     458                 : 
     459                 :   result_type
     460               0 :   MergeMultiplicativeR(nsCSSUnit aCalcFunction,
     461                 :                        result_type aValue1, float aValue2)
     462                 :   {
     463               0 :     NS_ABORT_IF_FALSE(aCalcFunction == eCSSUnit_Calc_Times_R ||
     464                 :                       aCalcFunction == eCSSUnit_Calc_Divided,
     465                 :                       "unexpected unit");
     466               0 :     if (aCalcFunction == eCSSUnit_Calc_Divided) {
     467               0 :       aValue2 = 1.0f / aValue2;
     468                 :     }
     469                 :     return result_type(NSCoordSaturatingMultiply(aValue1.mLength, aValue2),
     470               0 :                        aValue1.mPercent * aValue2);
     471                 :   }
     472                 : 
     473                 : };
     474                 : 
     475                 : static void
     476               0 : SpecifiedCalcToComputedCalc(const nsCSSValue& aValue, nsStyleCoord& aCoord, 
     477                 :                             nsStyleContext* aStyleContext,
     478                 :                             bool& aCanStoreInRuleTree)
     479                 : {
     480                 :   LengthPercentPairCalcOps ops(aStyleContext, aStyleContext->PresContext(),
     481               0 :                                aCanStoreInRuleTree);
     482               0 :   nsRuleNode::ComputedCalc vals = ComputeCalc(aValue, ops);
     483                 : 
     484                 :   nsStyleCoord::Calc *calcObj =
     485               0 :     new (aStyleContext->Alloc(sizeof(nsStyleCoord::Calc))) nsStyleCoord::Calc;
     486                 :   // Because we use aStyleContext->Alloc(), we have to store the result
     487                 :   // on the style context and not in the rule tree.
     488               0 :   aCanStoreInRuleTree = false;
     489                 : 
     490               0 :   calcObj->mLength = vals.mLength;
     491               0 :   calcObj->mPercent = vals.mPercent;
     492               0 :   calcObj->mHasPercent = ops.mHasPercent;
     493                 : 
     494               0 :   aCoord.SetCalcValue(calcObj);
     495               0 : }
     496                 : 
     497                 : /* static */ nsRuleNode::ComputedCalc
     498               0 : nsRuleNode::SpecifiedCalcToComputedCalc(const nsCSSValue& aValue,
     499                 :                                         nsStyleContext* aStyleContext,
     500                 :                                         nsPresContext* aPresContext,
     501                 :                                         bool& aCanStoreInRuleTree)
     502                 : {
     503                 :   LengthPercentPairCalcOps ops(aStyleContext, aPresContext,
     504               0 :                                aCanStoreInRuleTree);
     505               0 :   return ComputeCalc(aValue, ops);
     506                 : }
     507                 : 
     508                 : // This is our public API for handling calc() expressions that involve
     509                 : // percentages.
     510                 : /* static */ nscoord
     511               0 : nsRuleNode::ComputeComputedCalc(const nsStyleCoord& aValue,
     512                 :                                 nscoord aPercentageBasis)
     513                 : {
     514               0 :   nsStyleCoord::Calc *calc = aValue.GetCalcValue();
     515                 :   return calc->mLength +
     516               0 :          NSToCoordFloorClamped(aPercentageBasis * calc->mPercent);
     517                 : }
     518                 : 
     519                 : /* static */ nscoord
     520               0 : nsRuleNode::ComputeCoordPercentCalc(const nsStyleCoord& aCoord,
     521                 :                                     nscoord aPercentageBasis)
     522                 : {
     523               0 :   switch (aCoord.GetUnit()) {
     524                 :     case eStyleUnit_Coord:
     525               0 :       return aCoord.GetCoordValue();
     526                 :     case eStyleUnit_Percent:
     527               0 :       return NSToCoordFloorClamped(aPercentageBasis * aCoord.GetPercentValue());
     528                 :     case eStyleUnit_Calc:
     529               0 :       return ComputeComputedCalc(aCoord, aPercentageBasis);
     530                 :     default:
     531               0 :       NS_ABORT_IF_FALSE(false, "unexpected unit");
     532               0 :       return 0;
     533                 :   }
     534                 : }
     535                 : 
     536                 : /* Given an enumerated value that represents a box position, converts it to
     537                 :  * a float representing the percentage of the box it corresponds to.  For
     538                 :  * example, "center" becomes 0.5f.
     539                 :  *
     540                 :  * @param aEnumValue The enumerated value.
     541                 :  * @return The float percent it corresponds to.
     542                 :  */
     543                 : static float
     544               0 : GetFloatFromBoxPosition(PRInt32 aEnumValue)
     545                 : {
     546               0 :   switch (aEnumValue) {
     547                 :   case NS_STYLE_BG_POSITION_LEFT:
     548                 :   case NS_STYLE_BG_POSITION_TOP:
     549               0 :     return 0.0f;
     550                 :   case NS_STYLE_BG_POSITION_RIGHT:
     551                 :   case NS_STYLE_BG_POSITION_BOTTOM:
     552               0 :     return 1.0f;
     553                 :   default:
     554               0 :     NS_NOTREACHED("unexpected value");
     555                 :     // fall through
     556                 :   case NS_STYLE_BG_POSITION_CENTER:
     557               0 :     return 0.5f;
     558                 :   }
     559                 : }
     560                 : 
     561                 : #define SETCOORD_NORMAL                 0x01   // N
     562                 : #define SETCOORD_AUTO                   0x02   // A
     563                 : #define SETCOORD_INHERIT                0x04   // H
     564                 : #define SETCOORD_PERCENT                0x08   // P
     565                 : #define SETCOORD_FACTOR                 0x10   // F
     566                 : #define SETCOORD_LENGTH                 0x20   // L
     567                 : #define SETCOORD_INTEGER                0x40   // I
     568                 : #define SETCOORD_ENUMERATED             0x80   // E
     569                 : #define SETCOORD_NONE                   0x100  // O
     570                 : #define SETCOORD_INITIAL_ZERO           0x200
     571                 : #define SETCOORD_INITIAL_AUTO           0x400
     572                 : #define SETCOORD_INITIAL_NONE           0x800
     573                 : #define SETCOORD_INITIAL_NORMAL         0x1000
     574                 : #define SETCOORD_INITIAL_HALF           0x2000
     575                 : #define SETCOORD_INITIAL_HUNDRED_PCT    0x00004000
     576                 : #define SETCOORD_INITIAL_FACTOR_ONE     0x00008000
     577                 : #define SETCOORD_INITIAL_FACTOR_ZERO    0x00010000
     578                 : #define SETCOORD_CALC_LENGTH_ONLY       0x00020000
     579                 : #define SETCOORD_CALC_CLAMP_NONNEGATIVE 0x00040000 // modifier for CALC_LENGTH_ONLY
     580                 : #define SETCOORD_STORE_CALC             0x00080000
     581                 : #define SETCOORD_BOX_POSITION           0x00100000 // exclusive with _ENUMERATED
     582                 : 
     583                 : #define SETCOORD_LP     (SETCOORD_LENGTH | SETCOORD_PERCENT)
     584                 : #define SETCOORD_LH     (SETCOORD_LENGTH | SETCOORD_INHERIT)
     585                 : #define SETCOORD_AH     (SETCOORD_AUTO | SETCOORD_INHERIT)
     586                 : #define SETCOORD_LAH    (SETCOORD_AUTO | SETCOORD_LENGTH | SETCOORD_INHERIT)
     587                 : #define SETCOORD_LPH    (SETCOORD_LP | SETCOORD_INHERIT)
     588                 : #define SETCOORD_LPAH   (SETCOORD_LP | SETCOORD_AH)
     589                 : #define SETCOORD_LPEH   (SETCOORD_LP | SETCOORD_ENUMERATED | SETCOORD_INHERIT)
     590                 : #define SETCOORD_LPAEH  (SETCOORD_LPAH | SETCOORD_ENUMERATED)
     591                 : #define SETCOORD_LPO    (SETCOORD_LP | SETCOORD_NONE)
     592                 : #define SETCOORD_LPOH   (SETCOORD_LPH | SETCOORD_NONE)
     593                 : #define SETCOORD_LPOEH  (SETCOORD_LPOH | SETCOORD_ENUMERATED)
     594                 : #define SETCOORD_LE     (SETCOORD_LENGTH | SETCOORD_ENUMERATED)
     595                 : #define SETCOORD_LEH    (SETCOORD_LE | SETCOORD_INHERIT)
     596                 : #define SETCOORD_IA     (SETCOORD_INTEGER | SETCOORD_AUTO)
     597                 : #define SETCOORD_LAE    (SETCOORD_LENGTH | SETCOORD_AUTO | SETCOORD_ENUMERATED)
     598                 : 
     599                 : // changes aCoord iff it returns true
     600               0 : static bool SetCoord(const nsCSSValue& aValue, nsStyleCoord& aCoord,
     601                 :                        const nsStyleCoord& aParentCoord,
     602                 :                        PRInt32 aMask, nsStyleContext* aStyleContext,
     603                 :                        nsPresContext* aPresContext,
     604                 :                        bool& aCanStoreInRuleTree)
     605                 : {
     606               0 :   bool result = true;
     607               0 :   if (aValue.GetUnit() == eCSSUnit_Null) {
     608               0 :     result = false;
     609                 :   }
     610               0 :   else if ((((aMask & SETCOORD_LENGTH) != 0) &&
     611               0 :             aValue.IsLengthUnit()) ||
     612                 :            (((aMask & SETCOORD_CALC_LENGTH_ONLY) != 0) &&
     613               0 :             aValue.IsCalcUnit())) {
     614                 :     nscoord len = CalcLength(aValue, aStyleContext, aPresContext,
     615               0 :                              aCanStoreInRuleTree);
     616               0 :     if ((aMask & SETCOORD_CALC_CLAMP_NONNEGATIVE) && len < 0) {
     617               0 :       NS_ASSERTION(aValue.IsCalcUnit(),
     618                 :                    "parser should have ensured no nonnegative lengths");
     619               0 :       len = 0;
     620                 :     }
     621               0 :     aCoord.SetCoordValue(len);
     622                 :   }
     623               0 :   else if (((aMask & SETCOORD_PERCENT) != 0) &&
     624               0 :            (aValue.GetUnit() == eCSSUnit_Percent)) {
     625               0 :     aCoord.SetPercentValue(aValue.GetPercentValue());
     626                 :   }
     627               0 :   else if (((aMask & SETCOORD_INTEGER) != 0) &&
     628               0 :            (aValue.GetUnit() == eCSSUnit_Integer)) {
     629               0 :     aCoord.SetIntValue(aValue.GetIntValue(), eStyleUnit_Integer);
     630                 :   }
     631               0 :   else if (((aMask & SETCOORD_ENUMERATED) != 0) &&
     632               0 :            (aValue.GetUnit() == eCSSUnit_Enumerated)) {
     633               0 :     aCoord.SetIntValue(aValue.GetIntValue(), eStyleUnit_Enumerated);
     634                 :   }
     635               0 :   else if (((aMask & SETCOORD_BOX_POSITION) != 0) &&
     636               0 :            (aValue.GetUnit() == eCSSUnit_Enumerated)) {
     637               0 :     aCoord.SetPercentValue(GetFloatFromBoxPosition(aValue.GetIntValue()));
     638                 :   }
     639               0 :   else if (((aMask & SETCOORD_AUTO) != 0) &&
     640               0 :            (aValue.GetUnit() == eCSSUnit_Auto)) {
     641               0 :     aCoord.SetAutoValue();
     642                 :   }
     643               0 :   else if (((aMask & SETCOORD_INHERIT) != 0) &&
     644               0 :            (aValue.GetUnit() == eCSSUnit_Inherit)) {
     645               0 :     aCoord = aParentCoord;  // just inherit value from parent
     646               0 :     aCanStoreInRuleTree = false;
     647                 :   }
     648               0 :   else if (((aMask & SETCOORD_NORMAL) != 0) &&
     649               0 :            (aValue.GetUnit() == eCSSUnit_Normal)) {
     650               0 :     aCoord.SetNormalValue();
     651                 :   }
     652               0 :   else if (((aMask & SETCOORD_NONE) != 0) &&
     653               0 :            (aValue.GetUnit() == eCSSUnit_None)) {
     654               0 :     aCoord.SetNoneValue();
     655                 :   }
     656               0 :   else if (((aMask & SETCOORD_FACTOR) != 0) &&
     657               0 :            (aValue.GetUnit() == eCSSUnit_Number)) {
     658               0 :     aCoord.SetFactorValue(aValue.GetFloatValue());
     659                 :   }
     660               0 :   else if (((aMask & SETCOORD_STORE_CALC) != 0) &&
     661               0 :            (aValue.IsCalcUnit())) {
     662                 :     SpecifiedCalcToComputedCalc(aValue, aCoord, aStyleContext,
     663               0 :                                 aCanStoreInRuleTree);
     664                 :   }
     665               0 :   else if (aValue.GetUnit() == eCSSUnit_Initial) {
     666               0 :     if ((aMask & SETCOORD_INITIAL_AUTO) != 0) {
     667               0 :       aCoord.SetAutoValue();
     668                 :     }
     669               0 :     else if ((aMask & SETCOORD_INITIAL_ZERO) != 0) {
     670               0 :       aCoord.SetCoordValue(0);
     671                 :     }
     672               0 :     else if ((aMask & SETCOORD_INITIAL_FACTOR_ZERO) != 0) {
     673               0 :       aCoord.SetFactorValue(0.0f);
     674                 :     }
     675               0 :     else if ((aMask & SETCOORD_INITIAL_NONE) != 0) {
     676               0 :       aCoord.SetNoneValue();
     677                 :     }
     678               0 :     else if ((aMask & SETCOORD_INITIAL_NORMAL) != 0) {
     679               0 :       aCoord.SetNormalValue();
     680                 :     }
     681               0 :     else if ((aMask & SETCOORD_INITIAL_HALF) != 0) {
     682               0 :       aCoord.SetPercentValue(0.5f);
     683                 :     }
     684               0 :     else if ((aMask & SETCOORD_INITIAL_HUNDRED_PCT) != 0) {
     685               0 :       aCoord.SetPercentValue(1.0f);
     686                 :     }
     687               0 :     else if ((aMask & SETCOORD_INITIAL_FACTOR_ONE) != 0) {
     688               0 :       aCoord.SetFactorValue(1.0f);
     689                 :     }
     690                 :     else {
     691               0 :       result = false;  // didn't set anything
     692                 :     }
     693                 :   }
     694                 :   else {
     695               0 :     result = false;  // didn't set anything
     696                 :   }
     697               0 :   return result;
     698                 : }
     699                 : 
     700                 : // This inline function offers a shortcut for SetCoord() by refusing to accept
     701                 : // SETCOORD_LENGTH and SETCOORD_INHERIT masks.
     702               0 : static inline bool SetAbsCoord(const nsCSSValue& aValue,
     703                 :                                  nsStyleCoord& aCoord,
     704                 :                                  PRInt32 aMask)
     705                 : {
     706               0 :   NS_ABORT_IF_FALSE((aMask & SETCOORD_LH) == 0,
     707                 :                     "does not handle SETCOORD_LENGTH and SETCOORD_INHERIT");
     708                 : 
     709                 :   // The values of the following variables will never be used; so it does not
     710                 :   // matter what to set.
     711               0 :   const nsStyleCoord dummyParentCoord;
     712               0 :   nsStyleContext* dummyStyleContext = nsnull;
     713               0 :   nsPresContext* dummyPresContext = nsnull;
     714               0 :   bool dummyCanStoreInRuleTree = true;
     715                 : 
     716                 :   bool rv = SetCoord(aValue, aCoord, dummyParentCoord, aMask,
     717                 :                        dummyStyleContext, dummyPresContext,
     718               0 :                        dummyCanStoreInRuleTree);
     719               0 :   NS_ABORT_IF_FALSE(dummyCanStoreInRuleTree,
     720                 :                     "SetCoord() should not modify dummyCanStoreInRuleTree.");
     721                 : 
     722               0 :   return rv;
     723                 : }
     724                 : 
     725                 : /* Given a specified value that might be a pair value, call SetCoord twice,
     726                 :  * either using each member of the pair, or using the unpaired value twice.
     727                 :  */
     728                 : static bool
     729               0 : SetPairCoords(const nsCSSValue& aValue,
     730                 :               nsStyleCoord& aCoordX, nsStyleCoord& aCoordY,
     731                 :               const nsStyleCoord& aParentX, const nsStyleCoord& aParentY,
     732                 :               PRInt32 aMask, nsStyleContext* aStyleContext,
     733                 :               nsPresContext* aPresContext, bool& aCanStoreInRuleTree)
     734                 : {
     735                 :   const nsCSSValue& valX =
     736               0 :     aValue.GetUnit() == eCSSUnit_Pair ? aValue.GetPairValue().mXValue : aValue;
     737                 :   const nsCSSValue& valY =
     738               0 :     aValue.GetUnit() == eCSSUnit_Pair ? aValue.GetPairValue().mYValue : aValue;
     739                 : 
     740                 :   bool cX = SetCoord(valX, aCoordX, aParentX, aMask, aStyleContext,
     741               0 :                        aPresContext, aCanStoreInRuleTree);
     742                 :   mozilla::DebugOnly<bool> cY = SetCoord(valY, aCoordY, aParentY, aMask, 
     743               0 :                        aStyleContext, aPresContext, aCanStoreInRuleTree);
     744               0 :   NS_ABORT_IF_FALSE(cX == cY, "changed one but not the other");
     745               0 :   return cX;
     746                 : }
     747                 : 
     748               0 : static bool SetColor(const nsCSSValue& aValue, const nscolor aParentColor,
     749                 :                        nsPresContext* aPresContext, nsStyleContext *aContext,
     750                 :                        nscolor& aResult, bool& aCanStoreInRuleTree)
     751                 : {
     752               0 :   bool    result = false;
     753               0 :   nsCSSUnit unit = aValue.GetUnit();
     754                 : 
     755               0 :   if (eCSSUnit_Color == unit) {
     756               0 :     aResult = aValue.GetColorValue();
     757               0 :     result = true;
     758                 :   }
     759               0 :   else if (eCSSUnit_Ident == unit) {
     760               0 :     nsAutoString  value;
     761               0 :     aValue.GetStringValue(value);
     762                 :     nscolor rgba;
     763               0 :     if (NS_ColorNameToRGB(value, &rgba)) {
     764               0 :       aResult = rgba;
     765               0 :       result = true;
     766                 :     }
     767                 :   }
     768               0 :   else if (eCSSUnit_EnumColor == unit) {
     769               0 :     PRInt32 intValue = aValue.GetIntValue();
     770               0 :     if (0 <= intValue) {
     771               0 :       LookAndFeel::ColorID colorID = (LookAndFeel::ColorID) intValue;
     772               0 :       if (NS_SUCCEEDED(LookAndFeel::GetColor(colorID, &aResult))) {
     773               0 :         result = true;
     774                 :       }
     775                 :     }
     776                 :     else {
     777               0 :       switch (intValue) {
     778                 :         case NS_COLOR_MOZ_HYPERLINKTEXT:
     779               0 :           aResult = aPresContext->DefaultLinkColor();
     780               0 :           break;
     781                 :         case NS_COLOR_MOZ_VISITEDHYPERLINKTEXT:
     782               0 :           aResult = aPresContext->DefaultVisitedLinkColor();
     783               0 :           break;
     784                 :         case NS_COLOR_MOZ_ACTIVEHYPERLINKTEXT:
     785               0 :           aResult = aPresContext->DefaultActiveLinkColor();
     786               0 :           break;
     787                 :         case NS_COLOR_CURRENTCOLOR:
     788                 :           // The data computed from this can't be shared in the rule tree
     789                 :           // because they could be used on a node with a different color
     790               0 :           aCanStoreInRuleTree = false;
     791               0 :           aResult = aContext->GetStyleColor()->mColor;
     792               0 :           break;
     793                 :         case NS_COLOR_MOZ_DEFAULT_COLOR:
     794               0 :           aResult = aPresContext->DefaultColor();
     795               0 :           break;
     796                 :         case NS_COLOR_MOZ_DEFAULT_BACKGROUND_COLOR:
     797               0 :           aResult = aPresContext->DefaultBackgroundColor();
     798               0 :           break;
     799                 :         default:
     800               0 :           NS_NOTREACHED("Should never have an unknown negative colorID.");
     801               0 :           break;
     802                 :       }
     803               0 :       result = true;
     804                 :     }
     805                 :   }
     806               0 :   else if (eCSSUnit_Inherit == unit) {
     807               0 :     aResult = aParentColor;
     808               0 :     result = true;
     809               0 :     aCanStoreInRuleTree = false;
     810                 :   }
     811               0 :   else if (eCSSUnit_Enumerated == unit &&
     812               0 :            aValue.GetIntValue() == NS_STYLE_COLOR_INHERIT_FROM_BODY) {
     813               0 :     NS_ASSERTION(aPresContext->CompatibilityMode() == eCompatibility_NavQuirks,
     814                 :                  "Should only get this value in quirks mode");
     815                 :     // We just grab the color from the prescontext, and rely on the fact that
     816                 :     // if the body color ever changes all its descendants will get new style
     817                 :     // contexts (but NOT necessarily new rulenodes).
     818               0 :     aResult = aPresContext->BodyTextColor();
     819               0 :     result = true;
     820               0 :     aCanStoreInRuleTree = false;
     821                 :   }
     822               0 :   return result;
     823                 : }
     824                 : 
     825               0 : static void SetGradientCoord(const nsCSSValue& aValue, nsPresContext* aPresContext,
     826                 :                              nsStyleContext* aContext, nsStyleCoord& aResult,
     827                 :                              bool& aCanStoreInRuleTree)
     828                 : {
     829                 :   // OK to pass bad aParentCoord since we're not passing SETCOORD_INHERIT
     830               0 :   if (!SetCoord(aValue, aResult, nsStyleCoord(),
     831                 :                 SETCOORD_LPO | SETCOORD_BOX_POSITION | SETCOORD_STORE_CALC,
     832               0 :                 aContext, aPresContext, aCanStoreInRuleTree)) {
     833               0 :     NS_NOTREACHED("unexpected unit for gradient anchor point");
     834               0 :     aResult.SetNoneValue();
     835                 :   }
     836               0 : }
     837                 : 
     838               0 : static void SetGradient(const nsCSSValue& aValue, nsPresContext* aPresContext,
     839                 :                         nsStyleContext* aContext, nsStyleGradient& aResult,
     840                 :                         bool& aCanStoreInRuleTree)
     841                 : {
     842               0 :   NS_ABORT_IF_FALSE(aValue.GetUnit() == eCSSUnit_Gradient,
     843                 :                     "The given data is not a gradient");
     844                 : 
     845               0 :   nsCSSValueGradient* gradient = aValue.GetGradientValue();
     846                 : 
     847               0 :   if (gradient->mIsRadial) {
     848               0 :     if (gradient->mRadialShape.GetUnit() == eCSSUnit_Enumerated) {
     849               0 :       aResult.mShape = gradient->mRadialShape.GetIntValue();
     850                 :     } else {
     851               0 :       NS_ASSERTION(gradient->mRadialShape.GetUnit() == eCSSUnit_None,
     852                 :                    "bad unit for radial shape");
     853               0 :       aResult.mShape = NS_STYLE_GRADIENT_SHAPE_ELLIPTICAL;
     854                 :     }
     855               0 :     if (gradient->mRadialSize.GetUnit() == eCSSUnit_Enumerated) {
     856               0 :       aResult.mSize = gradient->mRadialSize.GetIntValue();
     857                 :     } else {
     858               0 :       NS_ASSERTION(gradient->mRadialSize.GetUnit() == eCSSUnit_None,
     859                 :                    "bad unit for radial shape");
     860               0 :       aResult.mSize = NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER;
     861                 :     }
     862                 :   } else {
     863               0 :     NS_ASSERTION(gradient->mRadialShape.GetUnit() == eCSSUnit_None,
     864                 :                  "bad unit for linear shape");
     865               0 :     NS_ASSERTION(gradient->mRadialSize.GetUnit() == eCSSUnit_None,
     866                 :                  "bad unit for linear size");
     867               0 :     aResult.mShape = NS_STYLE_GRADIENT_SHAPE_LINEAR;
     868               0 :     aResult.mSize = NS_STYLE_GRADIENT_SIZE_FARTHEST_CORNER;
     869                 : 
     870               0 :     aResult.mToCorner = gradient->mIsToCorner;
     871                 :   }
     872                 : 
     873                 :   // bg-position
     874                 :   SetGradientCoord(gradient->mBgPos.mXValue, aPresContext, aContext,
     875               0 :                    aResult.mBgPosX, aCanStoreInRuleTree);
     876                 : 
     877                 :   SetGradientCoord(gradient->mBgPos.mYValue, aPresContext, aContext,
     878               0 :                    aResult.mBgPosY, aCanStoreInRuleTree);
     879                 : 
     880               0 :   aResult.mRepeating = gradient->mIsRepeating;
     881                 : 
     882                 :   // angle
     883               0 :   if (gradient->mAngle.IsAngularUnit()) {
     884                 :     nsStyleUnit unit;
     885               0 :     switch (gradient->mAngle.GetUnit()) {
     886               0 :     case eCSSUnit_Degree: unit = eStyleUnit_Degree; break;
     887               0 :     case eCSSUnit_Grad:   unit = eStyleUnit_Grad; break;
     888               0 :     case eCSSUnit_Radian: unit = eStyleUnit_Radian; break;
     889               0 :     case eCSSUnit_Turn:   unit = eStyleUnit_Turn; break;
     890               0 :     default: NS_NOTREACHED("unrecognized angular unit");
     891               0 :       unit = eStyleUnit_Degree;
     892                 :     }
     893               0 :     aResult.mAngle.SetAngleValue(gradient->mAngle.GetAngleValue(), unit);
     894                 :   } else {
     895               0 :     NS_ASSERTION(gradient->mAngle.GetUnit() == eCSSUnit_None,
     896                 :                  "bad unit for gradient angle");
     897               0 :     aResult.mAngle.SetNoneValue();
     898                 :   }
     899                 : 
     900                 :   // stops
     901               0 :   for (PRUint32 i = 0; i < gradient->mStops.Length(); i++) {
     902               0 :     nsStyleGradientStop stop;
     903               0 :     nsCSSValueGradientStop &valueStop = gradient->mStops[i];
     904                 : 
     905               0 :     if (!SetCoord(valueStop.mLocation, stop.mLocation,
     906                 :                   nsStyleCoord(), SETCOORD_LPO,
     907               0 :                   aContext, aPresContext, aCanStoreInRuleTree)) {
     908               0 :       NS_NOTREACHED("unexpected unit for gradient stop location");
     909                 :     }
     910                 : 
     911                 :     // inherit is not a valid color for stops, so we pass in a dummy
     912                 :     // parent color
     913               0 :     NS_ASSERTION(valueStop.mColor.GetUnit() != eCSSUnit_Inherit,
     914                 :                  "inherit is not a valid color for gradient stops");
     915                 :     SetColor(valueStop.mColor, NS_RGB(0, 0, 0), aPresContext,
     916               0 :              aContext, stop.mColor, aCanStoreInRuleTree);
     917                 : 
     918               0 :     aResult.mStops.AppendElement(stop);
     919                 :   }
     920               0 : }
     921                 : 
     922                 : // -moz-image-rect(<uri>, <top>, <right>, <bottom>, <left>)
     923               0 : static void SetStyleImageToImageRect(nsStyleContext* aStyleContext,
     924                 :                                      const nsCSSValue& aValue,
     925                 :                                      nsStyleImage& aResult)
     926                 : {
     927               0 :   NS_ABORT_IF_FALSE(aValue.GetUnit() == eCSSUnit_Function &&
     928                 :                     aValue.EqualsFunction(eCSSKeyword__moz_image_rect),
     929                 :                     "the value is not valid -moz-image-rect()");
     930                 : 
     931               0 :   nsCSSValue::Array* arr = aValue.GetArrayValue();
     932               0 :   NS_ABORT_IF_FALSE(arr && arr->Count() == 6, "invalid number of arguments");
     933                 : 
     934                 :   // <uri>
     935               0 :   if (arr->Item(1).GetUnit() == eCSSUnit_Image) {
     936               0 :     NS_SET_IMAGE_REQUEST(aResult.SetImageData,
     937                 :                          aStyleContext,
     938                 :                          arr->Item(1).GetImageValue())
     939                 :   } else {
     940               0 :     NS_WARNING("nsCSSValue::Image::Image() failed?");
     941                 :   }
     942                 : 
     943                 :   // <top>, <right>, <bottom>, <left>
     944               0 :   nsStyleSides cropRect;
     945               0 :   NS_FOR_CSS_SIDES(side) {
     946               0 :     nsStyleCoord coord;
     947               0 :     const nsCSSValue& val = arr->Item(2 + side);
     948                 : 
     949                 : #ifdef DEBUG
     950                 :     bool unitOk =
     951                 : #endif
     952               0 :       SetAbsCoord(val, coord, SETCOORD_FACTOR | SETCOORD_PERCENT);
     953               0 :     NS_ABORT_IF_FALSE(unitOk, "Incorrect data structure created by CSS parser");
     954               0 :     cropRect.Set(side, coord);
     955                 :   }
     956               0 :   aResult.SetCropRect(&cropRect);
     957               0 : }
     958                 : 
     959               0 : static void SetStyleImage(nsStyleContext* aStyleContext,
     960                 :                           const nsCSSValue& aValue,
     961                 :                           nsStyleImage& aResult,
     962                 :                           bool& aCanStoreInRuleTree)
     963                 : {
     964               0 :   aResult.SetNull();
     965                 : 
     966               0 :   switch (aValue.GetUnit()) {
     967                 :     case eCSSUnit_Image:
     968               0 :       NS_SET_IMAGE_REQUEST(aResult.SetImageData,
     969                 :                            aStyleContext,
     970                 :                            aValue.GetImageValue())
     971               0 :       break;
     972                 :     case eCSSUnit_Function:
     973               0 :       if (aValue.EqualsFunction(eCSSKeyword__moz_image_rect)) {
     974               0 :         SetStyleImageToImageRect(aStyleContext, aValue, aResult);
     975                 :       } else {
     976               0 :         NS_NOTREACHED("-moz-image-rect() is the only expected function");
     977                 :       }
     978               0 :       break;
     979                 :     case eCSSUnit_Gradient:
     980                 :     {
     981               0 :       nsStyleGradient* gradient = new nsStyleGradient();
     982               0 :       if (gradient) {
     983                 :         SetGradient(aValue, aStyleContext->PresContext(), aStyleContext,
     984               0 :                     *gradient, aCanStoreInRuleTree);
     985               0 :         aResult.SetGradientData(gradient);
     986                 :       }
     987               0 :       break;
     988                 :     }
     989                 :     case eCSSUnit_Element:
     990               0 :       aResult.SetElementId(aValue.GetStringBufferValue());
     991               0 :       break;
     992                 :     case eCSSUnit_None:
     993               0 :       break;
     994                 :     default:
     995                 :       // We might have eCSSUnit_URL values for if-visited style
     996                 :       // contexts, which we can safely treat like 'none'.  Otherwise
     997                 :       // this is an unexpected unit.
     998               0 :       NS_ASSERTION(aStyleContext->IsStyleIfVisited() &&
     999                 :                    aValue.GetUnit() == eCSSUnit_URL,
    1000                 :                    "unexpected unit; maybe nsCSSValue::Image::Image() failed?");
    1001               0 :       break;
    1002                 :   }
    1003               0 : }
    1004                 : 
    1005                 : // flags for SetDiscrete - align values with SETCOORD_* constants
    1006                 : // where possible
    1007                 : 
    1008                 : #define SETDSC_NORMAL                 0x01   // N
    1009                 : #define SETDSC_AUTO                   0x02   // A
    1010                 : #define SETDSC_INTEGER                0x40   // I
    1011                 : #define SETDSC_ENUMERATED             0x80   // E
    1012                 : #define SETDSC_NONE                   0x100  // O
    1013                 : #define SETDSC_SYSTEM_FONT            0x2000
    1014                 : 
    1015                 : // no caller cares whether aField was changed or not
    1016                 : template <typename FieldT,
    1017                 :           typename T1, typename T2, typename T3, typename T4, typename T5>
    1018                 : static void
    1019               0 : SetDiscrete(const nsCSSValue& aValue, FieldT & aField,
    1020                 :             bool& aCanStoreInRuleTree, PRUint32 aMask,
    1021                 :             FieldT aParentValue,
    1022                 :             T1 aInitialValue,
    1023                 :             T2 aAutoValue,
    1024                 :             T3 aNoneValue,
    1025                 :             T4 aNormalValue,
    1026                 :             T5 aSystemFontValue)
    1027                 : {
    1028               0 :   switch (aValue.GetUnit()) {
    1029                 :   case eCSSUnit_Null:
    1030               0 :     return;
    1031                 : 
    1032                 :     // every caller of SetDiscrete provides inherit and initial
    1033                 :     // alternatives, so we don't require them to say so in the mask
    1034                 :   case eCSSUnit_Inherit:
    1035               0 :     aCanStoreInRuleTree = false;
    1036               0 :     aField = aParentValue;
    1037               0 :     return;
    1038                 : 
    1039                 :   case eCSSUnit_Initial:
    1040               0 :     aField = aInitialValue;
    1041               0 :     return;
    1042                 : 
    1043                 :     // every caller provides one or other of these alternatives,
    1044                 :     // but they have to say which
    1045                 :   case eCSSUnit_Enumerated:
    1046               0 :     if (aMask & SETDSC_ENUMERATED) {
    1047               0 :       aField = aValue.GetIntValue();
    1048               0 :       return;
    1049                 :     }
    1050               0 :     break;
    1051                 : 
    1052                 :   case eCSSUnit_Integer:
    1053               0 :     if (aMask & SETDSC_INTEGER) {
    1054               0 :       aField = aValue.GetIntValue();
    1055               0 :       return;
    1056                 :     }
    1057               0 :     break;
    1058                 : 
    1059                 :     // remaining possibilities in descending order of frequency of use
    1060                 :   case eCSSUnit_Auto:
    1061               0 :     if (aMask & SETDSC_AUTO) {
    1062               0 :       aField = aAutoValue;
    1063               0 :       return;
    1064                 :     }
    1065               0 :     break;
    1066                 : 
    1067                 :   case eCSSUnit_None:
    1068               0 :     if (aMask & SETDSC_NONE) {
    1069               0 :       aField = aNoneValue;
    1070               0 :       return;
    1071                 :     }
    1072               0 :     break;
    1073                 : 
    1074                 :   case eCSSUnit_Normal:
    1075               0 :     if (aMask & SETDSC_NORMAL) {
    1076               0 :       aField = aNormalValue;
    1077               0 :       return;
    1078                 :     }
    1079               0 :     break;
    1080                 : 
    1081                 :   case eCSSUnit_System_Font:
    1082               0 :     if (aMask & SETDSC_SYSTEM_FONT) {
    1083               0 :       aField = aSystemFontValue;
    1084               0 :       return;
    1085                 :     }
    1086               0 :     break;
    1087                 : 
    1088                 :   default:
    1089               0 :     break;
    1090                 :   }
    1091                 : 
    1092               0 :   NS_NOTREACHED("SetDiscrete: inappropriate unit");
    1093                 : }
    1094                 : 
    1095                 : // flags for SetFactor
    1096                 : #define SETFCT_POSITIVE 0x01        // assert value is >= 0.0f
    1097                 : #define SETFCT_OPACITY  0x02        // clamp value to [0.0f .. 1.0f]
    1098                 : #define SETFCT_NONE     0x04        // allow _None (uses aInitialValue).
    1099                 : 
    1100                 : static void
    1101               0 : SetFactor(const nsCSSValue& aValue, float& aField, bool& aCanStoreInRuleTree,
    1102                 :           float aParentValue, float aInitialValue, PRUint32 aFlags = 0)
    1103                 : {
    1104               0 :   switch (aValue.GetUnit()) {
    1105                 :   case eCSSUnit_Null:
    1106               0 :     return;
    1107                 : 
    1108                 :   case eCSSUnit_Number:
    1109               0 :     aField = aValue.GetFloatValue();
    1110               0 :     if (aFlags & SETFCT_POSITIVE) {
    1111               0 :       NS_ASSERTION(aField >= 0.0f, "negative value for positive-only property");
    1112               0 :       if (aField < 0.0f)
    1113               0 :         aField = 0.0f;
    1114                 :     }
    1115               0 :     if (aFlags & SETFCT_OPACITY) {
    1116               0 :       if (aField < 0.0f)
    1117               0 :         aField = 0.0f;
    1118               0 :       if (aField > 1.0f)
    1119               0 :         aField = 1.0f;
    1120                 :     }
    1121               0 :     return;
    1122                 : 
    1123                 :   case eCSSUnit_Inherit:
    1124               0 :     aCanStoreInRuleTree = false;
    1125               0 :     aField = aParentValue;
    1126               0 :     return;
    1127                 : 
    1128                 :   case eCSSUnit_Initial:
    1129               0 :     aField = aInitialValue;
    1130               0 :     return;
    1131                 : 
    1132                 :   case eCSSUnit_None:
    1133               0 :     if (aFlags & SETFCT_NONE) {
    1134               0 :       aField = aInitialValue;
    1135               0 :       return;
    1136                 :     }
    1137               0 :     break;
    1138                 : 
    1139                 :   default:
    1140               0 :     break;
    1141                 :   }
    1142                 : 
    1143               0 :   NS_NOTREACHED("SetFactor: inappropriate unit");
    1144                 : }
    1145                 : 
    1146                 : // Overloaded new operator. Initializes the memory to 0 and relies on an arena
    1147                 : // (which comes from the presShell) to perform the allocation.
    1148                 : void*
    1149               0 : nsRuleNode::operator new(size_t sz, nsPresContext* aPresContext) CPP_THROW_NEW
    1150                 : {
    1151                 :   // Check the recycle list first.
    1152               0 :   return aPresContext->AllocateFromShell(sz);
    1153                 : }
    1154                 : 
    1155                 : /* static */ PLDHashOperator
    1156               0 : nsRuleNode::EnqueueRuleNodeChildren(PLDHashTable *table, PLDHashEntryHdr *hdr,
    1157                 :                                     PRUint32 number, void *arg)
    1158                 : {
    1159               0 :   ChildrenHashEntry *entry = static_cast<ChildrenHashEntry*>(hdr);
    1160               0 :   nsRuleNode ***destroyQueueTail = static_cast<nsRuleNode***>(arg);
    1161               0 :   **destroyQueueTail = entry->mRuleNode;
    1162               0 :   *destroyQueueTail = &entry->mRuleNode->mNextSibling;
    1163               0 :   return PL_DHASH_NEXT;
    1164                 : }
    1165                 : 
    1166                 : // Overridden to prevent the global delete from being called, since the memory
    1167                 : // came out of an nsIArena instead of the global delete operator's heap.
    1168                 : void
    1169               0 : nsRuleNode::DestroyInternal(nsRuleNode ***aDestroyQueueTail)
    1170                 : {
    1171                 :   nsRuleNode *destroyQueue, **destroyQueueTail;
    1172               0 :   if (aDestroyQueueTail) {
    1173               0 :     destroyQueueTail = *aDestroyQueueTail;
    1174                 :   } else {
    1175               0 :     destroyQueue = nsnull;
    1176               0 :     destroyQueueTail = &destroyQueue;
    1177                 :   }
    1178                 : 
    1179               0 :   if (ChildrenAreHashed()) {
    1180               0 :     PLDHashTable *children = ChildrenHash();
    1181                 :     PL_DHashTableEnumerate(children, EnqueueRuleNodeChildren,
    1182               0 :                            &destroyQueueTail);
    1183               0 :     *destroyQueueTail = nsnull; // ensure null-termination
    1184               0 :     PL_DHashTableDestroy(children);
    1185               0 :   } else if (HaveChildren()) {
    1186               0 :     *destroyQueueTail = ChildrenList();
    1187               0 :     do {
    1188               0 :       destroyQueueTail = &(*destroyQueueTail)->mNextSibling;
    1189                 :     } while (*destroyQueueTail);
    1190                 :   }
    1191               0 :   mChildren.asVoid = nsnull;
    1192                 : 
    1193               0 :   if (aDestroyQueueTail) {
    1194                 :     // Our caller destroys the queue.
    1195               0 :     *aDestroyQueueTail = destroyQueueTail;
    1196                 :   } else {
    1197                 :     // We have to do destroy the queue.  When we destroy each node, it
    1198                 :     // will add its children to the queue.
    1199               0 :     while (destroyQueue) {
    1200               0 :       nsRuleNode *cur = destroyQueue;
    1201               0 :       destroyQueue = destroyQueue->mNextSibling;
    1202               0 :       if (!destroyQueue) {
    1203               0 :         NS_ASSERTION(destroyQueueTail == &cur->mNextSibling, "mangled list");
    1204               0 :         destroyQueueTail = &destroyQueue;
    1205                 :       }
    1206               0 :       cur->DestroyInternal(&destroyQueueTail);
    1207                 :     }
    1208                 :   }
    1209                 : 
    1210                 :   // Destroy ourselves.
    1211               0 :   this->~nsRuleNode();
    1212                 : 
    1213                 :   // Don't let the memory be freed, since it will be recycled
    1214                 :   // instead. Don't call the global operator delete.
    1215               0 :   mPresContext->FreeToShell(sizeof(nsRuleNode), this);
    1216               0 : }
    1217                 : 
    1218               0 : nsRuleNode* nsRuleNode::CreateRootNode(nsPresContext* aPresContext)
    1219                 : {
    1220                 :   return new (aPresContext)
    1221               0 :     nsRuleNode(aPresContext, nsnull, nsnull, 0xff, false);
    1222                 : }
    1223                 : 
    1224               0 : nsRuleNode::nsRuleNode(nsPresContext* aContext, nsRuleNode* aParent,
    1225                 :                        nsIStyleRule* aRule, PRUint8 aLevel,
    1226                 :                        bool aIsImportant)
    1227                 :   : mPresContext(aContext),
    1228                 :     mParent(aParent),
    1229                 :     mRule(aRule),
    1230                 :     mDependentBits((PRUint32(aLevel) << NS_RULE_NODE_LEVEL_SHIFT) |
    1231                 :                    (aIsImportant ? NS_RULE_NODE_IS_IMPORTANT : 0)),
    1232                 :     mNoneBits(0),
    1233               0 :     mRefCnt(0)
    1234                 : {
    1235               0 :   mChildren.asVoid = nsnull;
    1236               0 :   MOZ_COUNT_CTOR(nsRuleNode);
    1237               0 :   NS_IF_ADDREF(mRule);
    1238                 : 
    1239               0 :   NS_ASSERTION(IsRoot() || GetLevel() == aLevel, "not enough bits");
    1240               0 :   NS_ASSERTION(IsRoot() || IsImportantRule() == aIsImportant, "yikes");
    1241                 :   /* If IsRoot(), then aContext->StyleSet() is typically null at this
    1242                 :      point.  In any case, we don't want to treat the root rulenode as
    1243                 :      unused.  */
    1244               0 :   if (!IsRoot()) {
    1245               0 :     mParent->AddRef();
    1246               0 :     aContext->StyleSet()->RuleNodeUnused();
    1247                 :   }
    1248                 : 
    1249                 :   // nsStyleSet::GetContext depends on there being only one animation
    1250                 :   // rule.
    1251               0 :   NS_ABORT_IF_FALSE(IsRoot() || GetLevel() != nsStyleSet::eAnimationSheet ||
    1252                 :                     mParent->IsRoot() ||
    1253                 :                     mParent->GetLevel() != nsStyleSet::eAnimationSheet,
    1254                 :                     "must be only one rule at animation level");
    1255               0 : }
    1256                 : 
    1257               0 : nsRuleNode::~nsRuleNode()
    1258                 : {
    1259               0 :   MOZ_COUNT_DTOR(nsRuleNode);
    1260               0 :   if (mStyleData.mResetData || mStyleData.mInheritedData)
    1261               0 :     mStyleData.Destroy(0, mPresContext);
    1262               0 :   NS_IF_RELEASE(mRule);
    1263               0 : }
    1264                 : 
    1265                 : nsRuleNode*
    1266               0 : nsRuleNode::Transition(nsIStyleRule* aRule, PRUint8 aLevel,
    1267                 :                        bool aIsImportantRule)
    1268                 : {
    1269               0 :   nsRuleNode* next = nsnull;
    1270               0 :   nsRuleNode::Key key(aRule, aLevel, aIsImportantRule);
    1271                 : 
    1272               0 :   if (HaveChildren() && !ChildrenAreHashed()) {
    1273               0 :     PRInt32 numKids = 0;
    1274               0 :     nsRuleNode* curr = ChildrenList();
    1275               0 :     while (curr && curr->GetKey() != key) {
    1276               0 :       curr = curr->mNextSibling;
    1277               0 :       ++numKids;
    1278                 :     }
    1279               0 :     if (curr)
    1280               0 :       next = curr;
    1281               0 :     else if (numKids >= kMaxChildrenInList)
    1282               0 :       ConvertChildrenToHash();
    1283                 :   }
    1284                 : 
    1285               0 :   if (ChildrenAreHashed()) {
    1286                 :     ChildrenHashEntry *entry = static_cast<ChildrenHashEntry*>
    1287               0 :                                           (PL_DHashTableOperate(ChildrenHash(), &key, PL_DHASH_ADD));
    1288               0 :     if (!entry) {
    1289               0 :       NS_WARNING("out of memory");
    1290               0 :       return this;
    1291                 :     }
    1292               0 :     if (entry->mRuleNode)
    1293               0 :       next = entry->mRuleNode;
    1294                 :     else {
    1295                 :       next = entry->mRuleNode = new (mPresContext)
    1296               0 :         nsRuleNode(mPresContext, this, aRule, aLevel, aIsImportantRule);
    1297               0 :       if (!next) {
    1298               0 :         PL_DHashTableRawRemove(ChildrenHash(), entry);
    1299               0 :         NS_WARNING("out of memory");
    1300               0 :         return this;
    1301                 :       }
    1302                 :     }
    1303               0 :   } else if (!next) {
    1304                 :     // Create the new entry in our list.
    1305                 :     next = new (mPresContext)
    1306               0 :       nsRuleNode(mPresContext, this, aRule, aLevel, aIsImportantRule);
    1307               0 :     if (!next) {
    1308               0 :       NS_WARNING("out of memory");
    1309               0 :       return this;
    1310                 :     }
    1311               0 :     next->mNextSibling = ChildrenList();
    1312               0 :     SetChildrenList(next);
    1313                 :   }
    1314                 : 
    1315               0 :   return next;
    1316                 : }
    1317                 : 
    1318                 : void
    1319               0 : nsRuleNode::ConvertChildrenToHash()
    1320                 : {
    1321               0 :   NS_ASSERTION(!ChildrenAreHashed() && HaveChildren(),
    1322                 :                "must have a non-empty list of children");
    1323                 :   PLDHashTable *hash = PL_NewDHashTable(&ChildrenHashOps, nsnull,
    1324                 :                                         sizeof(ChildrenHashEntry),
    1325               0 :                                         kMaxChildrenInList * 4);
    1326               0 :   if (!hash)
    1327               0 :     return;
    1328               0 :   for (nsRuleNode* curr = ChildrenList(); curr; curr = curr->mNextSibling) {
    1329                 :     // This will never fail because of the initial size we gave the table.
    1330                 :     ChildrenHashEntry *entry = static_cast<ChildrenHashEntry*>(
    1331               0 :       PL_DHashTableOperate(hash, curr->mRule, PL_DHASH_ADD));
    1332               0 :     NS_ASSERTION(!entry->mRuleNode, "duplicate entries in list");
    1333               0 :     entry->mRuleNode = curr;
    1334                 :   }
    1335               0 :   SetChildrenHash(hash);
    1336                 : }
    1337                 : 
    1338                 : inline void
    1339               0 : nsRuleNode::PropagateNoneBit(PRUint32 aBit, nsRuleNode* aHighestNode)
    1340                 : {
    1341               0 :   nsRuleNode* curr = this;
    1342               0 :   for (;;) {
    1343               0 :     NS_ASSERTION(!(curr->mNoneBits & aBit), "propagating too far");
    1344               0 :     curr->mNoneBits |= aBit;
    1345               0 :     if (curr == aHighestNode)
    1346                 :       break;
    1347               0 :     curr = curr->mParent;
    1348                 :   }
    1349               0 : }
    1350                 : 
    1351                 : inline void
    1352               0 : nsRuleNode::PropagateDependentBit(PRUint32 aBit, nsRuleNode* aHighestNode)
    1353                 : {
    1354               0 :   for (nsRuleNode* curr = this; curr != aHighestNode; curr = curr->mParent) {
    1355               0 :     if (curr->mDependentBits & aBit) {
    1356                 : #ifdef DEBUG
    1357               0 :       while (curr != aHighestNode) {
    1358               0 :         NS_ASSERTION(curr->mDependentBits & aBit, "bit not set");
    1359               0 :         curr = curr->mParent;
    1360                 :       }
    1361                 : #endif
    1362               0 :       break;
    1363                 :     }
    1364                 : 
    1365               0 :     curr->mDependentBits |= aBit;
    1366                 :   }
    1367               0 : }
    1368                 : 
    1369                 : /*
    1370                 :  * The following "Check" functions are used for determining what type of
    1371                 :  * sharing can be used for the data on this rule node.  MORE HERE...
    1372                 :  */
    1373                 : 
    1374                 : /*
    1375                 :  * a callback function that that can revise the result of
    1376                 :  * CheckSpecifiedProperties before finishing; aResult is the current
    1377                 :  * result, and it returns the revised one.
    1378                 :  */
    1379                 : typedef nsRuleNode::RuleDetail
    1380                 :   (* CheckCallbackFn)(const nsRuleData* aRuleData,
    1381                 :                       nsRuleNode::RuleDetail aResult);
    1382                 : 
    1383                 : /**
    1384                 :  * @param aValue the value being examined
    1385                 :  * @param aSpecifiedCount to be incremented by one if the value is specified
    1386                 :  * @param aInherited to be incremented by one if the value is set to inherit
    1387                 :  */
    1388                 : inline void
    1389               0 : ExamineCSSValue(const nsCSSValue& aValue,
    1390                 :                 PRUint32& aSpecifiedCount, PRUint32& aInheritedCount)
    1391                 : {
    1392               0 :   if (aValue.GetUnit() != eCSSUnit_Null) {
    1393               0 :     ++aSpecifiedCount;
    1394               0 :     if (aValue.GetUnit() == eCSSUnit_Inherit) {
    1395               0 :       ++aInheritedCount;
    1396                 :     }
    1397                 :   }
    1398               0 : }
    1399                 : 
    1400                 : static nsRuleNode::RuleDetail
    1401               0 : CheckFontCallback(const nsRuleData* aRuleData,
    1402                 :                   nsRuleNode::RuleDetail aResult)
    1403                 : {
    1404                 :   // em, ex, percent, 'larger', and 'smaller' values on font-size depend
    1405                 :   // on the parent context's font-size
    1406                 :   // Likewise, 'lighter' and 'bolder' values of 'font-weight', and 'wider'
    1407                 :   // and 'narrower' values of 'font-stretch' depend on the parent.
    1408               0 :   const nsCSSValue& size = *aRuleData->ValueForFontSize();
    1409               0 :   const nsCSSValue& weight = *aRuleData->ValueForFontWeight();
    1410               0 :   if (size.IsRelativeLengthUnit() ||
    1411               0 :       size.GetUnit() == eCSSUnit_Percent ||
    1412               0 :       (size.GetUnit() == eCSSUnit_Enumerated &&
    1413               0 :        (size.GetIntValue() == NS_STYLE_FONT_SIZE_SMALLER ||
    1414               0 :         size.GetIntValue() == NS_STYLE_FONT_SIZE_LARGER)) ||
    1415               0 :       aRuleData->ValueForScriptLevel()->GetUnit() == eCSSUnit_Integer ||
    1416               0 :       (weight.GetUnit() == eCSSUnit_Enumerated &&
    1417               0 :        (weight.GetIntValue() == NS_STYLE_FONT_WEIGHT_BOLDER ||
    1418               0 :         weight.GetIntValue() == NS_STYLE_FONT_WEIGHT_LIGHTER))) {
    1419               0 :     NS_ASSERTION(aResult == nsRuleNode::eRulePartialReset ||
    1420                 :                  aResult == nsRuleNode::eRuleFullReset ||
    1421                 :                  aResult == nsRuleNode::eRulePartialMixed ||
    1422                 :                  aResult == nsRuleNode::eRuleFullMixed,
    1423                 :                  "we know we already have a reset-counted property");
    1424                 :     // Promote reset to mixed since we have something that depends on
    1425                 :     // the parent.  But never promote to inherited since that could
    1426                 :     // cause inheritance of the exact value.
    1427               0 :     if (aResult == nsRuleNode::eRulePartialReset)
    1428               0 :       aResult = nsRuleNode::eRulePartialMixed;
    1429               0 :     else if (aResult == nsRuleNode::eRuleFullReset)
    1430               0 :       aResult = nsRuleNode::eRuleFullMixed;
    1431                 :   }
    1432                 : 
    1433               0 :   return aResult;
    1434                 : }
    1435                 : 
    1436                 : static nsRuleNode::RuleDetail
    1437               0 : CheckColorCallback(const nsRuleData* aRuleData,
    1438                 :                    nsRuleNode::RuleDetail aResult)
    1439                 : {
    1440                 :   // currentColor values for color require inheritance
    1441               0 :   const nsCSSValue* colorValue = aRuleData->ValueForColor();
    1442               0 :   if (colorValue->GetUnit() == eCSSUnit_EnumColor &&
    1443               0 :       colorValue->GetIntValue() == NS_COLOR_CURRENTCOLOR) {
    1444               0 :     NS_ASSERTION(aResult == nsRuleNode::eRuleFullReset,
    1445                 :                  "we should already be counted as full-reset");
    1446               0 :     aResult = nsRuleNode::eRuleFullInherited;
    1447                 :   }
    1448                 : 
    1449               0 :   return aResult;
    1450                 : }
    1451                 : 
    1452                 : static nsRuleNode::RuleDetail
    1453               0 : CheckTextCallback(const nsRuleData* aRuleData,
    1454                 :                   nsRuleNode::RuleDetail aResult)
    1455                 : {
    1456               0 :   const nsCSSValue* textAlignValue = aRuleData->ValueForTextAlign();
    1457               0 :   if (textAlignValue->GetUnit() == eCSSUnit_Enumerated &&
    1458               0 :       textAlignValue->GetIntValue() ==
    1459                 :         NS_STYLE_TEXT_ALIGN_MOZ_CENTER_OR_INHERIT) {
    1460                 :     // Promote reset to mixed since we have something that depends on
    1461                 :     // the parent.
    1462               0 :     if (aResult == nsRuleNode::eRulePartialReset)
    1463               0 :       aResult = nsRuleNode::eRulePartialMixed;
    1464               0 :     else if (aResult == nsRuleNode::eRuleFullReset)
    1465               0 :       aResult = nsRuleNode::eRuleFullMixed;
    1466                 :   }
    1467                 : 
    1468               0 :   return aResult;
    1469                 : }
    1470                 : 
    1471                 : #define FLAG_DATA_FOR_PROPERTY(name_, id_, method_, flags_, parsevariant_,   \
    1472                 :                                kwtable_, stylestructoffset_, animtype_)      \
    1473                 :   flags_,
    1474                 : 
    1475                 : // The order here must match the enums in *CheckCounter in nsCSSProps.cpp.
    1476                 : 
    1477                 : static const PRUint32 gFontFlags[] = {
    1478                 : #define CSS_PROP_FONT FLAG_DATA_FOR_PROPERTY
    1479                 : #include "nsCSSPropList.h"
    1480                 : #undef CSS_PROP_FONT
    1481                 : };
    1482                 : 
    1483                 : static const PRUint32 gDisplayFlags[] = {
    1484                 : #define CSS_PROP_DISPLAY FLAG_DATA_FOR_PROPERTY
    1485                 : #include "nsCSSPropList.h"
    1486                 : #undef CSS_PROP_DISPLAY
    1487                 : };
    1488                 : 
    1489                 : static const PRUint32 gVisibilityFlags[] = {
    1490                 : #define CSS_PROP_VISIBILITY FLAG_DATA_FOR_PROPERTY
    1491                 : #include "nsCSSPropList.h"
    1492                 : #undef CSS_PROP_VISIBILITY
    1493                 : };
    1494                 : 
    1495                 : static const PRUint32 gMarginFlags[] = {
    1496                 : #define CSS_PROP_MARGIN FLAG_DATA_FOR_PROPERTY
    1497                 : #include "nsCSSPropList.h"
    1498                 : #undef CSS_PROP_MARGIN
    1499                 : };
    1500                 : 
    1501                 : static const PRUint32 gBorderFlags[] = {
    1502                 : #define CSS_PROP_BORDER FLAG_DATA_FOR_PROPERTY
    1503                 : #include "nsCSSPropList.h"
    1504                 : #undef CSS_PROP_BORDER
    1505                 : };
    1506                 : 
    1507                 : static const PRUint32 gPaddingFlags[] = {
    1508                 : #define CSS_PROP_PADDING FLAG_DATA_FOR_PROPERTY
    1509                 : #include "nsCSSPropList.h"
    1510                 : #undef CSS_PROP_PADDING
    1511                 : };
    1512                 : 
    1513                 : static const PRUint32 gOutlineFlags[] = {
    1514                 : #define CSS_PROP_OUTLINE FLAG_DATA_FOR_PROPERTY
    1515                 : #include "nsCSSPropList.h"
    1516                 : #undef CSS_PROP_OUTLINE
    1517                 : };
    1518                 : 
    1519                 : static const PRUint32 gListFlags[] = {
    1520                 : #define CSS_PROP_LIST FLAG_DATA_FOR_PROPERTY
    1521                 : #include "nsCSSPropList.h"
    1522                 : #undef CSS_PROP_LIST
    1523                 : };
    1524                 : 
    1525                 : static const PRUint32 gColorFlags[] = {
    1526                 : #define CSS_PROP_COLOR FLAG_DATA_FOR_PROPERTY
    1527                 : #include "nsCSSPropList.h"
    1528                 : #undef CSS_PROP_COLOR
    1529                 : };
    1530                 : 
    1531                 : static const PRUint32 gBackgroundFlags[] = {
    1532                 : #define CSS_PROP_BACKGROUND FLAG_DATA_FOR_PROPERTY
    1533                 : #include "nsCSSPropList.h"
    1534                 : #undef CSS_PROP_BACKGROUND
    1535                 : };
    1536                 : 
    1537                 : static const PRUint32 gPositionFlags[] = {
    1538                 : #define CSS_PROP_POSITION FLAG_DATA_FOR_PROPERTY
    1539                 : #include "nsCSSPropList.h"
    1540                 : #undef CSS_PROP_POSITION
    1541                 : };
    1542                 : 
    1543                 : static const PRUint32 gTableFlags[] = {
    1544                 : #define CSS_PROP_TABLE FLAG_DATA_FOR_PROPERTY
    1545                 : #include "nsCSSPropList.h"
    1546                 : #undef CSS_PROP_TABLE
    1547                 : };
    1548                 : 
    1549                 : static const PRUint32 gTableBorderFlags[] = {
    1550                 : #define CSS_PROP_TABLEBORDER FLAG_DATA_FOR_PROPERTY
    1551                 : #include "nsCSSPropList.h"
    1552                 : #undef CSS_PROP_TABLEBORDER
    1553                 : };
    1554                 : 
    1555                 : static const PRUint32 gContentFlags[] = {
    1556                 : #define CSS_PROP_CONTENT FLAG_DATA_FOR_PROPERTY
    1557                 : #include "nsCSSPropList.h"
    1558                 : #undef CSS_PROP_CONTENT
    1559                 : };
    1560                 : 
    1561                 : static const PRUint32 gQuotesFlags[] = {
    1562                 : #define CSS_PROP_QUOTES FLAG_DATA_FOR_PROPERTY
    1563                 : #include "nsCSSPropList.h"
    1564                 : #undef CSS_PROP_QUOTES
    1565                 : };
    1566                 : 
    1567                 : static const PRUint32 gTextFlags[] = {
    1568                 : #define CSS_PROP_TEXT FLAG_DATA_FOR_PROPERTY
    1569                 : #include "nsCSSPropList.h"
    1570                 : #undef CSS_PROP_TEXT
    1571                 : };
    1572                 : 
    1573                 : static const PRUint32 gTextResetFlags[] = {
    1574                 : #define CSS_PROP_TEXTRESET FLAG_DATA_FOR_PROPERTY
    1575                 : #include "nsCSSPropList.h"
    1576                 : #undef CSS_PROP_TEXTRESET
    1577                 : };
    1578                 : 
    1579                 : static const PRUint32 gUserInterfaceFlags[] = {
    1580                 : #define CSS_PROP_USERINTERFACE FLAG_DATA_FOR_PROPERTY
    1581                 : #include "nsCSSPropList.h"
    1582                 : #undef CSS_PROP_USERINTERFACE
    1583                 : };
    1584                 : 
    1585                 : static const PRUint32 gUIResetFlags[] = {
    1586                 : #define CSS_PROP_UIRESET FLAG_DATA_FOR_PROPERTY
    1587                 : #include "nsCSSPropList.h"
    1588                 : #undef CSS_PROP_UIRESET
    1589                 : };
    1590                 : 
    1591                 : static const PRUint32 gXULFlags[] = {
    1592                 : #define CSS_PROP_XUL FLAG_DATA_FOR_PROPERTY
    1593                 : #include "nsCSSPropList.h"
    1594                 : #undef CSS_PROP_XUL
    1595                 : };
    1596                 : 
    1597                 : static const PRUint32 gSVGFlags[] = {
    1598                 : #define CSS_PROP_SVG FLAG_DATA_FOR_PROPERTY
    1599                 : #include "nsCSSPropList.h"
    1600                 : #undef CSS_PROP_SVG
    1601                 : };
    1602                 : 
    1603                 : static const PRUint32 gSVGResetFlags[] = {
    1604                 : #define CSS_PROP_SVGRESET FLAG_DATA_FOR_PROPERTY
    1605                 : #include "nsCSSPropList.h"
    1606                 : #undef CSS_PROP_SVGRESET
    1607                 : };
    1608                 : 
    1609                 : static const PRUint32 gColumnFlags[] = {
    1610                 : #define CSS_PROP_COLUMN FLAG_DATA_FOR_PROPERTY
    1611                 : #include "nsCSSPropList.h"
    1612                 : #undef CSS_PROP_COLUMN
    1613                 : };
    1614                 : 
    1615                 : #undef FLAG_DATA_FOR_PROPERTY
    1616                 : 
    1617                 : static const PRUint32* gFlagsByStruct[] = {
    1618                 : 
    1619                 : #define STYLE_STRUCT(name, checkdata_cb, ctor_args) \
    1620                 :   g##name##Flags,
    1621                 : #include "nsStyleStructList.h"
    1622                 : #undef STYLE_STRUCT
    1623                 : 
    1624                 : };
    1625                 : 
    1626                 : static const CheckCallbackFn gCheckCallbacks[] = {
    1627                 : 
    1628                 : #define STYLE_STRUCT(name, checkdata_cb, ctor_args) \
    1629                 :   checkdata_cb,
    1630                 : #include "nsStyleStructList.h"
    1631                 : #undef STYLE_STRUCT
    1632                 : 
    1633                 : };
    1634                 : 
    1635                 : #ifdef DEBUG
    1636                 : static bool
    1637               0 : AreAllMathMLPropertiesUndefined(const nsRuleData* aRuleData)
    1638                 : {
    1639                 :   return
    1640               0 :     aRuleData->ValueForScriptLevel()->GetUnit() == eCSSUnit_Null &&
    1641               0 :     aRuleData->ValueForScriptSizeMultiplier()->GetUnit() == eCSSUnit_Null &&
    1642               0 :     aRuleData->ValueForScriptMinSize()->GetUnit() == eCSSUnit_Null;
    1643                 : }
    1644                 : #endif
    1645                 : 
    1646                 : inline nsRuleNode::RuleDetail
    1647               0 : nsRuleNode::CheckSpecifiedProperties(const nsStyleStructID aSID,
    1648                 :                                      const nsRuleData* aRuleData)
    1649                 : {
    1650                 :   // Build a count of the:
    1651               0 :   PRUint32 total = 0,      // total number of props in the struct
    1652               0 :            specified = 0,  // number that were specified for this node
    1653               0 :            inherited = 0;  // number that were 'inherit' (and not
    1654                 :                            //   eCSSUnit_Inherit) for this node
    1655                 : 
    1656                 :   // See comment in nsRuleData.h above mValueOffsets.
    1657               0 :   NS_ABORT_IF_FALSE(aRuleData->mValueOffsets[aSID] == 0,
    1658                 :                     "we assume the value offset is zero instead of adding it");
    1659               0 :   for (nsCSSValue *values = aRuleData->mValueStorage,
    1660               0 :               *values_end = values + nsCSSProps::PropertyCountInStruct(aSID);
    1661                 :        values != values_end; ++values) {
    1662               0 :     ++total;
    1663               0 :     ExamineCSSValue(*values, specified, inherited);
    1664                 :   }
    1665                 : 
    1666                 : #if 0
    1667                 :   printf("CheckSpecifiedProperties: SID=%d total=%d spec=%d inh=%d.\n",
    1668                 :          aSID, total, specified, inherited);
    1669                 : #endif
    1670                 : 
    1671               0 :   NS_ASSERTION(aSID != eStyleStruct_Font ||
    1672                 :                mPresContext->Document()->GetMathMLEnabled() ||
    1673                 :                AreAllMathMLPropertiesUndefined(aRuleData),
    1674                 :                "MathML style property was defined even though MathML is disabled");
    1675                 : 
    1676                 :   /*
    1677                 :    * Return the most specific information we can: prefer None or Full
    1678                 :    * over Partial, and Reset or Inherited over Mixed, since we can
    1679                 :    * optimize based on the edge cases and not the in-between cases.
    1680                 :    */
    1681                 :   nsRuleNode::RuleDetail result;
    1682               0 :   if (inherited == total)
    1683               0 :     result = eRuleFullInherited;
    1684               0 :   else if (specified == total
    1685                 :            // MathML defines 3 properties in Font that will never be set when
    1686                 :            // MathML is not in use. Therefore if all but three
    1687                 :            // properties have been set, and MathML is not enabled, we can treat
    1688                 :            // this as fully specified. Code in nsMathMLElementFactory will
    1689                 :            // rebuild the rule tree and style data when MathML is first enabled
    1690                 :            // (see nsMathMLElement::BindToTree).
    1691                 :            || (aSID == eStyleStruct_Font && specified + 3 == total &&
    1692               0 :                !mPresContext->Document()->GetMathMLEnabled())
    1693                 :           ) {
    1694               0 :     if (inherited == 0)
    1695               0 :       result = eRuleFullReset;
    1696                 :     else
    1697               0 :       result = eRuleFullMixed;
    1698               0 :   } else if (specified == 0)
    1699               0 :     result = eRuleNone;
    1700               0 :   else if (specified == inherited)
    1701               0 :     result = eRulePartialInherited;
    1702               0 :   else if (inherited == 0)
    1703               0 :     result = eRulePartialReset;
    1704                 :   else
    1705               0 :     result = eRulePartialMixed;
    1706                 : 
    1707               0 :   CheckCallbackFn cb = gCheckCallbacks[aSID];
    1708               0 :   if (cb) {
    1709               0 :     result = (*cb)(aRuleData, result);
    1710                 :   }
    1711                 : 
    1712               0 :   return result;
    1713                 : }
    1714                 : 
    1715                 : // If we need to restrict which properties apply to the style context,
    1716                 : // return the bit to check in nsCSSProp's flags table.  Otherwise,
    1717                 : // return 0.
    1718                 : inline PRUint32
    1719               0 : GetPseudoRestriction(nsStyleContext *aContext)
    1720                 : {
    1721                 :   // This needs to match nsStyleSet::WalkRestrictionRule.
    1722               0 :   PRUint32 pseudoRestriction = 0;
    1723               0 :   nsIAtom *pseudoType = aContext->GetPseudo();
    1724               0 :   if (pseudoType) {
    1725               0 :     if (pseudoType == nsCSSPseudoElements::firstLetter) {
    1726               0 :       pseudoRestriction = CSS_PROPERTY_APPLIES_TO_FIRST_LETTER;
    1727               0 :     } else if (pseudoType == nsCSSPseudoElements::firstLine) {
    1728               0 :       pseudoRestriction = CSS_PROPERTY_APPLIES_TO_FIRST_LINE;
    1729                 :     }
    1730                 :   }
    1731               0 :   return pseudoRestriction;
    1732                 : }
    1733                 : 
    1734                 : static void
    1735               0 : UnsetPropertiesWithoutFlags(const nsStyleStructID aSID,
    1736                 :                             nsRuleData* aRuleData,
    1737                 :                             PRUint32 aFlags)
    1738                 : {
    1739               0 :   NS_ASSERTION(aFlags != 0, "aFlags must be nonzero");
    1740                 : 
    1741               0 :   const PRUint32 *flagData = gFlagsByStruct[aSID];
    1742                 : 
    1743                 :   // See comment in nsRuleData.h above mValueOffsets.
    1744               0 :   NS_ABORT_IF_FALSE(aRuleData->mValueOffsets[aSID] == 0,
    1745                 :                     "we assume the value offset is zero instead of adding it");
    1746               0 :   nsCSSValue *values = aRuleData->mValueStorage;
    1747                 : 
    1748               0 :   for (size_t i = 0, i_end = nsCSSProps::PropertyCountInStruct(aSID);
    1749                 :        i != i_end; ++i) {
    1750               0 :     if ((flagData[i] & aFlags) != aFlags)
    1751               0 :       values[i].Reset();
    1752                 :   }
    1753               0 : }
    1754                 : 
    1755                 : /**
    1756                 :  * We allocate arrays of CSS values with alloca.  (These arrays are a
    1757                 :  * fixed size per style struct, but we don't want to waste the
    1758                 :  * allocation and construction/destruction costs of the big structs when
    1759                 :  * we're handling much smaller ones.)  Since the lifetime of an alloca
    1760                 :  * allocation is the life of the calling function, the caller must call
    1761                 :  * alloca.  However, to ensure that constructors and destructors are
    1762                 :  * balanced, we do the constructor and destructor calling from this RAII
    1763                 :  * class, AutoCSSValueArray.
    1764                 :  */
    1765                 : struct AutoCSSValueArray {
    1766                 :   /**
    1767                 :    * aStorage must be the result of alloca(aCount * sizeof(nsCSSValue))
    1768                 :    */
    1769               0 :   AutoCSSValueArray(void* aStorage, size_t aCount) {
    1770               0 :     NS_ABORT_IF_FALSE(size_t(aStorage) % NS_ALIGNMENT_OF(nsCSSValue) == 0,
    1771                 :                       "bad alignment from alloca");
    1772               0 :     mCount = aCount;
    1773                 :     // Don't use placement new[], since it might store extra data
    1774                 :     // for the count (on Windows!).
    1775               0 :     mArray = static_cast<nsCSSValue*>(aStorage);
    1776               0 :     for (size_t i = 0; i < mCount; ++i) {
    1777               0 :       new (mArray + i) nsCSSValue();
    1778                 :     }
    1779               0 :   }
    1780                 : 
    1781               0 :   ~AutoCSSValueArray() {
    1782               0 :     for (size_t i = 0; i < mCount; ++i) {
    1783               0 :       mArray[i].~nsCSSValue();
    1784                 :     }
    1785               0 :   }
    1786                 : 
    1787               0 :   nsCSSValue* get() { return mArray; }
    1788                 : 
    1789                 : private:
    1790                 :   nsCSSValue *mArray;
    1791                 :   size_t mCount;
    1792                 : };
    1793                 : 
    1794                 : const void*
    1795               0 : nsRuleNode::WalkRuleTree(const nsStyleStructID aSID,
    1796                 :                          nsStyleContext* aContext)
    1797                 : {
    1798                 :   // use placement new[] on the result of alloca() to allocate a
    1799                 :   // variable-sized stack array, including execution of constructors,
    1800                 :   // and use an RAII class to run the destructors too.
    1801               0 :   size_t nprops = nsCSSProps::PropertyCountInStruct(aSID);
    1802               0 :   void* dataStorage = alloca(nprops * sizeof(nsCSSValue));
    1803               0 :   AutoCSSValueArray dataArray(dataStorage, nprops);
    1804                 : 
    1805                 :   nsRuleData ruleData(nsCachedStyleData::GetBitForSID(aSID),
    1806               0 :                       dataArray.get(), mPresContext, aContext);
    1807               0 :   ruleData.mValueOffsets[aSID] = 0;
    1808                 : 
    1809                 :   // We start at the most specific rule in the tree.
    1810               0 :   void* startStruct = nsnull;
    1811                 : 
    1812               0 :   nsRuleNode* ruleNode = this;
    1813               0 :   nsRuleNode* highestNode = nsnull; // The highest node in the rule tree
    1814                 :                                     // that has the same properties
    1815                 :                                     // specified for struct |aSID| as
    1816                 :                                     // |this| does.
    1817               0 :   nsRuleNode* rootNode = this; // After the loop below, this will be the
    1818                 :                                // highest node that we've walked without
    1819                 :                                // finding cached data on the rule tree.
    1820                 :                                // If we don't find any cached data, it
    1821                 :                                // will be the root.  (XXX misnamed)
    1822               0 :   RuleDetail detail = eRuleNone;
    1823               0 :   PRUint32 bit = nsCachedStyleData::GetBitForSID(aSID);
    1824                 : 
    1825               0 :   while (ruleNode) {
    1826                 :     // See if this rule node has cached the fact that the remaining
    1827                 :     // nodes along this path specify no data whatsoever.
    1828               0 :     if (ruleNode->mNoneBits & bit)
    1829               0 :       break;
    1830                 : 
    1831                 :     // If the dependent bit is set on a rule node for this struct, that
    1832                 :     // means its rule won't have any information to add, so skip it.
    1833               0 :     while (ruleNode->mDependentBits & bit) {
    1834               0 :       NS_ASSERTION(ruleNode->mStyleData.GetStyleData(aSID) == nsnull,
    1835                 :                    "dependent bit with cached data makes no sense");
    1836                 :       // Climb up to the next rule in the tree (a less specific rule).
    1837               0 :       rootNode = ruleNode;
    1838               0 :       ruleNode = ruleNode->mParent;
    1839               0 :       NS_ASSERTION(!(ruleNode->mNoneBits & bit), "can't have both bits set");
    1840                 :     }
    1841                 : 
    1842                 :     // Check for cached data after the inner loop above -- otherwise
    1843                 :     // we'll miss it.
    1844               0 :     startStruct = ruleNode->mStyleData.GetStyleData(aSID);
    1845               0 :     if (startStruct)
    1846               0 :       break; // We found a rule with fully specified data.  We don't
    1847                 :              // need to go up the tree any further, since the remainder
    1848                 :              // of this branch has already been computed.
    1849                 : 
    1850                 :     // Ask the rule to fill in the properties that it specifies.
    1851               0 :     nsIStyleRule *rule = ruleNode->mRule;
    1852               0 :     if (rule) {
    1853               0 :       ruleData.mLevel = ruleNode->GetLevel();
    1854               0 :       ruleData.mIsImportantRule = ruleNode->IsImportantRule();
    1855               0 :       rule->MapRuleInfoInto(&ruleData);
    1856                 :     }
    1857                 : 
    1858                 :     // Now we check to see how many properties have been specified by
    1859                 :     // the rules we've examined so far.
    1860               0 :     RuleDetail oldDetail = detail;
    1861               0 :     detail = CheckSpecifiedProperties(aSID, &ruleData);
    1862                 : 
    1863               0 :     if (oldDetail == eRuleNone && detail != eRuleNone)
    1864               0 :       highestNode = ruleNode;
    1865                 : 
    1866               0 :     if (detail == eRuleFullReset ||
    1867                 :         detail == eRuleFullMixed ||
    1868                 :         detail == eRuleFullInherited)
    1869               0 :       break; // We don't need to examine any more rules.  All properties
    1870                 :              // have been fully specified.
    1871                 : 
    1872                 :     // Climb up to the next rule in the tree (a less specific rule).
    1873               0 :     rootNode = ruleNode;
    1874               0 :     ruleNode = ruleNode->mParent;
    1875                 :   }
    1876                 : 
    1877                 :   // If needed, unset the properties that don't have a flag that allows
    1878                 :   // them to be set for this style context.  (For example, only some
    1879                 :   // properties apply to :first-line and :first-letter.)
    1880               0 :   PRUint32 pseudoRestriction = GetPseudoRestriction(aContext);
    1881               0 :   if (pseudoRestriction) {
    1882               0 :     UnsetPropertiesWithoutFlags(aSID, &ruleData, pseudoRestriction);
    1883                 : 
    1884                 :     // Recompute |detail| based on the restrictions we just applied.
    1885                 :     // We can adjust |detail| arbitrarily because of the restriction
    1886                 :     // rule added in nsStyleSet::WalkRestrictionRule.
    1887               0 :     detail = CheckSpecifiedProperties(aSID, &ruleData);
    1888                 :   }
    1889                 : 
    1890               0 :   NS_ASSERTION(!startStruct || (detail != eRuleFullReset &&
    1891                 :                                 detail != eRuleFullMixed &&
    1892                 :                                 detail != eRuleFullInherited),
    1893                 :                "can't have start struct and be fully specified");
    1894                 : 
    1895               0 :   bool isReset = nsCachedStyleData::IsReset(aSID);
    1896               0 :   if (!highestNode)
    1897               0 :     highestNode = rootNode;
    1898                 : 
    1899               0 :   if (!ruleData.mCanStoreInRuleTree)
    1900               0 :     detail = eRulePartialMixed; // Treat as though some data is specified to avoid
    1901                 :                                 // the optimizations and force data computation.
    1902                 : 
    1903               0 :   if (detail == eRuleNone && startStruct && !ruleData.mPostResolveCallback) {
    1904                 :     // We specified absolutely no rule information, but a parent rule in the tree
    1905                 :     // specified all the rule information.  We set a bit along the branch from our
    1906                 :     // node in the tree to the node that specified the data that tells nodes on that
    1907                 :     // branch that they never need to examine their rules for this particular struct type
    1908                 :     // ever again.
    1909               0 :     PropagateDependentBit(bit, ruleNode);
    1910               0 :     return startStruct;
    1911                 :   }
    1912                 :   // FIXME Do we need to check for mPostResolveCallback?
    1913               0 :   if ((!startStruct && !isReset &&
    1914                 :        (detail == eRuleNone || detail == eRulePartialInherited)) ||
    1915                 :       detail == eRuleFullInherited) {
    1916                 :     // We specified no non-inherited information and neither did any of
    1917                 :     // our parent rules.
    1918                 : 
    1919                 :     // We set a bit along the branch from the highest node (ruleNode)
    1920                 :     // down to our node (this) indicating that no non-inherited data was
    1921                 :     // specified.  This bit is guaranteed to be set already on the path
    1922                 :     // from the highest node to the root node in the case where
    1923                 :     // (detail == eRuleNone), which is the most common case here.
    1924                 :     // We must check |!isReset| because the Compute*Data functions for
    1925                 :     // reset structs wouldn't handle none bits correctly.
    1926               0 :     if (highestNode != this && !isReset)
    1927               0 :       PropagateNoneBit(bit, highestNode);
    1928                 : 
    1929                 :     // All information must necessarily be inherited from our parent style context.
    1930                 :     // In the absence of any computed data in the rule tree and with
    1931                 :     // no rules specified that didn't have values of 'inherit', we should check our parent.
    1932               0 :     nsStyleContext* parentContext = aContext->GetParent();
    1933               0 :     if (isReset) {
    1934                 :       /* Reset structs don't inherit from first-line. */
    1935                 :       /* See similar code in COMPUTE_START_RESET */
    1936               0 :       while (parentContext &&
    1937               0 :              parentContext->GetPseudo() == nsCSSPseudoElements::firstLine) {
    1938               0 :         parentContext = parentContext->GetParent();
    1939                 :       }
    1940                 :     }
    1941               0 :     if (parentContext) {
    1942                 :       // We have a parent, and so we should just inherit from the parent.
    1943                 :       // Set the inherit bits on our context.  These bits tell the style context that
    1944                 :       // it never has to go back to the rule tree for data.  Instead the style context tree
    1945                 :       // should be walked to find the data.
    1946               0 :       const void* parentStruct = parentContext->GetStyleData(aSID);
    1947               0 :       aContext->AddStyleBit(bit); // makes const_cast OK.
    1948               0 :       aContext->SetStyle(aSID, const_cast<void*>(parentStruct));
    1949               0 :       return parentStruct;
    1950                 :     }
    1951                 :     else
    1952                 :       // We are the root.  In the case of fonts, the default values just
    1953                 :       // come from the pres context.
    1954               0 :       return SetDefaultOnRoot(aSID, aContext);
    1955                 :   }
    1956                 : 
    1957                 :   // We need to compute the data from the information that the rules specified.
    1958                 :   const void* res;
    1959                 : #define STYLE_STRUCT_TEST aSID
    1960                 : #define STYLE_STRUCT(name, checkdata_cb, ctor_args)                           \
    1961                 :   res = Compute##name##Data(startStruct, &ruleData, aContext,                 \
    1962                 :                             highestNode, detail, ruleData.mCanStoreInRuleTree);
    1963                 : #include "nsStyleStructList.h"
    1964                 : #undef STYLE_STRUCT
    1965                 : #undef STYLE_STRUCT_TEST
    1966                 : 
    1967                 :   // If we have a post-resolve callback, handle that now.
    1968               0 :   if (ruleData.mPostResolveCallback && (NS_LIKELY(res != nsnull)))
    1969               0 :     (*ruleData.mPostResolveCallback)(const_cast<void*>(res), &ruleData);
    1970                 : 
    1971                 :   // Now return the result.
    1972               0 :   return res;
    1973                 : }
    1974                 : 
    1975                 : const void*
    1976               0 : nsRuleNode::SetDefaultOnRoot(const nsStyleStructID aSID, nsStyleContext* aContext)
    1977                 : {
    1978               0 :   switch (aSID) {
    1979                 :     case eStyleStruct_Font:
    1980                 :     {
    1981               0 :       nsStyleFont* fontData = new (mPresContext) nsStyleFont(mPresContext);
    1982               0 :       if (NS_LIKELY(fontData != nsnull)) {
    1983               0 :         nscoord minimumFontSize = mPresContext->MinFontSize(fontData->mLanguage);
    1984                 : 
    1985               0 :         if (minimumFontSize > 0 && !mPresContext->IsChrome()) {
    1986               0 :           fontData->mFont.size = NS_MAX(fontData->mSize, minimumFontSize);
    1987                 :         }
    1988                 :         else {
    1989               0 :           fontData->mFont.size = fontData->mSize;
    1990                 :         }
    1991               0 :         aContext->SetStyle(eStyleStruct_Font, fontData);
    1992                 :       }
    1993               0 :       return fontData;
    1994                 :     }
    1995                 :     case eStyleStruct_Display:
    1996                 :     {
    1997               0 :       nsStyleDisplay* disp = new (mPresContext) nsStyleDisplay();
    1998               0 :       if (NS_LIKELY(disp != nsnull)) {
    1999               0 :         aContext->SetStyle(eStyleStruct_Display, disp);
    2000                 :       }
    2001               0 :       return disp;
    2002                 :     }
    2003                 :     case eStyleStruct_Visibility:
    2004                 :     {
    2005               0 :       nsStyleVisibility* vis = new (mPresContext) nsStyleVisibility(mPresContext);
    2006               0 :       if (NS_LIKELY(vis != nsnull)) {
    2007               0 :         aContext->SetStyle(eStyleStruct_Visibility, vis);
    2008                 :       }
    2009               0 :       return vis;
    2010                 :     }
    2011                 :     case eStyleStruct_Text:
    2012                 :     {
    2013               0 :       nsStyleText* text = new (mPresContext) nsStyleText();
    2014               0 :       if (NS_LIKELY(text != nsnull)) {
    2015               0 :         aContext->SetStyle(eStyleStruct_Text, text);
    2016                 :       }
    2017               0 :       return text;
    2018                 :     }
    2019                 :     case eStyleStruct_TextReset:
    2020                 :     {
    2021               0 :       nsStyleTextReset* text = new (mPresContext) nsStyleTextReset();
    2022               0 :       if (NS_LIKELY(text != nsnull)) {
    2023               0 :         aContext->SetStyle(eStyleStruct_TextReset, text);
    2024                 :       }
    2025               0 :       return text;
    2026                 :     }
    2027                 :     case eStyleStruct_Color:
    2028                 :     {
    2029               0 :       nsStyleColor* color = new (mPresContext) nsStyleColor(mPresContext);
    2030               0 :       if (NS_LIKELY(color != nsnull)) {
    2031               0 :         aContext->SetStyle(eStyleStruct_Color, color);
    2032                 :       }
    2033               0 :       return color;
    2034                 :     }
    2035                 :     case eStyleStruct_Background:
    2036                 :     {
    2037               0 :       nsStyleBackground* bg = new (mPresContext) nsStyleBackground();
    2038               0 :       if (NS_LIKELY(bg != nsnull)) {
    2039               0 :         aContext->SetStyle(eStyleStruct_Background, bg);
    2040                 :       }
    2041               0 :       return bg;
    2042                 :     }
    2043                 :     case eStyleStruct_Margin:
    2044                 :     {
    2045               0 :       nsStyleMargin* margin = new (mPresContext) nsStyleMargin();
    2046               0 :       if (NS_LIKELY(margin != nsnull)) {
    2047               0 :         aContext->SetStyle(eStyleStruct_Margin, margin);
    2048                 :       }
    2049               0 :       return margin;
    2050                 :     }
    2051                 :     case eStyleStruct_Border:
    2052                 :     {
    2053               0 :       nsStyleBorder* border = new (mPresContext) nsStyleBorder(mPresContext);
    2054               0 :       if (NS_LIKELY(border != nsnull)) {
    2055               0 :         aContext->SetStyle(eStyleStruct_Border, border);
    2056                 :       }
    2057               0 :       return border;
    2058                 :     }
    2059                 :     case eStyleStruct_Padding:
    2060                 :     {
    2061               0 :       nsStylePadding* padding = new (mPresContext) nsStylePadding();
    2062               0 :       if (NS_LIKELY(padding != nsnull)) {
    2063               0 :         aContext->SetStyle(eStyleStruct_Padding, padding);
    2064                 :       }
    2065               0 :       return padding;
    2066                 :     }
    2067                 :     case eStyleStruct_Outline:
    2068                 :     {
    2069               0 :       nsStyleOutline* outline = new (mPresContext) nsStyleOutline(mPresContext);
    2070               0 :       if (NS_LIKELY(outline != nsnull)) {
    2071               0 :         aContext->SetStyle(eStyleStruct_Outline, outline);
    2072                 :       }
    2073               0 :       return outline;
    2074                 :     }
    2075                 :     case eStyleStruct_List:
    2076                 :     {
    2077               0 :       nsStyleList* list = new (mPresContext) nsStyleList();
    2078               0 :       if (NS_LIKELY(list != nsnull)) {
    2079               0 :         aContext->SetStyle(eStyleStruct_List, list);
    2080                 :       }
    2081               0 :       return list;
    2082                 :     }
    2083                 :     case eStyleStruct_Position:
    2084                 :     {
    2085               0 :       nsStylePosition* pos = new (mPresContext) nsStylePosition();
    2086               0 :       if (NS_LIKELY(pos != nsnull)) {
    2087               0 :         aContext->SetStyle(eStyleStruct_Position, pos);
    2088                 :       }
    2089               0 :       return pos;
    2090                 :     }
    2091                 :     case eStyleStruct_Table:
    2092                 :     {
    2093               0 :       nsStyleTable* table = new (mPresContext) nsStyleTable();
    2094               0 :       if (NS_LIKELY(table != nsnull)) {
    2095               0 :         aContext->SetStyle(eStyleStruct_Table, table);
    2096                 :       }
    2097               0 :       return table;
    2098                 :     }
    2099                 :     case eStyleStruct_TableBorder:
    2100                 :     {
    2101               0 :       nsStyleTableBorder* table = new (mPresContext) nsStyleTableBorder(mPresContext);
    2102               0 :       if (NS_LIKELY(table != nsnull)) {
    2103               0 :         aContext->SetStyle(eStyleStruct_TableBorder, table);
    2104                 :       }
    2105               0 :       return table;
    2106                 :     }
    2107                 :     case eStyleStruct_Content:
    2108                 :     {
    2109               0 :       nsStyleContent* content = new (mPresContext) nsStyleContent();
    2110               0 :       if (NS_LIKELY(content != nsnull)) {
    2111               0 :         aContext->SetStyle(eStyleStruct_Content, content);
    2112                 :       }
    2113               0 :       return content;
    2114                 :     }
    2115                 :     case eStyleStruct_Quotes:
    2116                 :     {
    2117               0 :       nsStyleQuotes* quotes = new (mPresContext) nsStyleQuotes();
    2118               0 :       if (NS_LIKELY(quotes != nsnull)) {
    2119               0 :         aContext->SetStyle(eStyleStruct_Quotes, quotes);
    2120                 :       }
    2121               0 :       return quotes;
    2122                 :     }
    2123                 :     case eStyleStruct_UserInterface:
    2124                 :     {
    2125               0 :       nsStyleUserInterface* ui = new (mPresContext) nsStyleUserInterface();
    2126               0 :       if (NS_LIKELY(ui != nsnull)) {
    2127               0 :         aContext->SetStyle(eStyleStruct_UserInterface, ui);
    2128                 :       }
    2129               0 :       return ui;
    2130                 :     }
    2131                 :     case eStyleStruct_UIReset:
    2132                 :     {
    2133               0 :       nsStyleUIReset* ui = new (mPresContext) nsStyleUIReset();
    2134               0 :       if (NS_LIKELY(ui != nsnull)) {
    2135               0 :         aContext->SetStyle(eStyleStruct_UIReset, ui);
    2136                 :       }
    2137               0 :       return ui;
    2138                 :     }
    2139                 : 
    2140                 :     case eStyleStruct_XUL:
    2141                 :     {
    2142               0 :       nsStyleXUL* xul = new (mPresContext) nsStyleXUL();
    2143               0 :       if (NS_LIKELY(xul != nsnull)) {
    2144               0 :         aContext->SetStyle(eStyleStruct_XUL, xul);
    2145                 :       }
    2146               0 :       return xul;
    2147                 :     }
    2148                 : 
    2149                 :     case eStyleStruct_Column:
    2150                 :     {
    2151               0 :       nsStyleColumn* column = new (mPresContext) nsStyleColumn(mPresContext);
    2152               0 :       if (NS_LIKELY(column != nsnull)) {
    2153               0 :         aContext->SetStyle(eStyleStruct_Column, column);
    2154                 :       }
    2155               0 :       return column;
    2156                 :     }
    2157                 : 
    2158                 :     case eStyleStruct_SVG:
    2159                 :     {
    2160               0 :       nsStyleSVG* svg = new (mPresContext) nsStyleSVG();
    2161               0 :       if (NS_LIKELY(svg != nsnull)) {
    2162               0 :         aContext->SetStyle(eStyleStruct_SVG, svg);
    2163                 :       }
    2164               0 :       return svg;
    2165                 :     }
    2166                 : 
    2167                 :     case eStyleStruct_SVGReset:
    2168                 :     {
    2169               0 :       nsStyleSVGReset* svgReset = new (mPresContext) nsStyleSVGReset();
    2170               0 :       if (NS_LIKELY(svgReset != nsnull)) {
    2171               0 :         aContext->SetStyle(eStyleStruct_SVGReset, svgReset);
    2172                 :       }
    2173               0 :       return svgReset;
    2174                 :     }
    2175                 :     default:
    2176                 :       /*
    2177                 :        * unhandled case: nsStyleStructID_Length.
    2178                 :        * last item of nsStyleStructID, to know its length.
    2179                 :        */
    2180               0 :       return nsnull;
    2181                 :   }
    2182                 :   return nsnull;
    2183                 : }
    2184                 : 
    2185                 : /*
    2186                 :  * This function handles cascading of *-left or *-right box properties
    2187                 :  * against *-start (which is L for LTR and R for RTL) or *-end (which is
    2188                 :  * R for LTR and L for RTL).
    2189                 :  *
    2190                 :  * Cascading these properties correctly is hard because we need to
    2191                 :  * cascade two properties as one, but which two properties depends on a
    2192                 :  * third property ('direction').  We solve this by treating each of
    2193                 :  * these properties (say, 'margin-start') as a shorthand that sets a
    2194                 :  * property containing the value of the property specified
    2195                 :  * ('margin-start-value') and sets a pair of properties
    2196                 :  * ('margin-left-ltr-source' and 'margin-right-rtl-source') saying which
    2197                 :  * of the properties we use.  Thus, when we want to compute the value of
    2198                 :  * 'margin-left' when 'direction' is 'ltr', we look at the value of
    2199                 :  * 'margin-left-ltr-source', which tells us whether to use the highest
    2200                 :  * 'margin-left' in the cascade or the highest 'margin-start'.
    2201                 :  *
    2202                 :  * Finally, since we can compute the normal (*-left and *-right)
    2203                 :  * properties in a loop, this function works by modifying the data we
    2204                 :  * will use in that loop (which the caller must copy from the const
    2205                 :  * input).
    2206                 :  */
    2207                 : void
    2208               0 : nsRuleNode::AdjustLogicalBoxProp(nsStyleContext* aContext,
    2209                 :                                  const nsCSSValue& aLTRSource,
    2210                 :                                  const nsCSSValue& aRTLSource,
    2211                 :                                  const nsCSSValue& aLTRLogicalValue,
    2212                 :                                  const nsCSSValue& aRTLLogicalValue,
    2213                 :                                  mozilla::css::Side aSide,
    2214                 :                                  nsCSSRect& aValueRect,
    2215                 :                                  bool& aCanStoreInRuleTree)
    2216                 : {
    2217               0 :   bool LTRlogical = aLTRSource.GetUnit() == eCSSUnit_Enumerated &&
    2218               0 :                       aLTRSource.GetIntValue() == NS_BOXPROP_SOURCE_LOGICAL;
    2219               0 :   bool RTLlogical = aRTLSource.GetUnit() == eCSSUnit_Enumerated &&
    2220               0 :                       aRTLSource.GetIntValue() == NS_BOXPROP_SOURCE_LOGICAL;
    2221               0 :   if (LTRlogical || RTLlogical) {
    2222                 :     // We can't cache anything on the rule tree if we use any data from
    2223                 :     // the style context, since data cached in the rule tree could be
    2224                 :     // used with a style context with a different value.
    2225               0 :     aCanStoreInRuleTree = false;
    2226               0 :     PRUint8 dir = aContext->GetStyleVisibility()->mDirection;
    2227                 : 
    2228               0 :     if (dir == NS_STYLE_DIRECTION_LTR) {
    2229               0 :       if (LTRlogical)
    2230               0 :         aValueRect.*(nsCSSRect::sides[aSide]) = aLTRLogicalValue;
    2231                 :     } else {
    2232               0 :       if (RTLlogical)
    2233               0 :         aValueRect.*(nsCSSRect::sides[aSide]) = aRTLLogicalValue;
    2234               0 :     }
    2235               0 :   } else if (aLTRLogicalValue.GetUnit() == eCSSUnit_Inherit ||
    2236               0 :              aRTLLogicalValue.GetUnit() == eCSSUnit_Inherit) {
    2237                 :     // It actually is valid to store this in the ruletree, since
    2238                 :     // LTRlogical and RTLlogical are both false, but doing that will
    2239                 :     // trigger asserts.  Silence those.
    2240               0 :     aCanStoreInRuleTree = false;
    2241                 :   }
    2242               0 : }
    2243                 : 
    2244                 : /**
    2245                 :  * Begin an nsRuleNode::Compute*Data function for an inherited struct.
    2246                 :  *
    2247                 :  * @param type_ The nsStyle* type this function computes.
    2248                 :  * @param ctorargs_ The arguments used for the default nsStyle* constructor.
    2249                 :  * @param data_ Variable (declared here) holding the result of this
    2250                 :  *              function.
    2251                 :  * @param parentdata_ Variable (declared here) holding the parent style
    2252                 :  *                    context's data for this struct.
    2253                 :  */
    2254                 : #define COMPUTE_START_INHERITED(type_, ctorargs_, data_, parentdata_)         \
    2255                 :   NS_ASSERTION(aRuleDetail != eRuleFullInherited,                             \
    2256                 :                "should not have bothered calling Compute*Data");              \
    2257                 :                                                                               \
    2258                 :   nsStyleContext* parentContext = aContext->GetParent();                      \
    2259                 :                                                                               \
    2260                 :   nsStyle##type_* data_ = nsnull;                                             \
    2261                 :   const nsStyle##type_* parentdata_ = nsnull;                                 \
    2262                 :   bool canStoreInRuleTree = aCanStoreInRuleTree;                            \
    2263                 :                                                                               \
    2264                 :   /* If |canStoreInRuleTree| might be true by the time we're done, we */      \
    2265                 :   /* can't call parentContext->GetStyle##type_() since it could recur into */ \
    2266                 :   /* setting the same struct on the same rule node, causing a leak. */        \
    2267                 :   if (parentContext && aRuleDetail != eRuleFullReset &&                       \
    2268                 :       (!aStartStruct || (aRuleDetail != eRulePartialReset &&                  \
    2269                 :                          aRuleDetail != eRuleNone)))                          \
    2270                 :     parentdata_ = parentContext->GetStyle##type_();                           \
    2271                 :   if (aStartStruct)                                                           \
    2272                 :     /* We only need to compute the delta between this computed data and */    \
    2273                 :     /* our computed data. */                                                  \
    2274                 :     data_ = new (mPresContext)                                                \
    2275                 :             nsStyle##type_(*static_cast<nsStyle##type_*>(aStartStruct));      \
    2276                 :   else {                                                                      \
    2277                 :     if (aRuleDetail != eRuleFullMixed && aRuleDetail != eRuleFullReset) {     \
    2278                 :       /* No question. We will have to inherit. Go ahead and init */           \
    2279                 :       /* with inherited vals from parent. */                                  \
    2280                 :       canStoreInRuleTree = false;                                          \
    2281                 :       if (parentdata_)                                                        \
    2282                 :         data_ = new (mPresContext) nsStyle##type_(*parentdata_);              \
    2283                 :       else                                                                    \
    2284                 :         data_ = new (mPresContext) nsStyle##type_ ctorargs_;                  \
    2285                 :     }                                                                         \
    2286                 :     else                                                                      \
    2287                 :       data_ = new (mPresContext) nsStyle##type_ ctorargs_;                    \
    2288                 :   }                                                                           \
    2289                 :                                                                               \
    2290                 :   if (NS_UNLIKELY(!data_))                                                    \
    2291                 :     return nsnull;  /* Out Of Memory */                                       \
    2292                 :   if (!parentdata_)                                                           \
    2293                 :     parentdata_ = data_;
    2294                 : 
    2295                 : /**
    2296                 :  * Begin an nsRuleNode::Compute*Data function for a reset struct.
    2297                 :  *
    2298                 :  * @param type_ The nsStyle* type this function computes.
    2299                 :  * @param ctorargs_ The arguments used for the default nsStyle* constructor.
    2300                 :  * @param data_ Variable (declared here) holding the result of this
    2301                 :  *              function.
    2302                 :  * @param parentdata_ Variable (declared here) holding the parent style
    2303                 :  *                    context's data for this struct.
    2304                 :  */
    2305                 : #define COMPUTE_START_RESET(type_, ctorargs_, data_, parentdata_)             \
    2306                 :   NS_ASSERTION(aRuleDetail != eRuleFullInherited,                             \
    2307                 :                "should not have bothered calling Compute*Data");              \
    2308                 :                                                                               \
    2309                 :   nsStyleContext* parentContext = aContext->GetParent();                      \
    2310                 :   /* Reset structs don't inherit from first-line */                           \
    2311                 :   /* See similar code in WalkRuleTree */                                      \
    2312                 :   while (parentContext &&                                                     \
    2313                 :          parentContext->GetPseudo() == nsCSSPseudoElements::firstLine) {      \
    2314                 :     parentContext = parentContext->GetParent();                               \
    2315                 :   }                                                                           \
    2316                 :                                                                               \
    2317                 :   nsStyle##type_* data_;                                                      \
    2318                 :   if (aStartStruct)                                                           \
    2319                 :     /* We only need to compute the delta between this computed data and */    \
    2320                 :     /* our computed data. */                                                  \
    2321                 :     data_ = new (mPresContext)                                                \
    2322                 :             nsStyle##type_(*static_cast<nsStyle##type_*>(aStartStruct));      \
    2323                 :   else                                                                        \
    2324                 :     data_ = new (mPresContext) nsStyle##type_ ctorargs_;                      \
    2325                 :                                                                               \
    2326                 :   if (NS_UNLIKELY(!data_))                                                    \
    2327                 :     return nsnull;  /* Out Of Memory */                                       \
    2328                 :                                                                               \
    2329                 :   /* If |canStoreInRuleTree| might be true by the time we're done, we */      \
    2330                 :   /* can't call parentContext->GetStyle##type_() since it could recur into */ \
    2331                 :   /* setting the same struct on the same rule node, causing a leak. */        \
    2332                 :   const nsStyle##type_* parentdata_ = data_;                                  \
    2333                 :   if (parentContext &&                                                        \
    2334                 :       aRuleDetail != eRuleFullReset &&                                        \
    2335                 :       aRuleDetail != eRulePartialReset &&                                     \
    2336                 :       aRuleDetail != eRuleNone)                                               \
    2337                 :     parentdata_ = parentContext->GetStyle##type_();                           \
    2338                 :   bool canStoreInRuleTree = aCanStoreInRuleTree;
    2339                 : 
    2340                 : /**
    2341                 :  * Begin an nsRuleNode::Compute*Data function for an inherited struct.
    2342                 :  *
    2343                 :  * @param type_ The nsStyle* type this function computes.
    2344                 :  * @param data_ Variable holding the result of this function.
    2345                 :  */
    2346                 : #define COMPUTE_END_INHERITED(type_, data_)                                   \
    2347                 :   NS_POSTCONDITION(!canStoreInRuleTree || aRuleDetail == eRuleFullReset ||    \
    2348                 :                    (aStartStruct && aRuleDetail == eRulePartialReset),        \
    2349                 :                    "canStoreInRuleTree must be false for inherited structs "  \
    2350                 :                    "unless all properties have been specified with values "   \
    2351                 :                    "other than inherit");                                     \
    2352                 :   if (canStoreInRuleTree) {                                                   \
    2353                 :     /* We were fully specified and can therefore be cached right on the */    \
    2354                 :     /* rule node. */                                                          \
    2355                 :     if (!aHighestNode->mStyleData.mInheritedData) {                           \
    2356                 :       aHighestNode->mStyleData.mInheritedData =                               \
    2357                 :         new (mPresContext) nsInheritedStyleData;                              \
    2358                 :       if (NS_UNLIKELY(!aHighestNode->mStyleData.mInheritedData)) {            \
    2359                 :         data_->Destroy(mPresContext);                                         \
    2360                 :         return nsnull;                                                        \
    2361                 :       }                                                                       \
    2362                 :     }                                                                         \
    2363                 :     NS_ASSERTION(!aHighestNode->mStyleData.mInheritedData->                   \
    2364                 :                    mStyleStructs[eStyleStruct_##type_],                       \
    2365                 :                  "Going to leak style data");                                 \
    2366                 :     aHighestNode->mStyleData.mInheritedData->                                 \
    2367                 :       mStyleStructs[eStyleStruct_##type_] = data_;                            \
    2368                 :     /* Propagate the bit down. */                                             \
    2369                 :     PropagateDependentBit(NS_STYLE_INHERIT_BIT(type_), aHighestNode);         \
    2370                 :     /* Tell the style context that it doesn't own the data */                 \
    2371                 :     aContext->                                                                \
    2372                 :       AddStyleBit(nsCachedStyleData::GetBitForSID(eStyleStruct_##type_));     \
    2373                 :   }                                                                           \
    2374                 :   /* Always cache inherited data on the style context */                      \
    2375                 :   aContext->SetStyle##type_(data_);                                           \
    2376                 :                                                                               \
    2377                 :   return data_;
    2378                 : 
    2379                 : /**
    2380                 :  * Begin an nsRuleNode::Compute*Data function for a reset struct.
    2381                 :  *
    2382                 :  * @param type_ The nsStyle* type this function computes.
    2383                 :  * @param data_ Variable holding the result of this function.
    2384                 :  */
    2385                 : #define COMPUTE_END_RESET(type_, data_)                                       \
    2386                 :   NS_POSTCONDITION(!canStoreInRuleTree ||                                     \
    2387                 :                    aRuleDetail == eRuleNone ||                                \
    2388                 :                    aRuleDetail == eRulePartialReset ||                        \
    2389                 :                    aRuleDetail == eRuleFullReset,                             \
    2390                 :                    "canStoreInRuleTree must be false for reset structs "      \
    2391                 :                    "if any properties were specified as inherit");            \
    2392                 :   if (!canStoreInRuleTree)                                                    \
    2393                 :     /* We can't be cached in the rule node.  We have to be put right */       \
    2394                 :     /* on the style context. */                                               \
    2395                 :     aContext->SetStyle(eStyleStruct_##type_, data_);                          \
    2396                 :   else {                                                                      \
    2397                 :     /* We were fully specified and can therefore be cached right on the */    \
    2398                 :     /* rule node. */                                                          \
    2399                 :     if (!aHighestNode->mStyleData.mResetData) {                               \
    2400                 :       aHighestNode->mStyleData.mResetData =                                   \
    2401                 :         new (mPresContext) nsResetStyleData;                                  \
    2402                 :       if (NS_UNLIKELY(!aHighestNode->mStyleData.mResetData)) {                \
    2403                 :         data_->Destroy(mPresContext);                                         \
    2404                 :         return nsnull;                                                        \
    2405                 :       }                                                                       \
    2406                 :     }                                                                         \
    2407                 :     NS_ASSERTION(!aHighestNode->mStyleData.mResetData->                       \
    2408                 :                    mStyleStructs[eStyleStruct_##type_],                       \
    2409                 :                  "Going to leak style data");                                 \
    2410                 :     aHighestNode->mStyleData.mResetData->                                     \
    2411                 :       mStyleStructs[eStyleStruct_##type_] = data_;                            \
    2412                 :     /* Propagate the bit down. */                                             \
    2413                 :     PropagateDependentBit(NS_STYLE_INHERIT_BIT(type_), aHighestNode);         \
    2414                 :   }                                                                           \
    2415                 :                                                                               \
    2416                 :   return data_;
    2417                 : 
    2418                 : // This function figures out how much scaling should be suppressed to
    2419                 : // satisfy scriptminsize. This is our attempt to implement
    2420                 : // http://www.w3.org/TR/MathML2/chapter3.html#id.3.3.4.2.2
    2421                 : // This is called after mScriptLevel, mScriptMinSize and mScriptSizeMultiplier
    2422                 : // have been set in aFont.
    2423                 : //
    2424                 : // Here are the invariants we enforce:
    2425                 : // 1) A decrease in size must not reduce the size below minscriptsize.
    2426                 : // 2) An increase in size must not increase the size above the size we would
    2427                 : // have if minscriptsize had not been applied anywhere.
    2428                 : // 3) The scriptlevel-induced size change must between 1.0 and the parent's
    2429                 : // scriptsizemultiplier^(new script level - old script level), as close to the
    2430                 : // latter as possible subject to constraints 1 and 2.
    2431                 : static nscoord
    2432               0 : ComputeScriptLevelSize(const nsStyleFont* aFont, const nsStyleFont* aParentFont,
    2433                 :                        nsPresContext* aPresContext, nscoord* aUnconstrainedSize)
    2434                 : {
    2435                 :   PRInt32 scriptLevelChange =
    2436               0 :     aFont->mScriptLevel - aParentFont->mScriptLevel;
    2437               0 :   if (scriptLevelChange == 0) {
    2438               0 :     *aUnconstrainedSize = aParentFont->mScriptUnconstrainedSize;
    2439                 :     // Constraint #3 says that we cannot change size, and #1 and #2 are always
    2440                 :     // satisfied with no change. It's important this be fast because it covers
    2441                 :     // all non-MathML content.
    2442               0 :     return aParentFont->mSize;
    2443                 :   }
    2444                 : 
    2445                 :   // Compute actual value of minScriptSize
    2446                 :   nscoord minScriptSize =
    2447               0 :     nsStyleFont::ZoomText(aPresContext, aParentFont->mScriptMinSize);
    2448                 : 
    2449                 :   double scriptLevelScale =
    2450               0 :     pow(aParentFont->mScriptSizeMultiplier, scriptLevelChange);
    2451                 :   // Compute the size we would have had if minscriptsize had never been
    2452                 :   // applied, also prevent overflow (bug 413274)
    2453                 :   *aUnconstrainedSize =
    2454                 :     NSToCoordRound(NS_MIN(aParentFont->mScriptUnconstrainedSize*scriptLevelScale,
    2455               0 :                           double(nscoord_MAX)));
    2456                 :   // Compute the size we could get via scriptlevel change
    2457                 :   nscoord scriptLevelSize =
    2458                 :     NSToCoordRound(NS_MIN(aParentFont->mSize*scriptLevelScale,
    2459               0 :                           double(nscoord_MAX)));
    2460               0 :   if (scriptLevelScale <= 1.0) {
    2461               0 :     if (aParentFont->mSize <= minScriptSize) {
    2462                 :       // We can't decrease the font size at all, so just stick to no change
    2463                 :       // (authors are allowed to explicitly set the font size smaller than
    2464                 :       // minscriptsize)
    2465               0 :       return aParentFont->mSize;
    2466                 :     }
    2467                 :     // We can decrease, so apply constraint #1
    2468               0 :     return NS_MAX(minScriptSize, scriptLevelSize);
    2469                 :   } else {
    2470                 :     // scriptminsize can only make sizes larger than the unconstrained size
    2471               0 :     NS_ASSERTION(*aUnconstrainedSize <= scriptLevelSize, "How can this ever happen?");
    2472                 :     // Apply constraint #2
    2473               0 :     return NS_MIN(scriptLevelSize, NS_MAX(*aUnconstrainedSize, minScriptSize));
    2474                 :   }
    2475                 : }
    2476                 : 
    2477                 : struct SetFontSizeCalcOps : public css::BasicCoordCalcOps,
    2478                 :                             public css::NumbersAlreadyNormalizedOps
    2479                 : {
    2480                 :   // The parameters beyond aValue that we need for CalcLengthWith.
    2481                 :   const nscoord mParentSize;
    2482                 :   const nsStyleFont* const mParentFont;
    2483                 :   nsPresContext* const mPresContext;
    2484                 :   const bool mAtRoot;
    2485                 :   bool& mCanStoreInRuleTree;
    2486                 : 
    2487               0 :   SetFontSizeCalcOps(nscoord aParentSize, const nsStyleFont* aParentFont,
    2488                 :                      nsPresContext* aPresContext, bool aAtRoot,
    2489                 :                      bool& aCanStoreInRuleTree)
    2490                 :     : mParentSize(aParentSize),
    2491                 :       mParentFont(aParentFont),
    2492                 :       mPresContext(aPresContext),
    2493                 :       mAtRoot(aAtRoot),
    2494               0 :       mCanStoreInRuleTree(aCanStoreInRuleTree)
    2495                 :   {
    2496               0 :   }
    2497                 : 
    2498               0 :   result_type ComputeLeafValue(const nsCSSValue& aValue)
    2499                 :   {
    2500                 :     nscoord size;
    2501               0 :     if (aValue.IsLengthUnit()) {
    2502                 :       // Note that font-based length units use the parent's size
    2503                 :       // unadjusted for scriptlevel changes. A scriptlevel change
    2504                 :       // between us and the parent is simply ignored.
    2505                 :       size = CalcLengthWith(aValue, mParentSize,
    2506                 :                             mParentFont,
    2507                 :                             nsnull, mPresContext, mAtRoot,
    2508               0 :                             true, mCanStoreInRuleTree);
    2509               0 :       if (!aValue.IsRelativeLengthUnit()) {
    2510               0 :         size = nsStyleFont::ZoomText(mPresContext, size);
    2511                 :       }
    2512                 :     }
    2513               0 :     else if (eCSSUnit_Percent == aValue.GetUnit()) {
    2514               0 :       mCanStoreInRuleTree = false;
    2515                 :       // Note that % units use the parent's size unadjusted for scriptlevel
    2516                 :       // changes. A scriptlevel change between us and the parent is simply
    2517                 :       // ignored.
    2518                 :       // aValue.GetPercentValue() may be negative for, e.g., calc(-50%)
    2519               0 :       size = NSCoordSaturatingMultiply(mParentSize, aValue.GetPercentValue());
    2520                 :     } else {
    2521               0 :       NS_ABORT_IF_FALSE(false, "unexpected value");
    2522               0 :       size = mParentSize;
    2523                 :     }
    2524                 : 
    2525               0 :     return size;
    2526                 :   }
    2527                 : };
    2528                 : 
    2529                 : /* static */ void
    2530               0 : nsRuleNode::SetFontSize(nsPresContext* aPresContext,
    2531                 :                         const nsRuleData* aRuleData,
    2532                 :                         const nsStyleFont* aFont,
    2533                 :                         const nsStyleFont* aParentFont,
    2534                 :                         nscoord* aSize,
    2535                 :                         const nsFont& aSystemFont,
    2536                 :                         nscoord aParentSize,
    2537                 :                         nscoord aScriptLevelAdjustedParentSize,
    2538                 :                         bool aUsedStartStruct,
    2539                 :                         bool aAtRoot,
    2540                 :                         bool& aCanStoreInRuleTree)
    2541                 : {
    2542               0 :   bool zoom = false;
    2543                 :   PRInt32 baseSize = (PRInt32) aPresContext->
    2544               0 :     GetDefaultFont(aFont->mGenericID, aFont->mLanguage)->size;
    2545               0 :   const nsCSSValue* sizeValue = aRuleData->ValueForFontSize();
    2546               0 :   if (eCSSUnit_Enumerated == sizeValue->GetUnit()) {
    2547               0 :     PRInt32 value = sizeValue->GetIntValue();
    2548                 : 
    2549               0 :     zoom = true;
    2550               0 :     if ((NS_STYLE_FONT_SIZE_XXSMALL <= value) &&
    2551                 :         (value <= NS_STYLE_FONT_SIZE_XXLARGE)) {
    2552                 :       *aSize = nsStyleUtil::CalcFontPointSize(value, baseSize,
    2553               0 :                        aPresContext, eFontSize_CSS);
    2554                 :     }
    2555               0 :     else if (NS_STYLE_FONT_SIZE_XXXLARGE == value) {
    2556                 :       // <font size="7"> is not specified in CSS, so we don't use eFontSize_CSS.
    2557               0 :       *aSize = nsStyleUtil::CalcFontPointSize(value, baseSize, aPresContext);
    2558                 :     }
    2559               0 :     else if (NS_STYLE_FONT_SIZE_LARGER  == value ||
    2560                 :              NS_STYLE_FONT_SIZE_SMALLER == value) {
    2561               0 :       aCanStoreInRuleTree = false;
    2562                 : 
    2563                 :       // Un-zoom so we use the tables correctly.  We'll then rezoom due
    2564                 :       // to the |zoom = true| above.
    2565                 :       // Note that relative units here use the parent's size unadjusted
    2566                 :       // for scriptlevel changes. A scriptlevel change between us and the parent
    2567                 :       // is simply ignored.
    2568                 :       nscoord parentSize =
    2569               0 :         nsStyleFont::UnZoomText(aPresContext, aParentSize);
    2570                 : 
    2571               0 :       if (NS_STYLE_FONT_SIZE_LARGER == value) {
    2572                 :         *aSize = nsStyleUtil::FindNextLargerFontSize(parentSize,
    2573               0 :                          baseSize, aPresContext, eFontSize_CSS);
    2574                 : 
    2575               0 :         NS_ASSERTION(*aSize >= parentSize,
    2576                 :                      "FindNextLargerFontSize failed");
    2577                 :       }
    2578                 :       else {
    2579                 :         *aSize = nsStyleUtil::FindNextSmallerFontSize(parentSize,
    2580               0 :                          baseSize, aPresContext, eFontSize_CSS);
    2581               0 :         NS_ASSERTION(*aSize < parentSize ||
    2582                 :                      parentSize <= nsPresContext::CSSPixelsToAppUnits(1),
    2583                 :                      "FindNextSmallerFontSize failed");
    2584               0 :       }
    2585                 :     } else {
    2586               0 :       NS_NOTREACHED("unexpected value");
    2587                 :     }
    2588                 :   }
    2589               0 :   else if (sizeValue->IsLengthUnit() ||
    2590               0 :            sizeValue->GetUnit() == eCSSUnit_Percent ||
    2591               0 :            sizeValue->IsCalcUnit()) {
    2592                 :     SetFontSizeCalcOps ops(aParentSize, aParentFont,
    2593               0 :                            aPresContext, aAtRoot, aCanStoreInRuleTree);
    2594               0 :     *aSize = css::ComputeCalc(*sizeValue, ops);
    2595               0 :     if (*aSize < 0) {
    2596               0 :       NS_ABORT_IF_FALSE(sizeValue->IsCalcUnit(),
    2597                 :                         "negative lengths and percents should be rejected "
    2598                 :                         "by parser");
    2599               0 :       *aSize = 0;
    2600                 :     }
    2601                 :     // Zoom is handled inside the calc ops when needed.
    2602               0 :     zoom = false;
    2603                 :   }
    2604               0 :   else if (eCSSUnit_System_Font == sizeValue->GetUnit()) {
    2605                 :     // this becomes our cascading size
    2606               0 :     *aSize = aSystemFont.size;
    2607               0 :     zoom = true;
    2608                 :   }
    2609               0 :   else if (eCSSUnit_Inherit == sizeValue->GetUnit()) {
    2610               0 :     aCanStoreInRuleTree = false;
    2611                 :     // We apply scriptlevel change for this case, because the default is
    2612                 :     // to inherit and we don't want explicit "inherit" to differ from the
    2613                 :     // default.
    2614               0 :     *aSize = aScriptLevelAdjustedParentSize;
    2615               0 :     zoom = false;
    2616                 :   }
    2617               0 :   else if (eCSSUnit_Initial == sizeValue->GetUnit()) {
    2618                 :     // The initial value is 'medium', which has magical sizing based on
    2619                 :     // the generic font family, so do that here too.
    2620               0 :     *aSize = baseSize;
    2621               0 :     zoom = true;
    2622                 :   } else {
    2623               0 :     NS_ASSERTION(eCSSUnit_Null == sizeValue->GetUnit(),
    2624                 :                  "What kind of font-size value is this?");
    2625                 :     // if aUsedStartStruct is true, then every single property in the
    2626                 :     // font struct is being set all at once. This means scriptlevel is not
    2627                 :     // going to have any influence on the font size; there is no need to
    2628                 :     // do anything here.
    2629               0 :     if (!aUsedStartStruct && aParentSize != aScriptLevelAdjustedParentSize) {
    2630                 :       // There was no rule affecting the size but the size has been
    2631                 :       // affected by the parent's size via scriptlevel change. So we cannot
    2632                 :       // store the data in the rule tree.
    2633               0 :       aCanStoreInRuleTree = false;
    2634               0 :       *aSize = aScriptLevelAdjustedParentSize;
    2635                 :     }
    2636                 :   }
    2637                 : 
    2638                 :   // We want to zoom the cascaded size so that em-based measurements,
    2639                 :   // line-heights, etc., work.
    2640               0 :   if (zoom) {
    2641               0 :     *aSize = nsStyleFont::ZoomText(aPresContext, *aSize);
    2642                 :   }
    2643               0 : }
    2644                 : 
    2645               0 : static PRInt8 ClampTo8Bit(PRInt32 aValue) {
    2646               0 :   if (aValue < -128)
    2647               0 :     return -128;
    2648               0 :   if (aValue > 127)
    2649               0 :     return 127;
    2650               0 :   return PRInt8(aValue);
    2651                 : }
    2652                 : 
    2653                 : /* static */ void
    2654               0 : nsRuleNode::SetFont(nsPresContext* aPresContext, nsStyleContext* aContext,
    2655                 :                     PRUint8 aGenericFontID, const nsRuleData* aRuleData,
    2656                 :                     const nsStyleFont* aParentFont,
    2657                 :                     nsStyleFont* aFont, bool aUsedStartStruct,
    2658                 :                     bool& aCanStoreInRuleTree)
    2659                 : {
    2660               0 :   bool atRoot = !aContext->GetParent();
    2661                 : 
    2662                 :   // mLanguage must be set before before any of the CalcLengthWith calls
    2663                 :   // (direct calls or calls via SetFontSize) for the cases where |aParentFont|
    2664                 :   // is the same as |aFont|.
    2665                 :   //
    2666                 :   // -x-lang: string, inherit
    2667                 :   // This is not a real CSS property, it is an HTML attribute mapped to CSS.
    2668               0 :   const nsCSSValue* langValue = aRuleData->ValueForLang();
    2669               0 :   if (eCSSUnit_Ident == langValue->GetUnit()) {
    2670               0 :     nsAutoString lang;
    2671               0 :     langValue->GetStringValue(lang);
    2672                 : 
    2673               0 :     nsContentUtils::ASCIIToLower(lang);
    2674               0 :     aFont->mLanguage = do_GetAtom(lang);
    2675                 :   }
    2676                 : 
    2677                 :   const nsFont* defaultVariableFont =
    2678                 :     aPresContext->GetDefaultFont(kPresContext_DefaultVariableFont_ID,
    2679               0 :                                  aFont->mLanguage);
    2680                 : 
    2681                 :   // -moz-system-font: enum (never inherit!)
    2682                 :   MOZ_STATIC_ASSERT(
    2683                 :     NS_STYLE_FONT_CAPTION        == LookAndFeel::eFont_Caption &&
    2684                 :     NS_STYLE_FONT_ICON           == LookAndFeel::eFont_Icon &&
    2685                 :     NS_STYLE_FONT_MENU           == LookAndFeel::eFont_Menu &&
    2686                 :     NS_STYLE_FONT_MESSAGE_BOX    == LookAndFeel::eFont_MessageBox &&
    2687                 :     NS_STYLE_FONT_SMALL_CAPTION  == LookAndFeel::eFont_SmallCaption &&
    2688                 :     NS_STYLE_FONT_STATUS_BAR     == LookAndFeel::eFont_StatusBar &&
    2689                 :     NS_STYLE_FONT_WINDOW         == LookAndFeel::eFont_Window &&
    2690                 :     NS_STYLE_FONT_DOCUMENT       == LookAndFeel::eFont_Document &&
    2691                 :     NS_STYLE_FONT_WORKSPACE      == LookAndFeel::eFont_Workspace &&
    2692                 :     NS_STYLE_FONT_DESKTOP        == LookAndFeel::eFont_Desktop &&
    2693                 :     NS_STYLE_FONT_INFO           == LookAndFeel::eFont_Info &&
    2694                 :     NS_STYLE_FONT_DIALOG         == LookAndFeel::eFont_Dialog &&
    2695                 :     NS_STYLE_FONT_BUTTON         == LookAndFeel::eFont_Button &&
    2696                 :     NS_STYLE_FONT_PULL_DOWN_MENU == LookAndFeel::eFont_PullDownMenu &&
    2697                 :     NS_STYLE_FONT_LIST           == LookAndFeel::eFont_List &&
    2698                 :     NS_STYLE_FONT_FIELD          == LookAndFeel::eFont_Field,
    2699                 :     "LookAndFeel.h system-font constants out of sync with nsStyleConsts.h");
    2700                 : 
    2701                 :   // Fall back to defaultVariableFont.
    2702               0 :   nsFont systemFont = *defaultVariableFont;
    2703               0 :   const nsCSSValue* systemFontValue = aRuleData->ValueForSystemFont();
    2704               0 :   if (eCSSUnit_Enumerated == systemFontValue->GetUnit()) {
    2705               0 :     gfxFontStyle fontStyle;
    2706                 :     LookAndFeel::FontID fontID =
    2707               0 :       (LookAndFeel::FontID)systemFontValue->GetIntValue();
    2708               0 :     if (LookAndFeel::GetFont(fontID, systemFont.name, fontStyle)) {
    2709               0 :       systemFont.style = fontStyle.style;
    2710               0 :       systemFont.systemFont = fontStyle.systemFont;
    2711               0 :       systemFont.variant = NS_FONT_VARIANT_NORMAL;
    2712               0 :       systemFont.weight = fontStyle.weight;
    2713               0 :       systemFont.stretch = fontStyle.stretch;
    2714               0 :       systemFont.decorations = NS_FONT_DECORATION_NONE;
    2715                 :       systemFont.size = NSFloatPixelsToAppUnits(fontStyle.size,
    2716                 :                                                 aPresContext->DeviceContext()->
    2717               0 :                                                 UnscaledAppUnitsPerDevPixel());
    2718                 :       //systemFont.langGroup = fontStyle.langGroup;
    2719               0 :       systemFont.sizeAdjust = fontStyle.sizeAdjust;
    2720                 : 
    2721                 : #ifdef XP_WIN
    2722                 :       // XXXldb This platform-specific stuff should be in the
    2723                 :       // LookAndFeel implementation, not here.
    2724                 :       // XXXzw Should we even still *have* this code?  It looks to be making
    2725                 :       // old, probably obsolete assumptions.
    2726                 : 
    2727                 :       // As far as I can tell the system default fonts and sizes
    2728                 :       // on MS-Windows for Buttons, Listboxes/Comboxes and Text Fields are
    2729                 :       // all pre-determined and cannot be changed by either the control panel
    2730                 :       // or programmtically.
    2731                 :       switch (fontID) {
    2732                 :         // Fields (text fields)
    2733                 :         // Button and Selects (listboxes/comboboxes)
    2734                 :         //    We use whatever font is defined by the system. Which it appears
    2735                 :         //    (and the assumption is) it is always a proportional font. Then we
    2736                 :         //    always use 2 points smaller than what the browser has defined as
    2737                 :         //    the default proportional font.
    2738                 :       case LookAndFeel::eFont_Field:
    2739                 :       case LookAndFeel::eFont_Button:
    2740                 :       case LookAndFeel::eFont_List:
    2741                 :         // Assumption: system defined font is proportional
    2742                 :         systemFont.size =
    2743                 :           NS_MAX(defaultVariableFont->size -
    2744                 :                  nsPresContext::CSSPointsToAppUnits(2), 0);
    2745                 :         break;
    2746                 :       }
    2747                 : #endif
    2748                 :     }
    2749                 :   }
    2750                 : 
    2751                 :   // font-family: string list, enum, inherit
    2752               0 :   const nsCSSValue* familyValue = aRuleData->ValueForFontFamily();
    2753               0 :   NS_ASSERTION(eCSSUnit_Enumerated != familyValue->GetUnit(),
    2754                 :                "system fonts should not be in mFamily anymore");
    2755               0 :   if (eCSSUnit_Families == familyValue->GetUnit()) {
    2756                 :     // set the correct font if we are using DocumentFonts OR we are overriding for XUL
    2757                 :     // MJA: bug 31816
    2758               0 :     if (aGenericFontID == kGenericFont_NONE) {
    2759                 :       // only bother appending fallback fonts if this isn't a fallback generic font itself
    2760               0 :       if (!aFont->mFont.name.IsEmpty())
    2761               0 :         aFont->mFont.name.Append((PRUnichar)',');
    2762                 :       // defaultVariableFont.name should always be "serif" or "sans-serif".
    2763               0 :       aFont->mFont.name.Append(defaultVariableFont->name);
    2764                 :     }
    2765               0 :     aFont->mFont.systemFont = false;
    2766                 :     // Technically this is redundant with the code below, but it's good
    2767                 :     // to have since we'll still want it once we get rid of
    2768                 :     // SetGenericFont (bug 380915).
    2769               0 :     aFont->mGenericID = aGenericFontID;
    2770                 :   }
    2771               0 :   else if (eCSSUnit_System_Font == familyValue->GetUnit()) {
    2772               0 :     aFont->mFont.name = systemFont.name;
    2773               0 :     aFont->mFont.systemFont = true;
    2774               0 :     aFont->mGenericID = kGenericFont_NONE;
    2775                 :   }
    2776               0 :   else if (eCSSUnit_Inherit == familyValue->GetUnit()) {
    2777               0 :     aCanStoreInRuleTree = false;
    2778               0 :     aFont->mFont.name = aParentFont->mFont.name;
    2779               0 :     aFont->mFont.systemFont = aParentFont->mFont.systemFont;
    2780               0 :     aFont->mGenericID = aParentFont->mGenericID;
    2781                 :   }
    2782               0 :   else if (eCSSUnit_Initial == familyValue->GetUnit()) {
    2783               0 :     aFont->mFont.name = defaultVariableFont->name;
    2784               0 :     aFont->mFont.systemFont = defaultVariableFont->systemFont;
    2785               0 :     aFont->mGenericID = kGenericFont_NONE;
    2786                 :   }
    2787                 : 
    2788                 :   // When we're in the loop in SetGenericFont, we must ensure that we
    2789                 :   // always keep aFont->mFlags set to the correct generic.  But we have
    2790                 :   // to be careful not to touch it when we're called directly from
    2791                 :   // ComputeFontData, because we could have a start struct.
    2792               0 :   if (aGenericFontID != kGenericFont_NONE) {
    2793               0 :     aFont->mGenericID = aGenericFontID;
    2794                 :   }
    2795                 : 
    2796                 :   // font-style: enum, inherit, initial, -moz-system-font
    2797               0 :   SetDiscrete(*aRuleData->ValueForFontStyle(),
    2798                 :               aFont->mFont.style, aCanStoreInRuleTree,
    2799                 :               SETDSC_ENUMERATED | SETDSC_SYSTEM_FONT,
    2800                 :               aParentFont->mFont.style,
    2801                 :               defaultVariableFont->style,
    2802               0 :               0, 0, 0, systemFont.style);
    2803                 : 
    2804                 :   // font-variant: enum, inherit, initial, -moz-system-font
    2805               0 :   SetDiscrete(*aRuleData->ValueForFontVariant(),
    2806                 :               aFont->mFont.variant, aCanStoreInRuleTree,
    2807                 :               SETDSC_ENUMERATED | SETDSC_SYSTEM_FONT,
    2808                 :               aParentFont->mFont.variant,
    2809                 :               defaultVariableFont->variant,
    2810               0 :               0, 0, 0, systemFont.variant);
    2811                 : 
    2812                 :   // font-weight: int, enum, inherit, initial, -moz-system-font
    2813                 :   // special handling for enum
    2814               0 :   const nsCSSValue* weightValue = aRuleData->ValueForFontWeight();
    2815               0 :   if (eCSSUnit_Enumerated == weightValue->GetUnit()) {
    2816               0 :     PRInt32 value = weightValue->GetIntValue();
    2817               0 :     switch (value) {
    2818                 :       case NS_STYLE_FONT_WEIGHT_NORMAL:
    2819                 :       case NS_STYLE_FONT_WEIGHT_BOLD:
    2820               0 :         aFont->mFont.weight = value;
    2821               0 :         break;
    2822                 :       case NS_STYLE_FONT_WEIGHT_BOLDER: {
    2823               0 :         aCanStoreInRuleTree = false;
    2824               0 :         PRInt32 inheritedValue = aParentFont->mFont.weight;
    2825               0 :         if (inheritedValue <= 300) {
    2826               0 :           aFont->mFont.weight = 400;
    2827               0 :         } else if (inheritedValue <= 500) {
    2828               0 :           aFont->mFont.weight = 700;
    2829                 :         } else {
    2830               0 :           aFont->mFont.weight = 900;
    2831                 :         }
    2832               0 :         break;
    2833                 :       }
    2834                 :       case NS_STYLE_FONT_WEIGHT_LIGHTER: {
    2835               0 :         aCanStoreInRuleTree = false;
    2836               0 :         PRInt32 inheritedValue = aParentFont->mFont.weight;
    2837               0 :         if (inheritedValue < 600) {
    2838               0 :           aFont->mFont.weight = 100;
    2839               0 :         } else if (inheritedValue < 800) {
    2840               0 :           aFont->mFont.weight = 400;
    2841                 :         } else {
    2842               0 :           aFont->mFont.weight = 700;
    2843                 :         }
    2844               0 :         break;
    2845                 :       }
    2846                 :     }
    2847                 :   } else
    2848                 :     SetDiscrete(*weightValue, aFont->mFont.weight, aCanStoreInRuleTree,
    2849                 :                 SETDSC_INTEGER | SETDSC_SYSTEM_FONT,
    2850                 :                 aParentFont->mFont.weight,
    2851                 :                 defaultVariableFont->weight,
    2852               0 :                 0, 0, 0, systemFont.weight);
    2853                 : 
    2854                 :   // font-stretch: enum, inherit, initial, -moz-system-font
    2855               0 :   SetDiscrete(*aRuleData->ValueForFontStretch(),
    2856                 :               aFont->mFont.stretch, aCanStoreInRuleTree,
    2857                 :               SETDSC_SYSTEM_FONT | SETDSC_ENUMERATED,
    2858                 :               aParentFont->mFont.stretch,
    2859                 :               defaultVariableFont->stretch,
    2860               0 :               0, 0, 0, systemFont.stretch);
    2861                 : 
    2862                 :   // Compute scriptlevel, scriptminsize and scriptsizemultiplier now so
    2863                 :   // they're available for font-size computation.
    2864                 : 
    2865                 :   // -moz-script-min-size: length
    2866               0 :   const nsCSSValue* scriptMinSizeValue = aRuleData->ValueForScriptMinSize();
    2867               0 :   if (scriptMinSizeValue->IsLengthUnit()) {
    2868                 :     // scriptminsize in font units (em, ex) has to be interpreted relative
    2869                 :     // to the parent font, or the size definitions are circular and we
    2870                 :     //
    2871                 :     aFont->mScriptMinSize =
    2872                 :       CalcLengthWith(*scriptMinSizeValue, aParentFont->mSize,
    2873                 :                      aParentFont,
    2874                 :                      nsnull, aPresContext, atRoot, true,
    2875               0 :                      aCanStoreInRuleTree);
    2876                 :   }
    2877                 : 
    2878                 :   // -moz-script-size-multiplier: factor, inherit, initial
    2879               0 :   SetFactor(*aRuleData->ValueForScriptSizeMultiplier(),
    2880                 :             aFont->mScriptSizeMultiplier,
    2881                 :             aCanStoreInRuleTree, aParentFont->mScriptSizeMultiplier,
    2882                 :             NS_MATHML_DEFAULT_SCRIPT_SIZE_MULTIPLIER,
    2883               0 :             SETFCT_POSITIVE);
    2884                 : 
    2885                 :   // -moz-script-level: integer, number, inherit
    2886               0 :   const nsCSSValue* scriptLevelValue = aRuleData->ValueForScriptLevel();
    2887               0 :   if (eCSSUnit_Integer == scriptLevelValue->GetUnit()) {
    2888                 :     // "relative"
    2889               0 :     aFont->mScriptLevel = ClampTo8Bit(aParentFont->mScriptLevel + scriptLevelValue->GetIntValue());
    2890                 :   }
    2891               0 :   else if (eCSSUnit_Number == scriptLevelValue->GetUnit()) {
    2892                 :     // "absolute"
    2893               0 :     aFont->mScriptLevel = ClampTo8Bit(PRInt32(scriptLevelValue->GetFloatValue()));
    2894                 :   }
    2895               0 :   else if (eCSSUnit_Inherit == scriptLevelValue->GetUnit()) {
    2896               0 :     aCanStoreInRuleTree = false;
    2897               0 :     aFont->mScriptLevel = aParentFont->mScriptLevel;
    2898                 :   }
    2899               0 :   else if (eCSSUnit_Initial == scriptLevelValue->GetUnit()) {
    2900               0 :     aFont->mScriptLevel = 0;
    2901                 :   }
    2902                 : 
    2903                 :   // font-feature-settings
    2904                 :   const nsCSSValue* featureSettingsValue =
    2905               0 :     aRuleData->ValueForFontFeatureSettings();
    2906               0 :   if (eCSSUnit_Inherit == featureSettingsValue->GetUnit()) {
    2907               0 :     aCanStoreInRuleTree = false;
    2908               0 :     aFont->mFont.featureSettings = aParentFont->mFont.featureSettings;
    2909               0 :   } else if (eCSSUnit_Normal == featureSettingsValue->GetUnit() ||
    2910               0 :              eCSSUnit_Initial == featureSettingsValue->GetUnit()) {
    2911               0 :     aFont->mFont.featureSettings.Truncate();
    2912               0 :   } else if (eCSSUnit_System_Font == featureSettingsValue->GetUnit()) {
    2913               0 :     aFont->mFont.featureSettings = systemFont.featureSettings;
    2914               0 :   } else if (eCSSUnit_String == featureSettingsValue->GetUnit()) {
    2915               0 :     featureSettingsValue->GetStringValue(aFont->mFont.featureSettings);
    2916                 :   }
    2917                 : 
    2918                 :   // font-language-override
    2919                 :   const nsCSSValue* languageOverrideValue =
    2920               0 :     aRuleData->ValueForFontLanguageOverride();
    2921               0 :   if (eCSSUnit_Inherit == languageOverrideValue->GetUnit()) {
    2922               0 :     aCanStoreInRuleTree = false;
    2923               0 :     aFont->mFont.languageOverride = aParentFont->mFont.languageOverride;
    2924               0 :   } else if (eCSSUnit_Normal == languageOverrideValue->GetUnit() ||
    2925               0 :              eCSSUnit_Initial == languageOverrideValue->GetUnit()) {
    2926               0 :     aFont->mFont.languageOverride.Truncate();
    2927               0 :   } else if (eCSSUnit_System_Font == languageOverrideValue->GetUnit()) {
    2928               0 :     aFont->mFont.languageOverride = systemFont.languageOverride;
    2929               0 :   } else if (eCSSUnit_String == languageOverrideValue->GetUnit()) {
    2930               0 :     languageOverrideValue->GetStringValue(aFont->mFont.languageOverride);
    2931                 :   }
    2932                 : 
    2933                 :   // font-size: enum, length, percent, inherit
    2934               0 :   nscoord scriptLevelAdjustedParentSize = aParentFont->mSize;
    2935                 :   nscoord scriptLevelAdjustedUnconstrainedParentSize;
    2936                 :   scriptLevelAdjustedParentSize =
    2937                 :     ComputeScriptLevelSize(aFont, aParentFont, aPresContext,
    2938               0 :                            &scriptLevelAdjustedUnconstrainedParentSize);
    2939               0 :   NS_ASSERTION(!aUsedStartStruct || aFont->mScriptUnconstrainedSize == aFont->mSize,
    2940                 :                "If we have a start struct, we should have reset everything coming in here");
    2941                 :   SetFontSize(aPresContext, aRuleData, aFont, aParentFont,
    2942                 :               &aFont->mSize,
    2943                 :               systemFont, aParentFont->mSize, scriptLevelAdjustedParentSize,
    2944               0 :               aUsedStartStruct, atRoot, aCanStoreInRuleTree);
    2945               0 :   if (aParentFont->mSize == aParentFont->mScriptUnconstrainedSize &&
    2946                 :       scriptLevelAdjustedParentSize == scriptLevelAdjustedUnconstrainedParentSize) {
    2947                 :     // Fast path: we have not been affected by scriptminsize so we don't
    2948                 :     // need to call SetFontSize again to compute the
    2949                 :     // scriptminsize-unconstrained size. This is OK even if we have a
    2950                 :     // start struct, because if we have a start struct then 'font-size'
    2951                 :     // was specified and so scriptminsize has no effect.
    2952               0 :     aFont->mScriptUnconstrainedSize = aFont->mSize;
    2953                 :   } else {
    2954                 :     SetFontSize(aPresContext, aRuleData, aFont, aParentFont,
    2955                 :                 &aFont->mScriptUnconstrainedSize,
    2956                 :                 systemFont, aParentFont->mScriptUnconstrainedSize,
    2957                 :                 scriptLevelAdjustedUnconstrainedParentSize,
    2958               0 :                 aUsedStartStruct, atRoot, aCanStoreInRuleTree);
    2959                 :   }
    2960               0 :   NS_ASSERTION(aFont->mScriptUnconstrainedSize <= aFont->mSize,
    2961                 :                "scriptminsize should never be making things bigger");
    2962                 : 
    2963               0 :   nscoord fontSize = aFont->mSize;
    2964                 : 
    2965                 :   // enforce the user' specified minimum font-size on the value that we expose
    2966                 :   // (but don't change font-size:0, since that would unhide hidden text)
    2967               0 :   if (fontSize > 0) {
    2968               0 :     nscoord minFontSize = aPresContext->MinFontSize(aFont->mLanguage);
    2969               0 :     if (minFontSize < 0) {
    2970               0 :       minFontSize = 0;
    2971                 :     }
    2972               0 :     if (fontSize < minFontSize && !aPresContext->IsChrome()) {
    2973                 :       // override the minimum font-size constraint
    2974               0 :       fontSize = minFontSize;
    2975                 :     }
    2976                 :   }
    2977               0 :   aFont->mFont.size = fontSize;
    2978                 : 
    2979                 :   // font-size-adjust: number, none, inherit, initial, -moz-system-font
    2980               0 :   const nsCSSValue* sizeAdjustValue = aRuleData->ValueForFontSizeAdjust();
    2981               0 :   if (eCSSUnit_System_Font == sizeAdjustValue->GetUnit()) {
    2982               0 :     aFont->mFont.sizeAdjust = systemFont.sizeAdjust;
    2983                 :   } else
    2984                 :     SetFactor(*sizeAdjustValue, aFont->mFont.sizeAdjust,
    2985                 :               aCanStoreInRuleTree, aParentFont->mFont.sizeAdjust, 0.0f,
    2986               0 :               SETFCT_NONE);
    2987               0 : }
    2988                 : 
    2989                 : // This should die (bug 380915).
    2990                 : //
    2991                 : // SetGenericFont:
    2992                 : //  - backtrack to an ancestor with the same generic font name (possibly
    2993                 : //    up to the root where default values come from the presentation context)
    2994                 : //  - re-apply cascading rules from there without caching intermediate values
    2995                 : /* static */ void
    2996               0 : nsRuleNode::SetGenericFont(nsPresContext* aPresContext,
    2997                 :                            nsStyleContext* aContext,
    2998                 :                            PRUint8 aGenericFontID,
    2999                 :                            nsStyleFont* aFont)
    3000                 : {
    3001                 :   // walk up the contexts until a context with the desired generic font
    3002               0 :   nsAutoTArray<nsStyleContext*, 8> contextPath;
    3003               0 :   contextPath.AppendElement(aContext);
    3004               0 :   nsStyleContext* higherContext = aContext->GetParent();
    3005               0 :   while (higherContext) {
    3006               0 :     if (higherContext->GetStyleFont()->mGenericID == aGenericFontID) {
    3007                 :       // done walking up the higher contexts
    3008               0 :       break;
    3009                 :     }
    3010               0 :     contextPath.AppendElement(higherContext);
    3011               0 :     higherContext = higherContext->GetParent();
    3012                 :   }
    3013                 : 
    3014                 :   // re-apply the cascading rules, starting from the higher context
    3015                 : 
    3016                 :   // If we stopped earlier because we reached the root of the style tree,
    3017                 :   // we will start with the default generic font from the presentation
    3018                 :   // context. Otherwise we start with the higher context.
    3019                 :   const nsFont* defaultFont =
    3020               0 :     aPresContext->GetDefaultFont(aGenericFontID, aFont->mLanguage);
    3021               0 :   nsStyleFont parentFont(*defaultFont, aPresContext);
    3022               0 :   if (higherContext) {
    3023               0 :     const nsStyleFont* tmpFont = higherContext->GetStyleFont();
    3024               0 :     parentFont = *tmpFont;
    3025                 :   }
    3026               0 :   *aFont = parentFont;
    3027                 : 
    3028                 :   bool dummy;
    3029               0 :   PRUint32 fontBit = nsCachedStyleData::GetBitForSID(eStyleStruct_Font);
    3030                 : 
    3031                 :   // use placement new[] on the result of alloca() to allocate a
    3032                 :   // variable-sized stack array, including execution of constructors,
    3033                 :   // and use an RAII class to run the destructors too.
    3034               0 :   size_t nprops = nsCSSProps::PropertyCountInStruct(eStyleStruct_Font);
    3035               0 :   void* dataStorage = alloca(nprops * sizeof(nsCSSValue));
    3036                 : 
    3037               0 :   for (PRInt32 i = contextPath.Length() - 1; i >= 0; --i) {
    3038               0 :     nsStyleContext* context = contextPath[i];
    3039               0 :     AutoCSSValueArray dataArray(dataStorage, nprops);
    3040                 : 
    3041                 :     nsRuleData ruleData(NS_STYLE_INHERIT_BIT(Font), dataArray.get(),
    3042               0 :                         aPresContext, context);
    3043               0 :     ruleData.mValueOffsets[eStyleStruct_Font] = 0;
    3044                 : 
    3045                 :     // Trimmed down version of ::WalkRuleTree() to re-apply the style rules
    3046                 :     // Note that we *do* need to do this for our own data, since what is
    3047                 :     // in |fontData| in ComputeFontData is only for the rules below
    3048                 :     // aStartStruct.
    3049               0 :     for (nsRuleNode* ruleNode = context->GetRuleNode(); ruleNode;
    3050                 :          ruleNode = ruleNode->GetParent()) {
    3051               0 :       if (ruleNode->mNoneBits & fontBit)
    3052                 :         // no more font rules on this branch, get out
    3053               0 :         break;
    3054                 : 
    3055               0 :       nsIStyleRule *rule = ruleNode->GetRule();
    3056               0 :       if (rule) {
    3057               0 :         ruleData.mLevel = ruleNode->GetLevel();
    3058               0 :         ruleData.mIsImportantRule = ruleNode->IsImportantRule();
    3059               0 :         rule->MapRuleInfoInto(&ruleData);
    3060                 :       }
    3061                 :     }
    3062                 : 
    3063                 :     // Compute the delta from the information that the rules specified
    3064                 : 
    3065                 :     // Avoid unnecessary operations in SetFont().  But we care if it's
    3066                 :     // the final value that we're computing.
    3067               0 :     if (i != 0)
    3068               0 :       ruleData.ValueForFontFamily()->Reset();
    3069                 : 
    3070                 :     nsRuleNode::SetFont(aPresContext, context,
    3071                 :                         aGenericFontID, &ruleData, &parentFont, aFont,
    3072               0 :                         false, dummy);
    3073                 : 
    3074                 :     // XXX Not sure if we need to do this here
    3075                 :     // If we have a post-resolve callback, handle that now.
    3076               0 :     if (ruleData.mPostResolveCallback)
    3077               0 :       (ruleData.mPostResolveCallback)(aFont, &ruleData);
    3078                 : 
    3079               0 :     parentFont = *aFont;
    3080                 :   }
    3081               0 : }
    3082                 : 
    3083               0 : static bool ExtractGeneric(const nsString& aFamily, bool aGeneric,
    3084                 :                              void *aData)
    3085                 : {
    3086               0 :   nsAutoString *data = static_cast<nsAutoString*>(aData);
    3087                 : 
    3088               0 :   if (aGeneric) {
    3089               0 :     *data = aFamily;
    3090               0 :     return false; // stop enumeration
    3091                 :   }
    3092               0 :   return true;
    3093                 : }
    3094                 : 
    3095                 : const void*
    3096               0 : nsRuleNode::ComputeFontData(void* aStartStruct,
    3097                 :                             const nsRuleData* aRuleData,
    3098                 :                             nsStyleContext* aContext,
    3099                 :                             nsRuleNode* aHighestNode,
    3100                 :                             const RuleDetail aRuleDetail,
    3101                 :                             const bool aCanStoreInRuleTree)
    3102                 : {
    3103               0 :   COMPUTE_START_INHERITED(Font, (mPresContext), font, parentFont)
    3104                 : 
    3105                 :   // NOTE:  The |aRuleDetail| passed in is a little bit conservative due
    3106                 :   // to the -moz-system-font property.  We really don't need to consider
    3107                 :   // it here in determining whether to cache in the rule tree.  However,
    3108                 :   // we do need to consider it in WalkRuleTree when deciding whether to
    3109                 :   // walk further up the tree.  So this means that when the font struct
    3110                 :   // is fully specified using *longhand* properties (excluding
    3111                 :   // -moz-system-font), we won't cache in the rule tree even though we
    3112                 :   // could.  However, it's pretty unlikely authors will do that
    3113                 :   // (although there is a pretty good chance they'll fully specify it
    3114                 :   // using the 'font' shorthand).
    3115                 : 
    3116                 :   bool useDocumentFonts =
    3117               0 :     mPresContext->GetCachedBoolPref(kPresContext_UseDocumentFonts);
    3118                 : 
    3119                 :   // See if we are in the chrome
    3120                 :   // We only need to know this to determine if we have to use the
    3121                 :   // document fonts (overriding the useDocumentFonts flag).
    3122               0 :   if (!useDocumentFonts && mPresContext->IsChrome()) {
    3123                 :     // if we are not using document fonts, but this is a XUL document,
    3124                 :     // then we use the document fonts anyway
    3125               0 :     useDocumentFonts = true;
    3126                 :   }
    3127                 : 
    3128                 :   // Figure out if we are a generic font
    3129               0 :   PRUint8 generic = kGenericFont_NONE;
    3130                 :   // XXXldb What if we would have had a string if we hadn't been doing
    3131                 :   // the optimization with a non-null aStartStruct?
    3132               0 :   const nsCSSValue* familyValue = aRuleData->ValueForFontFamily();
    3133               0 :   if (eCSSUnit_Families == familyValue->GetUnit()) {
    3134               0 :     familyValue->GetStringValue(font->mFont.name);
    3135                 :     // XXXldb Do we want to extract the generic for this if it's not only a
    3136                 :     // generic?
    3137               0 :     nsFont::GetGenericID(font->mFont.name, &generic);
    3138                 : 
    3139                 :     // If we aren't allowed to use document fonts, then we are only entitled
    3140                 :     // to use the user's default variable-width font and fixed-width font
    3141               0 :     if (!useDocumentFonts) {
    3142                 :       // Extract the generic from the specified font family...
    3143               0 :       nsAutoString genericName;
    3144               0 :       if (!font->mFont.EnumerateFamilies(ExtractGeneric, &genericName)) {
    3145                 :         // The specified font had a generic family.
    3146               0 :         font->mFont.name = genericName;
    3147               0 :         nsFont::GetGenericID(genericName, &generic);
    3148                 : 
    3149                 :         // ... and only use it if it's -moz-fixed or monospace
    3150               0 :         if (generic != kGenericFont_moz_fixed &&
    3151                 :             generic != kGenericFont_monospace) {
    3152               0 :           font->mFont.name.Truncate();
    3153               0 :           generic = kGenericFont_NONE;
    3154                 :         }
    3155                 :       } else {
    3156                 :         // The specified font did not have a generic family.
    3157               0 :         font->mFont.name.Truncate();
    3158               0 :         generic = kGenericFont_NONE;
    3159                 :       }
    3160                 :     }
    3161                 :   }
    3162                 : 
    3163                 :   // Now compute our font struct
    3164               0 :   if (generic == kGenericFont_NONE) {
    3165                 :     // continue the normal processing
    3166                 :     nsRuleNode::SetFont(mPresContext, aContext, generic,
    3167                 :                         aRuleData, parentFont, font,
    3168               0 :                         aStartStruct != nsnull, canStoreInRuleTree);
    3169                 :   }
    3170                 :   else {
    3171                 :     // re-calculate the font as a generic font
    3172               0 :     canStoreInRuleTree = false;
    3173                 :     nsRuleNode::SetGenericFont(mPresContext, aContext, generic,
    3174               0 :                                font);
    3175                 :   }
    3176                 : 
    3177               0 :   COMPUTE_END_INHERITED(Font, font)
    3178                 : }
    3179                 : 
    3180                 : template <typename T>
    3181               0 : inline PRUint32 ListLength(const T* aList)
    3182                 : {
    3183               0 :   PRUint32 len = 0;
    3184               0 :   while (aList) {
    3185               0 :     len++;
    3186               0 :     aList = aList->mNext;
    3187                 :   }
    3188               0 :   return len;
    3189                 : }
    3190                 : 
    3191                 : 
    3192                 : 
    3193                 : already_AddRefed<nsCSSShadowArray>
    3194               0 : nsRuleNode::GetShadowData(const nsCSSValueList* aList,
    3195                 :                           nsStyleContext* aContext,
    3196                 :                           bool aIsBoxShadow,
    3197                 :                           bool& canStoreInRuleTree)
    3198                 : {
    3199               0 :   PRUint32 arrayLength = ListLength(aList);
    3200                 : 
    3201               0 :   NS_ABORT_IF_FALSE(arrayLength > 0,
    3202                 :                     "Non-null text-shadow list, yet we counted 0 items.");
    3203               0 :   nsCSSShadowArray* shadowList = new(arrayLength) nsCSSShadowArray(arrayLength);
    3204                 : 
    3205               0 :   if (!shadowList)
    3206               0 :     return nsnull;
    3207                 : 
    3208               0 :   nsStyleCoord tempCoord;
    3209                 :   bool unitOK;
    3210               0 :   for (nsCSSShadowItem* item = shadowList->ShadowAt(0);
    3211                 :        aList;
    3212                 :        aList = aList->mNext, ++item) {
    3213               0 :     NS_ABORT_IF_FALSE(aList->mValue.GetUnit() == eCSSUnit_Array,
    3214                 :                       "expecting a plain array value");
    3215               0 :     nsCSSValue::Array *arr = aList->mValue.GetArrayValue();
    3216                 :     // OK to pass bad aParentCoord since we're not passing SETCOORD_INHERIT
    3217               0 :     unitOK = SetCoord(arr->Item(0), tempCoord, nsStyleCoord(),
    3218                 :                       SETCOORD_LENGTH | SETCOORD_CALC_LENGTH_ONLY,
    3219               0 :                       aContext, mPresContext, canStoreInRuleTree);
    3220               0 :     NS_ASSERTION(unitOK, "unexpected unit");
    3221               0 :     item->mXOffset = tempCoord.GetCoordValue();
    3222                 : 
    3223               0 :     unitOK = SetCoord(arr->Item(1), tempCoord, nsStyleCoord(),
    3224                 :                       SETCOORD_LENGTH | SETCOORD_CALC_LENGTH_ONLY,
    3225               0 :                       aContext, mPresContext, canStoreInRuleTree);
    3226               0 :     NS_ASSERTION(unitOK, "unexpected unit");
    3227               0 :     item->mYOffset = tempCoord.GetCoordValue();
    3228                 : 
    3229                 :     // Blur radius is optional in the current box-shadow spec
    3230               0 :     if (arr->Item(2).GetUnit() != eCSSUnit_Null) {
    3231               0 :       unitOK = SetCoord(arr->Item(2), tempCoord, nsStyleCoord(),
    3232                 :                         SETCOORD_LENGTH | SETCOORD_CALC_LENGTH_ONLY |
    3233                 :                           SETCOORD_CALC_CLAMP_NONNEGATIVE,
    3234               0 :                         aContext, mPresContext, canStoreInRuleTree);
    3235               0 :       NS_ASSERTION(unitOK, "unexpected unit");
    3236               0 :       item->mRadius = tempCoord.GetCoordValue();
    3237                 :     } else {
    3238               0 :       item->mRadius = 0;
    3239                 :     }
    3240                 : 
    3241                 :     // Find the spread radius
    3242               0 :     if (aIsBoxShadow && arr->Item(3).GetUnit() != eCSSUnit_Null) {
    3243               0 :       unitOK = SetCoord(arr->Item(3), tempCoord, nsStyleCoord(),
    3244                 :                         SETCOORD_LENGTH | SETCOORD_CALC_LENGTH_ONLY,
    3245               0 :                         aContext, mPresContext, canStoreInRuleTree);
    3246               0 :       NS_ASSERTION(unitOK, "unexpected unit");
    3247               0 :       item->mSpread = tempCoord.GetCoordValue();
    3248                 :     } else {
    3249               0 :       item->mSpread = 0;
    3250                 :     }
    3251                 : 
    3252               0 :     if (arr->Item(4).GetUnit() != eCSSUnit_Null) {
    3253               0 :       item->mHasColor = true;
    3254                 :       // 2nd argument can be bogus since inherit is not a valid color
    3255               0 :       unitOK = SetColor(arr->Item(4), 0, mPresContext, aContext, item->mColor,
    3256               0 :                         canStoreInRuleTree);
    3257               0 :       NS_ASSERTION(unitOK, "unexpected unit");
    3258                 :     }
    3259                 : 
    3260               0 :     if (aIsBoxShadow && arr->Item(5).GetUnit() == eCSSUnit_Enumerated) {
    3261               0 :       NS_ASSERTION(arr->Item(5).GetIntValue() == NS_STYLE_BOX_SHADOW_INSET,
    3262                 :                    "invalid keyword type for box shadow");
    3263               0 :       item->mInset = true;
    3264                 :     } else {
    3265               0 :       item->mInset = false;
    3266                 :     }
    3267                 :   }
    3268                 : 
    3269               0 :   NS_ADDREF(shadowList);
    3270               0 :   return shadowList;
    3271                 : }
    3272                 : 
    3273                 : const void*
    3274               0 : nsRuleNode::ComputeTextData(void* aStartStruct,
    3275                 :                             const nsRuleData* aRuleData,
    3276                 :                             nsStyleContext* aContext,
    3277                 :                             nsRuleNode* aHighestNode,
    3278                 :                             const RuleDetail aRuleDetail,
    3279                 :                             const bool aCanStoreInRuleTree)
    3280                 : {
    3281               0 :   COMPUTE_START_INHERITED(Text, (), text, parentText)
    3282                 : 
    3283                 :   // tab-size: integer, inherit
    3284               0 :   SetDiscrete(*aRuleData->ValueForTabSize(),
    3285                 :               text->mTabSize, canStoreInRuleTree,
    3286                 :               SETDSC_INTEGER, parentText->mTabSize,
    3287               0 :               NS_STYLE_TABSIZE_INITIAL, 0, 0, 0, 0);
    3288                 : 
    3289                 :   // letter-spacing: normal, length, inherit
    3290               0 :   SetCoord(*aRuleData->ValueForLetterSpacing(),
    3291                 :            text->mLetterSpacing, parentText->mLetterSpacing,
    3292                 :            SETCOORD_LH | SETCOORD_NORMAL | SETCOORD_INITIAL_NORMAL |
    3293                 :              SETCOORD_CALC_LENGTH_ONLY,
    3294               0 :            aContext, mPresContext, canStoreInRuleTree);
    3295                 : 
    3296                 :   // text-shadow: none, list, inherit, initial
    3297               0 :   const nsCSSValue* textShadowValue = aRuleData->ValueForTextShadow();
    3298               0 :   if (textShadowValue->GetUnit() != eCSSUnit_Null) {
    3299               0 :     text->mTextShadow = nsnull;
    3300                 : 
    3301                 :     // Don't need to handle none/initial explicitly: The above assignment
    3302                 :     // takes care of that
    3303               0 :     if (textShadowValue->GetUnit() == eCSSUnit_Inherit) {
    3304               0 :       canStoreInRuleTree = false;
    3305               0 :       text->mTextShadow = parentText->mTextShadow;
    3306               0 :     } else if (textShadowValue->GetUnit() == eCSSUnit_List ||
    3307               0 :                textShadowValue->GetUnit() == eCSSUnit_ListDep) {
    3308                 :       // List of arrays
    3309                 :       text->mTextShadow = GetShadowData(textShadowValue->GetListValue(),
    3310               0 :                                         aContext, false, canStoreInRuleTree);
    3311                 :     }
    3312                 :   }
    3313                 : 
    3314                 :   // line-height: normal, number, length, percent, inherit
    3315               0 :   const nsCSSValue* lineHeightValue = aRuleData->ValueForLineHeight();
    3316               0 :   if (eCSSUnit_Percent == lineHeightValue->GetUnit()) {
    3317               0 :     canStoreInRuleTree = false;
    3318                 :     // Use |mFont.size| to pick up minimum font size.
    3319                 :     text->mLineHeight.SetCoordValue(
    3320               0 :         nscoord(float(aContext->GetStyleFont()->mFont.size) *
    3321               0 :                 lineHeightValue->GetPercentValue()));
    3322                 :   }
    3323               0 :   else if (eCSSUnit_Initial == lineHeightValue->GetUnit() ||
    3324               0 :            eCSSUnit_System_Font == lineHeightValue->GetUnit()) {
    3325               0 :     text->mLineHeight.SetNormalValue();
    3326                 :   }
    3327                 :   else {
    3328                 :     SetCoord(*lineHeightValue, text->mLineHeight, parentText->mLineHeight,
    3329                 :              SETCOORD_LEH | SETCOORD_FACTOR | SETCOORD_NORMAL,
    3330               0 :              aContext, mPresContext, canStoreInRuleTree);
    3331               0 :     if (lineHeightValue->IsLengthUnit() &&
    3332               0 :         !lineHeightValue->IsRelativeLengthUnit()) {
    3333                 :       nscoord lh = nsStyleFont::ZoomText(mPresContext,
    3334               0 :                                          text->mLineHeight.GetCoordValue());
    3335                 : 
    3336               0 :       canStoreInRuleTree = false;
    3337               0 :       const nsStyleFont *font = aContext->GetStyleFont();
    3338               0 :       nscoord minimumFontSize = mPresContext->MinFontSize(font->mLanguage);
    3339                 : 
    3340               0 :       if (minimumFontSize > 0 && !mPresContext->IsChrome()) {
    3341               0 :         if (font->mSize != 0) {
    3342               0 :           lh = nscoord(float(lh) * float(font->mFont.size) / float(font->mSize));
    3343                 :         } else {
    3344               0 :           lh = minimumFontSize;
    3345                 :         }
    3346                 :       }
    3347               0 :       text->mLineHeight.SetCoordValue(lh);
    3348                 :     }
    3349                 :   }
    3350                 : 
    3351                 : 
    3352                 :   // text-align: enum, string, inherit, initial
    3353               0 :   const nsCSSValue* textAlignValue = aRuleData->ValueForTextAlign();
    3354               0 :   if (eCSSUnit_String == textAlignValue->GetUnit()) {
    3355               0 :     NS_NOTYETIMPLEMENTED("align string");
    3356               0 :   } else if (eCSSUnit_Enumerated == textAlignValue->GetUnit() &&
    3357                 :              NS_STYLE_TEXT_ALIGN_MOZ_CENTER_OR_INHERIT ==
    3358               0 :                textAlignValue->GetIntValue()) {
    3359               0 :     canStoreInRuleTree = false;
    3360               0 :     PRUint8 parentAlign = parentText->mTextAlign;
    3361                 :     text->mTextAlign = (NS_STYLE_TEXT_ALIGN_DEFAULT == parentAlign) ?
    3362               0 :       NS_STYLE_TEXT_ALIGN_CENTER : parentAlign;
    3363                 :   } else
    3364                 :     SetDiscrete(*textAlignValue, text->mTextAlign, canStoreInRuleTree,
    3365                 :                 SETDSC_ENUMERATED, parentText->mTextAlign,
    3366                 :                 NS_STYLE_TEXT_ALIGN_DEFAULT,
    3367               0 :                 0, 0, 0, 0);
    3368                 : 
    3369                 :   // text-align-last: enum, inherit, initial
    3370               0 :   SetDiscrete(*aRuleData->ValueForTextAlignLast(), text->mTextAlignLast,
    3371                 :               canStoreInRuleTree, SETDSC_ENUMERATED, parentText->mTextAlignLast,
    3372               0 :               NS_STYLE_TEXT_ALIGN_AUTO, 0, 0, 0, 0);
    3373                 : 
    3374                 :   // text-indent: length, percent, calc, inherit, initial
    3375               0 :   SetCoord(*aRuleData->ValueForTextIndent(), text->mTextIndent, parentText->mTextIndent,
    3376                 :            SETCOORD_LPH | SETCOORD_INITIAL_ZERO | SETCOORD_STORE_CALC,
    3377               0 :            aContext, mPresContext, canStoreInRuleTree);
    3378                 : 
    3379                 :   // text-transform: enum, inherit, initial
    3380               0 :   SetDiscrete(*aRuleData->ValueForTextTransform(), text->mTextTransform, canStoreInRuleTree,
    3381                 :               SETDSC_ENUMERATED, parentText->mTextTransform,
    3382               0 :               NS_STYLE_TEXT_TRANSFORM_NONE, 0, 0, 0, 0);
    3383                 : 
    3384                 :   // white-space: enum, inherit, initial
    3385               0 :   SetDiscrete(*aRuleData->ValueForWhiteSpace(), text->mWhiteSpace, canStoreInRuleTree,
    3386                 :               SETDSC_ENUMERATED, parentText->mWhiteSpace,
    3387               0 :               NS_STYLE_WHITESPACE_NORMAL, 0, 0, 0, 0);
    3388                 : 
    3389                 :   // word-spacing: normal, length, inherit
    3390               0 :   nsStyleCoord tempCoord;
    3391               0 :   const nsCSSValue* wordSpacingValue = aRuleData->ValueForWordSpacing();
    3392               0 :   if (SetCoord(*wordSpacingValue, tempCoord,
    3393                 :                nsStyleCoord(parentText->mWordSpacing,
    3394                 :                             nsStyleCoord::CoordConstructor),
    3395                 :                SETCOORD_LH | SETCOORD_NORMAL | SETCOORD_INITIAL_NORMAL |
    3396                 :                  SETCOORD_CALC_LENGTH_ONLY,
    3397               0 :                aContext, mPresContext, canStoreInRuleTree)) {
    3398               0 :     if (tempCoord.GetUnit() == eStyleUnit_Coord) {
    3399               0 :       text->mWordSpacing = tempCoord.GetCoordValue();
    3400               0 :     } else if (tempCoord.GetUnit() == eStyleUnit_Normal) {
    3401               0 :       text->mWordSpacing = 0;
    3402                 :     } else {
    3403               0 :       NS_NOTREACHED("unexpected unit");
    3404                 :     }
    3405                 :   } else {
    3406               0 :     NS_ASSERTION(wordSpacingValue->GetUnit() == eCSSUnit_Null,
    3407                 :                  "unexpected unit");
    3408                 :   }
    3409                 : 
    3410                 :   // word-wrap: enum, inherit, initial
    3411               0 :   SetDiscrete(*aRuleData->ValueForWordWrap(), text->mWordWrap, canStoreInRuleTree,
    3412                 :               SETDSC_ENUMERATED, parentText->mWordWrap,
    3413               0 :               NS_STYLE_WORDWRAP_NORMAL, 0, 0, 0, 0);
    3414                 : 
    3415                 :   // hyphens: enum, inherit, initial
    3416               0 :   SetDiscrete(*aRuleData->ValueForHyphens(), text->mHyphens, canStoreInRuleTree,
    3417                 :               SETDSC_ENUMERATED, parentText->mHyphens,
    3418               0 :               NS_STYLE_HYPHENS_MANUAL, 0, 0, 0, 0);
    3419                 : 
    3420                 :   // text-size-adjust: none, auto, inherit, initial
    3421               0 :   SetDiscrete(*aRuleData->ValueForTextSizeAdjust(), text->mTextSizeAdjust,
    3422                 :               canStoreInRuleTree, SETDSC_NONE | SETDSC_AUTO,
    3423                 :               parentText->mTextSizeAdjust,
    3424                 :               NS_STYLE_TEXT_SIZE_ADJUST_AUTO, // initial value
    3425                 :               NS_STYLE_TEXT_SIZE_ADJUST_AUTO, // auto value
    3426                 :               NS_STYLE_TEXT_SIZE_ADJUST_NONE, // none value
    3427               0 :               0, 0);
    3428                 : 
    3429               0 :   COMPUTE_END_INHERITED(Text, text)
    3430                 : }
    3431                 : 
    3432                 : const void*
    3433               0 : nsRuleNode::ComputeTextResetData(void* aStartStruct,
    3434                 :                                  const nsRuleData* aRuleData,
    3435                 :                                  nsStyleContext* aContext,
    3436                 :                                  nsRuleNode* aHighestNode,
    3437                 :                                  const RuleDetail aRuleDetail,
    3438                 :                                  const bool aCanStoreInRuleTree)
    3439                 : {
    3440               0 :   COMPUTE_START_RESET(TextReset, (), text, parentText)
    3441                 : 
    3442                 :   // vertical-align: enum, length, percent, calc, inherit
    3443               0 :   const nsCSSValue* verticalAlignValue = aRuleData->ValueForVerticalAlign();
    3444               0 :   if (!SetCoord(*verticalAlignValue, text->mVerticalAlign,
    3445                 :                 parentText->mVerticalAlign,
    3446                 :                 SETCOORD_LPH | SETCOORD_ENUMERATED | SETCOORD_STORE_CALC,
    3447               0 :                 aContext, mPresContext, canStoreInRuleTree)) {
    3448               0 :     if (eCSSUnit_Initial == verticalAlignValue->GetUnit()) {
    3449                 :       text->mVerticalAlign.SetIntValue(NS_STYLE_VERTICAL_ALIGN_BASELINE,
    3450               0 :                                        eStyleUnit_Enumerated);
    3451                 :     }
    3452                 :   }
    3453                 : 
    3454                 :   // text-blink: enum, inherit, initial
    3455               0 :   SetDiscrete(*aRuleData->ValueForTextBlink(), text->mTextBlink,
    3456                 :               canStoreInRuleTree, SETDSC_ENUMERATED, parentText->mTextBlink,
    3457               0 :               NS_STYLE_TEXT_BLINK_NONE, 0, 0, 0, 0);
    3458                 : 
    3459                 :   // text-decoration-line: enum (bit field), inherit, initial
    3460                 :   const nsCSSValue* decorationLineValue =
    3461               0 :     aRuleData->ValueForTextDecorationLine();
    3462               0 :   if (eCSSUnit_Enumerated == decorationLineValue->GetUnit()) {
    3463               0 :     PRInt32 td = decorationLineValue->GetIntValue();
    3464               0 :     text->mTextDecorationLine = td;
    3465               0 :     if (td & NS_STYLE_TEXT_DECORATION_LINE_PREF_ANCHORS) {
    3466                 :       bool underlineLinks =
    3467               0 :         mPresContext->GetCachedBoolPref(kPresContext_UnderlineLinks);
    3468               0 :       if (underlineLinks) {
    3469               0 :         text->mTextDecorationLine |= NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE;
    3470                 :       }
    3471                 :       else {
    3472               0 :         text->mTextDecorationLine &= ~NS_STYLE_TEXT_DECORATION_LINE_UNDERLINE;
    3473                 :       }
    3474                 :     }
    3475               0 :   } else if (eCSSUnit_Inherit == decorationLineValue->GetUnit()) {
    3476               0 :     canStoreInRuleTree = false;
    3477               0 :     text->mTextDecorationLine = parentText->mTextDecorationLine;
    3478               0 :   } else if (eCSSUnit_Initial == decorationLineValue->GetUnit()) {
    3479               0 :     text->mTextDecorationLine = NS_STYLE_TEXT_DECORATION_LINE_NONE;
    3480                 :   }
    3481                 : 
    3482                 :   // text-decoration-color: color, string, enum, inherit, initial
    3483                 :   const nsCSSValue* decorationColorValue =
    3484               0 :     aRuleData->ValueForTextDecorationColor();
    3485                 :   nscolor decorationColor;
    3486               0 :   if (eCSSUnit_Inherit == decorationColorValue->GetUnit()) {
    3487               0 :     canStoreInRuleTree = false;
    3488               0 :     if (parentContext) {
    3489                 :       bool isForeground;
    3490               0 :       parentText->GetDecorationColor(decorationColor, isForeground);
    3491               0 :       if (isForeground) {
    3492               0 :         text->SetDecorationColor(parentContext->GetStyleColor()->mColor);
    3493                 :       } else {
    3494               0 :         text->SetDecorationColor(decorationColor);
    3495                 :       }
    3496                 :     } else {
    3497               0 :       text->SetDecorationColorToForeground();
    3498                 :     }
    3499                 :   }
    3500               0 :   else if (eCSSUnit_EnumColor == decorationColorValue->GetUnit() &&
    3501               0 :            decorationColorValue->GetIntValue() == NS_COLOR_CURRENTCOLOR) {
    3502               0 :     text->SetDecorationColorToForeground();
    3503                 :   }
    3504               0 :   else if (SetColor(*decorationColorValue, 0, mPresContext, aContext,
    3505               0 :                     decorationColor, canStoreInRuleTree)) {
    3506               0 :     text->SetDecorationColor(decorationColor);
    3507                 :   }
    3508               0 :   else if (eCSSUnit_Initial == decorationColorValue->GetUnit() ||
    3509               0 :            eCSSUnit_Enumerated == decorationColorValue->GetUnit()) {
    3510               0 :     NS_ABORT_IF_FALSE(eCSSUnit_Enumerated != decorationColorValue->GetUnit() ||
    3511                 :                       decorationColorValue->GetIntValue() ==
    3512                 :                         NS_STYLE_COLOR_MOZ_USE_TEXT_COLOR,
    3513                 :                       "unexpected enumerated value");
    3514               0 :     text->SetDecorationColorToForeground();
    3515                 :   }
    3516                 : 
    3517                 :   // text-decoration-style: enum, inherit, initial
    3518                 :   const nsCSSValue* decorationStyleValue =
    3519               0 :     aRuleData->ValueForTextDecorationStyle();
    3520               0 :   if (eCSSUnit_Enumerated == decorationStyleValue->GetUnit()) {
    3521               0 :     text->SetDecorationStyle(decorationStyleValue->GetIntValue());
    3522               0 :   } else if (eCSSUnit_Inherit == decorationStyleValue->GetUnit()) {
    3523               0 :     text->SetDecorationStyle(parentText->GetDecorationStyle());
    3524               0 :     canStoreInRuleTree = false;
    3525               0 :   } else if (eCSSUnit_Initial == decorationStyleValue->GetUnit()) {
    3526               0 :     text->SetDecorationStyle(NS_STYLE_TEXT_DECORATION_STYLE_SOLID);
    3527                 :   }
    3528                 : 
    3529                 :   // text-overflow: enum, string, pair(enum|string), inherit, initial
    3530                 :   const nsCSSValue* textOverflowValue =
    3531               0 :     aRuleData->ValueForTextOverflow();
    3532               0 :   if (eCSSUnit_Initial == textOverflowValue->GetUnit()) {
    3533               0 :     text->mTextOverflow = nsStyleTextOverflow();
    3534               0 :   } else if (eCSSUnit_Inherit == textOverflowValue->GetUnit()) {
    3535               0 :     canStoreInRuleTree = false;
    3536               0 :     text->mTextOverflow = parentText->mTextOverflow;
    3537               0 :   } else if (eCSSUnit_Enumerated == textOverflowValue->GetUnit()) {
    3538                 :     // A single enumerated value.
    3539                 :     SetDiscrete(*textOverflowValue, text->mTextOverflow.mRight.mType,
    3540                 :                 canStoreInRuleTree,
    3541                 :                 SETDSC_ENUMERATED, parentText->mTextOverflow.mRight.mType,
    3542               0 :                 NS_STYLE_TEXT_OVERFLOW_CLIP, 0, 0, 0, 0);
    3543               0 :     text->mTextOverflow.mRight.mString.Truncate();
    3544               0 :     text->mTextOverflow.mLeft.mType = NS_STYLE_TEXT_OVERFLOW_CLIP;
    3545               0 :     text->mTextOverflow.mLeft.mString.Truncate();
    3546               0 :     text->mTextOverflow.mLogicalDirections = true;
    3547               0 :   } else if (eCSSUnit_String == textOverflowValue->GetUnit()) {
    3548                 :     // A single string value.
    3549               0 :     text->mTextOverflow.mRight.mType = NS_STYLE_TEXT_OVERFLOW_STRING;
    3550               0 :     textOverflowValue->GetStringValue(text->mTextOverflow.mRight.mString);
    3551               0 :     text->mTextOverflow.mLeft.mType = NS_STYLE_TEXT_OVERFLOW_CLIP;
    3552               0 :     text->mTextOverflow.mLeft.mString.Truncate();
    3553               0 :     text->mTextOverflow.mLogicalDirections = true;
    3554               0 :   } else if (eCSSUnit_Pair == textOverflowValue->GetUnit()) {
    3555                 :     // Two values were specified.
    3556               0 :     text->mTextOverflow.mLogicalDirections = false;
    3557                 :     const nsCSSValuePair& textOverflowValue =
    3558               0 :       aRuleData->ValueForTextOverflow()->GetPairValue();
    3559                 : 
    3560               0 :     const nsCSSValue *textOverflowLeftValue = &textOverflowValue.mXValue;
    3561               0 :     if (eCSSUnit_Enumerated == textOverflowLeftValue->GetUnit()) {
    3562                 :       SetDiscrete(*textOverflowLeftValue, text->mTextOverflow.mLeft.mType,
    3563                 :                   canStoreInRuleTree,
    3564                 :                   SETDSC_ENUMERATED, parentText->mTextOverflow.mLeft.mType,
    3565               0 :                   NS_STYLE_TEXT_OVERFLOW_CLIP, 0, 0, 0, 0);
    3566               0 :       text->mTextOverflow.mLeft.mString.Truncate();
    3567               0 :     } else if (eCSSUnit_String == textOverflowLeftValue->GetUnit()) {
    3568               0 :       textOverflowLeftValue->GetStringValue(text->mTextOverflow.mLeft.mString);
    3569               0 :       text->mTextOverflow.mLeft.mType = NS_STYLE_TEXT_OVERFLOW_STRING;
    3570                 :     }
    3571                 : 
    3572               0 :     const nsCSSValue *textOverflowRightValue = &textOverflowValue.mYValue;
    3573               0 :     if (eCSSUnit_Enumerated == textOverflowRightValue->GetUnit()) {
    3574                 :       SetDiscrete(*textOverflowRightValue, text->mTextOverflow.mRight.mType,
    3575                 :                   canStoreInRuleTree,
    3576                 :                   SETDSC_ENUMERATED, parentText->mTextOverflow.mRight.mType,
    3577               0 :                   NS_STYLE_TEXT_OVERFLOW_CLIP, 0, 0, 0, 0);
    3578               0 :       text->mTextOverflow.mRight.mString.Truncate();
    3579               0 :     } else if (eCSSUnit_String == textOverflowRightValue->GetUnit()) {
    3580               0 :       textOverflowRightValue->GetStringValue(text->mTextOverflow.mRight.mString);
    3581               0 :       text->mTextOverflow.mRight.mType = NS_STYLE_TEXT_OVERFLOW_STRING;
    3582                 :     }
    3583                 :   }
    3584                 : 
    3585                 :   // unicode-bidi: enum, inherit, initial
    3586               0 :   SetDiscrete(*aRuleData->ValueForUnicodeBidi(), text->mUnicodeBidi, canStoreInRuleTree,
    3587                 :               SETDSC_ENUMERATED, parentText->mUnicodeBidi,
    3588               0 :               NS_STYLE_UNICODE_BIDI_NORMAL, 0, 0, 0, 0);
    3589                 : 
    3590               0 :   COMPUTE_END_RESET(TextReset, text)
    3591                 : }
    3592                 : 
    3593                 : const void*
    3594               0 : nsRuleNode::ComputeUserInterfaceData(void* aStartStruct,
    3595                 :                                      const nsRuleData* aRuleData,
    3596                 :                                      nsStyleContext* aContext,
    3597                 :                                      nsRuleNode* aHighestNode,
    3598                 :                                      const RuleDetail aRuleDetail,
    3599                 :                                      const bool aCanStoreInRuleTree)
    3600                 : {
    3601               0 :   COMPUTE_START_INHERITED(UserInterface, (), ui, parentUI)
    3602                 : 
    3603                 :   // cursor: enum, url, inherit
    3604               0 :   const nsCSSValue* cursorValue = aRuleData->ValueForCursor();
    3605               0 :   nsCSSUnit cursorUnit = cursorValue->GetUnit();
    3606               0 :   if (cursorUnit != eCSSUnit_Null) {
    3607               0 :     delete [] ui->mCursorArray;
    3608               0 :     ui->mCursorArray = nsnull;
    3609               0 :     ui->mCursorArrayLength = 0;
    3610                 : 
    3611               0 :     if (cursorUnit == eCSSUnit_Inherit) {
    3612               0 :       canStoreInRuleTree = false;
    3613               0 :       ui->mCursor = parentUI->mCursor;
    3614               0 :       ui->CopyCursorArrayFrom(*parentUI);
    3615                 :     }
    3616               0 :     else if (cursorUnit == eCSSUnit_Initial) {
    3617               0 :       ui->mCursor = NS_STYLE_CURSOR_AUTO;
    3618                 :     }
    3619                 :     else {
    3620                 :       // The parser will never create a list that is *all* URL values --
    3621                 :       // that's invalid.
    3622               0 :       NS_ABORT_IF_FALSE(cursorUnit == eCSSUnit_List ||
    3623                 :                         cursorUnit == eCSSUnit_ListDep,
    3624                 :                         nsPrintfCString(64, "unrecognized cursor unit %d",
    3625                 :                                         cursorUnit).get());
    3626               0 :       const nsCSSValueList* list = cursorValue->GetListValue();
    3627               0 :       const nsCSSValueList* list2 = list;
    3628               0 :       PRUint32 arrayLength = 0;
    3629               0 :       for ( ; list->mValue.GetUnit() == eCSSUnit_Array; list = list->mNext)
    3630               0 :         if (list->mValue.GetArrayValue()->Item(0).GetImageValue())
    3631               0 :           ++arrayLength;
    3632                 : 
    3633               0 :       if (arrayLength != 0) {
    3634               0 :         ui->mCursorArray = new nsCursorImage[arrayLength];
    3635               0 :         if (ui->mCursorArray) {
    3636               0 :           ui->mCursorArrayLength = arrayLength;
    3637                 : 
    3638               0 :           for (nsCursorImage *item = ui->mCursorArray;
    3639               0 :                list2->mValue.GetUnit() == eCSSUnit_Array;
    3640                 :                list2 = list2->mNext) {
    3641               0 :             nsCSSValue::Array *arr = list2->mValue.GetArrayValue();
    3642               0 :             imgIRequest *req = arr->Item(0).GetImageValue();
    3643               0 :             if (req) {
    3644               0 :               item->SetImage(req);
    3645               0 :               if (arr->Item(1).GetUnit() != eCSSUnit_Null) {
    3646               0 :                 item->mHaveHotspot = true;
    3647               0 :                 item->mHotspotX = arr->Item(1).GetFloatValue(),
    3648               0 :                 item->mHotspotY = arr->Item(2).GetFloatValue();
    3649                 :               }
    3650               0 :               ++item;
    3651                 :             }
    3652                 :           }
    3653                 :         }
    3654                 :       }
    3655                 : 
    3656               0 :       NS_ASSERTION(list, "Must have non-array value at the end");
    3657               0 :       NS_ASSERTION(list->mValue.GetUnit() == eCSSUnit_Enumerated,
    3658                 :                    "Unexpected fallback value at end of cursor list");
    3659               0 :       ui->mCursor = list->mValue.GetIntValue();
    3660                 :     }
    3661                 :   }
    3662                 : 
    3663                 :   // user-input: enum, inherit, initial
    3664               0 :   SetDiscrete(*aRuleData->ValueForUserInput(),
    3665                 :               ui->mUserInput, canStoreInRuleTree,
    3666                 :               SETDSC_ENUMERATED, parentUI->mUserInput,
    3667               0 :               NS_STYLE_USER_INPUT_AUTO, 0, 0, 0, 0);
    3668                 : 
    3669                 :   // user-modify: enum, inherit, initial
    3670               0 :   SetDiscrete(*aRuleData->ValueForUserModify(),
    3671                 :               ui->mUserModify, canStoreInRuleTree,
    3672                 :               SETDSC_ENUMERATED, parentUI->mUserModify,
    3673                 :               NS_STYLE_USER_MODIFY_READ_ONLY,
    3674               0 :               0, 0, 0, 0);
    3675                 : 
    3676                 :   // user-focus: enum, inherit, initial
    3677               0 :   SetDiscrete(*aRuleData->ValueForUserFocus(),
    3678                 :               ui->mUserFocus, canStoreInRuleTree,
    3679                 :               SETDSC_ENUMERATED, parentUI->mUserFocus,
    3680               0 :               NS_STYLE_USER_FOCUS_NONE, 0, 0, 0, 0);
    3681                 : 
    3682               0 :   COMPUTE_END_INHERITED(UserInterface, ui)
    3683                 : }
    3684                 : 
    3685                 : const void*
    3686               0 : nsRuleNode::ComputeUIResetData(void* aStartStruct,
    3687                 :                                const nsRuleData* aRuleData,
    3688                 :                                nsStyleContext* aContext,
    3689                 :                                nsRuleNode* aHighestNode,
    3690                 :                                const RuleDetail aRuleDetail,
    3691                 :                                const bool aCanStoreInRuleTree)
    3692                 : {
    3693               0 :   COMPUTE_START_RESET(UIReset, (), ui, parentUI)
    3694                 : 
    3695                 :   // user-select: enum, inherit, initial
    3696               0 :   SetDiscrete(*aRuleData->ValueForUserSelect(),
    3697                 :               ui->mUserSelect, canStoreInRuleTree,
    3698                 :               SETDSC_ENUMERATED, parentUI->mUserSelect,
    3699               0 :               NS_STYLE_USER_SELECT_AUTO, 0, 0, 0, 0);
    3700                 : 
    3701                 :   // ime-mode: enum, inherit, initial
    3702               0 :   SetDiscrete(*aRuleData->ValueForImeMode(),
    3703                 :               ui->mIMEMode, canStoreInRuleTree,
    3704                 :               SETDSC_ENUMERATED, parentUI->mIMEMode,
    3705               0 :               NS_STYLE_IME_MODE_AUTO, 0, 0, 0, 0);
    3706                 : 
    3707                 :   // force-broken-image-icons: integer, inherit, initial
    3708               0 :   SetDiscrete(*aRuleData->ValueForForceBrokenImageIcon(),
    3709                 :               ui->mForceBrokenImageIcon,
    3710                 :               canStoreInRuleTree,
    3711                 :               SETDSC_INTEGER,
    3712                 :               parentUI->mForceBrokenImageIcon,
    3713               0 :               0, 0, 0, 0, 0);
    3714                 : 
    3715                 :   // -moz-window-shadow: enum, inherit, initial
    3716               0 :   SetDiscrete(*aRuleData->ValueForWindowShadow(),
    3717                 :               ui->mWindowShadow, canStoreInRuleTree,
    3718                 :               SETDSC_ENUMERATED, parentUI->mWindowShadow,
    3719               0 :               NS_STYLE_WINDOW_SHADOW_DEFAULT, 0, 0, 0, 0);
    3720                 : 
    3721               0 :   COMPUTE_END_RESET(UIReset, ui)
    3722                 : }
    3723                 : 
    3724                 : // Information about each transition or animation property that is
    3725                 : // constant.
    3726                 : struct TransitionPropInfo {
    3727                 :   nsCSSProperty property;
    3728                 :   // Location of the count of the property's computed value.
    3729                 :   PRUint32 nsStyleDisplay::* sdCount;
    3730                 : };
    3731                 : 
    3732                 : // Each property's index in this array must match its index in the
    3733                 : // mutable array |transitionPropData| below.
    3734                 : static const TransitionPropInfo transitionPropInfo[4] = {
    3735                 :   { eCSSProperty_transition_delay,
    3736                 :     &nsStyleDisplay::mTransitionDelayCount },
    3737                 :   { eCSSProperty_transition_duration,
    3738                 :     &nsStyleDisplay::mTransitionDurationCount },
    3739                 :   { eCSSProperty_transition_property,
    3740                 :     &nsStyleDisplay::mTransitionPropertyCount },
    3741                 :   { eCSSProperty_transition_timing_function,
    3742                 :     &nsStyleDisplay::mTransitionTimingFunctionCount },
    3743                 : };
    3744                 : 
    3745                 : // Each property's index in this array must match its index in the
    3746                 : // mutable array |animationPropData| below.
    3747                 : static const TransitionPropInfo animationPropInfo[8] = {
    3748                 :   { eCSSProperty_animation_delay,
    3749                 :     &nsStyleDisplay::mAnimationDelayCount },
    3750                 :   { eCSSProperty_animation_duration,
    3751                 :     &nsStyleDisplay::mAnimationDurationCount },
    3752                 :   { eCSSProperty_animation_name,
    3753                 :     &nsStyleDisplay::mAnimationNameCount },
    3754                 :   { eCSSProperty_animation_timing_function,
    3755                 :     &nsStyleDisplay::mAnimationTimingFunctionCount },
    3756                 :   { eCSSProperty_animation_direction,
    3757                 :     &nsStyleDisplay::mAnimationDirectionCount },
    3758                 :   { eCSSProperty_animation_fill_mode,
    3759                 :     &nsStyleDisplay::mAnimationFillModeCount },
    3760                 :   { eCSSProperty_animation_play_state,
    3761                 :     &nsStyleDisplay::mAnimationPlayStateCount },
    3762                 :   { eCSSProperty_animation_iteration_count,
    3763                 :     &nsStyleDisplay::mAnimationIterationCountCount },
    3764                 : };
    3765                 : 
    3766                 : // Information about each transition or animation property that changes
    3767                 : // during ComputeDisplayData.
    3768                 : struct TransitionPropData {
    3769                 :   const nsCSSValueList *list;
    3770                 :   nsCSSUnit unit;
    3771                 :   PRUint32 num;
    3772                 : };
    3773                 : 
    3774                 : static PRUint32
    3775               0 : CountTransitionProps(const TransitionPropInfo* aInfo,
    3776                 :                      TransitionPropData* aData,
    3777                 :                      size_t aLength,
    3778                 :                      nsStyleDisplay* aDisplay,
    3779                 :                      const nsStyleDisplay* aParentDisplay,
    3780                 :                      const nsRuleData* aRuleData,
    3781                 :                      bool& aCanStoreInRuleTree)
    3782                 : {
    3783                 :   // The four transition properties or eight animation properties are
    3784                 :   // stored in nsCSSDisplay in a single array for all properties.  The
    3785                 :   // number of transitions is equal to the number of items in the
    3786                 :   // longest property's value.  Properties that have fewer values than
    3787                 :   // the longest are filled in by repeating the list.  However, this
    3788                 :   // repetition does not extend the computed value of that particular
    3789                 :   // property (for purposes of inheritance, or, in our code, for when
    3790                 :   // other properties are overridden by a more specific rule).
    3791                 : 
    3792                 :   // But actually, since the spec isn't clear yet, we'll fully compute
    3793                 :   // all of them (so we can switch easily later), but only care about
    3794                 :   // the ones up to the number of items for 'transition-property', per
    3795                 :   // http://lists.w3.org/Archives/Public/www-style/2009Aug/0109.html .
    3796                 : 
    3797                 :   // Transitions are difficult to handle correctly because of this.  For
    3798                 :   // example, we need to handle scenarios such as:
    3799                 :   //  * a more general rule specifies transition-property: a, b, c;
    3800                 :   //  * a more specific rule overrides as transition-property: d;
    3801                 :   //
    3802                 :   // If only the general rule applied, we would fill in the extra
    3803                 :   // properties (duration, delay, etc) with initial values to create 3
    3804                 :   // fully-specified transitions.  But when the more specific rule
    3805                 :   // applies, we should only create a single transition.  In order to do
    3806                 :   // this we need to remember which properties were explicitly specified
    3807                 :   // and which ones were just filled in with initial values to get a
    3808                 :   // fully-specified transition, which we do by remembering the number
    3809                 :   // of values for each property.
    3810                 : 
    3811               0 :   PRUint32 numTransitions = 0;
    3812               0 :   for (size_t i = 0; i < aLength; ++i) {
    3813               0 :     const TransitionPropInfo& info = aInfo[i];
    3814               0 :     TransitionPropData& data = aData[i];
    3815                 : 
    3816                 :     // cache whether any of the properties are specified as 'inherit' so
    3817                 :     // we can use it below
    3818                 : 
    3819               0 :     const nsCSSValue& value = *aRuleData->ValueFor(info.property);
    3820               0 :     data.unit = value.GetUnit();
    3821               0 :     data.list = (value.GetUnit() == eCSSUnit_List ||
    3822               0 :                  value.GetUnit() == eCSSUnit_ListDep)
    3823               0 :                   ? value.GetListValue() : nsnull;
    3824                 : 
    3825                 :     // General algorithm to determine how many total transitions we need
    3826                 :     // to build.  For each property:
    3827                 :     //  - if there is no value specified in for the property in
    3828                 :     //    displayData, use the values from the start struct, but only if
    3829                 :     //    they were explicitly specified
    3830                 :     //  - if there is a value specified for the property in displayData:
    3831                 :     //    - if the value is 'inherit', count the number of values for
    3832                 :     //      that property are specified by the parent, but only those
    3833                 :     //      that were explicitly specified
    3834                 :     //    - otherwise, count the number of values specified in displayData
    3835                 : 
    3836                 : 
    3837                 :     // calculate number of elements
    3838               0 :     if (data.unit == eCSSUnit_Inherit) {
    3839               0 :       data.num = aParentDisplay->*(info.sdCount);
    3840               0 :       aCanStoreInRuleTree = false;
    3841               0 :     } else if (data.list) {
    3842               0 :       data.num = ListLength(data.list);
    3843                 :     } else {
    3844               0 :       data.num = aDisplay->*(info.sdCount);
    3845                 :     }
    3846               0 :     if (data.num > numTransitions)
    3847               0 :       numTransitions = data.num;
    3848                 :   }
    3849                 : 
    3850               0 :   return numTransitions;
    3851                 : }
    3852                 : 
    3853                 : static void
    3854               0 : ComputeTimingFunction(const nsCSSValue& aValue, nsTimingFunction& aResult)
    3855                 : {
    3856               0 :   switch (aValue.GetUnit()) {
    3857                 :     case eCSSUnit_Enumerated:
    3858               0 :       aResult = nsTimingFunction(aValue.GetIntValue());
    3859               0 :       break;
    3860                 :     case eCSSUnit_Cubic_Bezier:
    3861                 :       {
    3862               0 :         nsCSSValue::Array* array = aValue.GetArrayValue();
    3863               0 :         NS_ASSERTION(array && array->Count() == 4,
    3864                 :                      "Need 4 control points");
    3865               0 :         aResult = nsTimingFunction(array->Item(0).GetFloatValue(),
    3866               0 :                                    array->Item(1).GetFloatValue(),
    3867               0 :                                    array->Item(2).GetFloatValue(),
    3868               0 :                                    array->Item(3).GetFloatValue());
    3869                 :       }
    3870               0 :       break;
    3871                 :     case eCSSUnit_Steps:
    3872                 :       {
    3873               0 :         nsCSSValue::Array* array = aValue.GetArrayValue();
    3874               0 :         NS_ASSERTION(array && array->Count() == 2,
    3875                 :                      "Need 2 items");
    3876               0 :         NS_ASSERTION(array->Item(0).GetUnit() == eCSSUnit_Integer,
    3877                 :                      "unexpected first value");
    3878               0 :         NS_ASSERTION(array->Item(1).GetUnit() == eCSSUnit_Enumerated &&
    3879                 :                      (array->Item(1).GetIntValue() ==
    3880                 :                        NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_START ||
    3881                 :                       array->Item(1).GetIntValue() ==
    3882                 :                        NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END),
    3883                 :                      "unexpected second value");
    3884                 :         nsTimingFunction::Type type =
    3885               0 :           (array->Item(1).GetIntValue() ==
    3886                 :             NS_STYLE_TRANSITION_TIMING_FUNCTION_STEP_END)
    3887               0 :             ? nsTimingFunction::StepEnd : nsTimingFunction::StepStart;
    3888               0 :         aResult = nsTimingFunction(type, array->Item(0).GetIntValue());
    3889                 :       }
    3890               0 :       break;
    3891                 :     default:
    3892               0 :       NS_NOTREACHED("Invalid transition property unit");
    3893                 :   }
    3894               0 : }
    3895                 : 
    3896                 : const void*
    3897               0 : nsRuleNode::ComputeDisplayData(void* aStartStruct,
    3898                 :                                const nsRuleData* aRuleData,
    3899                 :                                nsStyleContext* aContext,
    3900                 :                                nsRuleNode* aHighestNode,
    3901                 :                                const RuleDetail aRuleDetail,
    3902                 :                                const bool aCanStoreInRuleTree)
    3903                 : {
    3904               0 :   COMPUTE_START_RESET(Display, (), display, parentDisplay)
    3905                 : 
    3906                 :   // We may have ended up with aStartStruct's values of mDisplay and
    3907                 :   // mFloats, but those may not be correct if our style data overrides
    3908                 :   // its position or float properties.  Reset to mOriginalDisplay and
    3909                 :   // mOriginalFloats; it if turns out we still need the display/floats
    3910                 :   // adjustments we'll do them below.
    3911               0 :   display->mDisplay = display->mOriginalDisplay;
    3912               0 :   display->mFloats = display->mOriginalFloats;
    3913                 : 
    3914                 :   // Each property's index in this array must match its index in the
    3915                 :   // const array |transitionPropInfo| above.
    3916                 :   TransitionPropData transitionPropData[4];
    3917               0 :   TransitionPropData& delay = transitionPropData[0];
    3918               0 :   TransitionPropData& duration = transitionPropData[1];
    3919               0 :   TransitionPropData& property = transitionPropData[2];
    3920               0 :   TransitionPropData& timingFunction = transitionPropData[3];
    3921                 : 
    3922                 : #define FOR_ALL_TRANSITION_PROPS(var_) \
    3923                 :                                       for (PRUint32 var_ = 0; var_ < 4; ++var_)
    3924                 : 
    3925                 :   // CSS Transitions
    3926                 :   PRUint32 numTransitions =
    3927                 :     CountTransitionProps(transitionPropInfo, transitionPropData,
    3928                 :                          ArrayLength(transitionPropData),
    3929                 :                          display, parentDisplay, aRuleData,
    3930               0 :                          canStoreInRuleTree);
    3931                 : 
    3932               0 :   if (!display->mTransitions.SetLength(numTransitions)) {
    3933               0 :     NS_WARNING("failed to allocate transitions array");
    3934               0 :     display->mTransitions.SetLength(1);
    3935               0 :     NS_ABORT_IF_FALSE(display->mTransitions.Length() == 1,
    3936                 :                       "could not allocate using auto array buffer");
    3937               0 :     numTransitions = 1;
    3938               0 :     FOR_ALL_TRANSITION_PROPS(p) {
    3939               0 :       TransitionPropData& d = transitionPropData[p];
    3940                 : 
    3941               0 :       d.num = 1;
    3942                 :     }
    3943                 :   }
    3944                 : 
    3945               0 :   FOR_ALL_TRANSITION_PROPS(p) {
    3946               0 :     const TransitionPropInfo& i = transitionPropInfo[p];
    3947               0 :     TransitionPropData& d = transitionPropData[p];
    3948                 : 
    3949               0 :     display->*(i.sdCount) = d.num;
    3950                 :   }
    3951                 : 
    3952                 :   // Fill in the transitions we just allocated with the appropriate values.
    3953               0 :   for (PRUint32 i = 0; i < numTransitions; ++i) {
    3954               0 :     nsTransition *transition = &display->mTransitions[i];
    3955                 : 
    3956               0 :     if (i >= delay.num) {
    3957               0 :       transition->SetDelay(display->mTransitions[i % delay.num].GetDelay());
    3958               0 :     } else if (delay.unit == eCSSUnit_Inherit) {
    3959                 :       // FIXME (Bug 522599) (for all transition properties): write a test that
    3960                 :       // detects when this was wrong for i >= delay.num if parent had
    3961                 :       // count for this property not equal to length
    3962               0 :       NS_ABORT_IF_FALSE(i < parentDisplay->mTransitionDelayCount,
    3963                 :                         "delay.num computed incorrectly");
    3964               0 :       NS_ABORT_IF_FALSE(!canStoreInRuleTree,
    3965                 :                         "should have made canStoreInRuleTree false above");
    3966               0 :       transition->SetDelay(parentDisplay->mTransitions[i].GetDelay());
    3967               0 :     } else if (delay.unit == eCSSUnit_Initial) {
    3968               0 :       transition->SetDelay(0.0);
    3969               0 :     } else if (delay.list) {
    3970               0 :       switch (delay.list->mValue.GetUnit()) {
    3971                 :         case eCSSUnit_Seconds:
    3972                 :           transition->SetDelay(PR_MSEC_PER_SEC *
    3973               0 :                                delay.list->mValue.GetFloatValue());
    3974               0 :           break;
    3975                 :         case eCSSUnit_Milliseconds:
    3976               0 :           transition->SetDelay(delay.list->mValue.GetFloatValue());
    3977               0 :           break;
    3978                 :         default:
    3979               0 :           NS_NOTREACHED("Invalid delay unit");
    3980                 :       }
    3981                 :     }
    3982                 : 
    3983               0 :     if (i >= duration.num) {
    3984                 :       transition->SetDuration(
    3985               0 :         display->mTransitions[i % duration.num].GetDuration());
    3986               0 :     } else if (duration.unit == eCSSUnit_Inherit) {
    3987               0 :       NS_ABORT_IF_FALSE(i < parentDisplay->mTransitionDurationCount,
    3988                 :                         "duration.num computed incorrectly");
    3989               0 :       NS_ABORT_IF_FALSE(!canStoreInRuleTree,
    3990                 :                         "should have made canStoreInRuleTree false above");
    3991               0 :       transition->SetDuration(parentDisplay->mTransitions[i].GetDuration());
    3992               0 :     } else if (duration.unit == eCSSUnit_Initial) {
    3993               0 :       transition->SetDuration(0.0);
    3994               0 :     } else if (duration.list) {
    3995               0 :       switch (duration.list->mValue.GetUnit()) {
    3996                 :         case eCSSUnit_Seconds:
    3997                 :           transition->SetDuration(PR_MSEC_PER_SEC *
    3998               0 :                                   duration.list->mValue.GetFloatValue());
    3999               0 :           break;
    4000                 :         case eCSSUnit_Milliseconds:
    4001               0 :           transition->SetDuration(duration.list->mValue.GetFloatValue());
    4002               0 :           break;
    4003                 :         default:
    4004               0 :           NS_NOTREACHED("Invalid duration unit");
    4005                 :       }
    4006                 :     }
    4007                 : 
    4008               0 :     if (i >= property.num) {
    4009               0 :       transition->CopyPropertyFrom(display->mTransitions[i % property.num]);
    4010               0 :     } else if (property.unit == eCSSUnit_Inherit) {
    4011               0 :       NS_ABORT_IF_FALSE(i < parentDisplay->mTransitionPropertyCount,
    4012                 :                         "property.num computed incorrectly");
    4013               0 :       NS_ABORT_IF_FALSE(!canStoreInRuleTree,
    4014                 :                         "should have made canStoreInRuleTree false above");
    4015               0 :       transition->CopyPropertyFrom(parentDisplay->mTransitions[i]);
    4016               0 :     } else if (property.unit == eCSSUnit_Initial ||
    4017                 :                property.unit == eCSSUnit_All) {
    4018               0 :       transition->SetProperty(eCSSPropertyExtra_all_properties);
    4019               0 :     } else if (property.unit == eCSSUnit_None) {
    4020               0 :       transition->SetProperty(eCSSPropertyExtra_no_properties);
    4021               0 :     } else if (property.list) {
    4022               0 :       NS_ABORT_IF_FALSE(property.list->mValue.GetUnit() == eCSSUnit_Ident,
    4023                 :                         nsPrintfCString(64,
    4024                 :                                         "Invalid transition property unit %d",
    4025                 :                                         property.list->mValue.GetUnit()).get());
    4026                 : 
    4027                 :       nsDependentString
    4028               0 :         propertyStr(property.list->mValue.GetStringBufferValue());
    4029               0 :       nsCSSProperty prop = nsCSSProps::LookupProperty(propertyStr);
    4030               0 :       if (prop == eCSSProperty_UNKNOWN) {
    4031               0 :         transition->SetUnknownProperty(propertyStr);
    4032                 :       } else {
    4033               0 :         transition->SetProperty(prop);
    4034                 :       }
    4035                 :     }
    4036                 : 
    4037               0 :     if (i >= timingFunction.num) {
    4038                 :       transition->SetTimingFunction(
    4039               0 :         display->mTransitions[i % timingFunction.num].GetTimingFunction());
    4040               0 :     } else if (timingFunction.unit == eCSSUnit_Inherit) {
    4041               0 :       NS_ABORT_IF_FALSE(i < parentDisplay->mTransitionTimingFunctionCount,
    4042                 :                         "timingFunction.num computed incorrectly");
    4043               0 :       NS_ABORT_IF_FALSE(!canStoreInRuleTree,
    4044                 :                         "should have made canStoreInRuleTree false above");
    4045                 :       transition->SetTimingFunction(
    4046               0 :         parentDisplay->mTransitions[i].GetTimingFunction());
    4047               0 :     } else if (timingFunction.unit == eCSSUnit_Initial) {
    4048                 :       transition->SetTimingFunction(
    4049               0 :         nsTimingFunction(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE));
    4050               0 :     } else if (timingFunction.list) {
    4051                 :       ComputeTimingFunction(timingFunction.list->mValue,
    4052               0 :                             transition->TimingFunctionSlot());
    4053                 :     }
    4054                 : 
    4055               0 :     FOR_ALL_TRANSITION_PROPS(p) {
    4056               0 :       const TransitionPropInfo& info = transitionPropInfo[p];
    4057               0 :       TransitionPropData& d = transitionPropData[p];
    4058                 : 
    4059                 :       // if we're at the end of the list, start at the beginning and repeat
    4060                 :       // until we're out of transitions to populate
    4061               0 :       if (d.list) {
    4062                 :         d.list = d.list->mNext ? d.list->mNext :
    4063               0 :           aRuleData->ValueFor(info.property)->GetListValue();
    4064                 :       }
    4065                 :     }
    4066                 :   }
    4067                 : 
    4068                 :   // Each property's index in this array must match its index in the
    4069                 :   // const array |animationPropInfo| above.
    4070                 :   TransitionPropData animationPropData[8];
    4071               0 :   TransitionPropData& animDelay = animationPropData[0];
    4072               0 :   TransitionPropData& animDuration = animationPropData[1];
    4073               0 :   TransitionPropData& animName = animationPropData[2];
    4074               0 :   TransitionPropData& animTimingFunction = animationPropData[3];
    4075               0 :   TransitionPropData& animDirection = animationPropData[4];
    4076               0 :   TransitionPropData& animFillMode = animationPropData[5];
    4077               0 :   TransitionPropData& animPlayState = animationPropData[6];
    4078               0 :   TransitionPropData& animIterationCount = animationPropData[7];
    4079                 : 
    4080                 : #define FOR_ALL_ANIMATION_PROPS(var_) \
    4081                 :     for (PRUint32 var_ = 0; var_ < 8; ++var_)
    4082                 : 
    4083                 :   // CSS Animations.
    4084                 : 
    4085                 :   PRUint32 numAnimations =
    4086                 :     CountTransitionProps(animationPropInfo, animationPropData,
    4087                 :                          ArrayLength(animationPropData),
    4088                 :                          display, parentDisplay, aRuleData,
    4089               0 :                          canStoreInRuleTree);
    4090                 : 
    4091               0 :   if (!display->mAnimations.SetLength(numAnimations)) {
    4092               0 :     NS_WARNING("failed to allocate animations array");
    4093               0 :     display->mAnimations.SetLength(1);
    4094               0 :     NS_ABORT_IF_FALSE(display->mAnimations.Length() == 1,
    4095                 :                       "could not allocate using auto array buffer");
    4096               0 :     numAnimations = 1;
    4097               0 :     FOR_ALL_ANIMATION_PROPS(p) {
    4098               0 :       TransitionPropData& d = animationPropData[p];
    4099                 : 
    4100               0 :       d.num = 1;
    4101                 :     }
    4102                 :   }
    4103                 : 
    4104               0 :   FOR_ALL_ANIMATION_PROPS(p) {
    4105               0 :     const TransitionPropInfo& i = animationPropInfo[p];
    4106               0 :     TransitionPropData& d = animationPropData[p];
    4107                 : 
    4108               0 :     display->*(i.sdCount) = d.num;
    4109                 :   }
    4110                 : 
    4111                 :   // Fill in the animations we just allocated with the appropriate values.
    4112               0 :   for (PRUint32 i = 0; i < numAnimations; ++i) {
    4113               0 :     nsAnimation *animation = &display->mAnimations[i];
    4114                 : 
    4115               0 :     if (i >= animDelay.num) {
    4116               0 :       animation->SetDelay(display->mAnimations[i % animDelay.num].GetDelay());
    4117               0 :     } else if (animDelay.unit == eCSSUnit_Inherit) {
    4118                 :       // FIXME (Bug 522599) (for all animation properties): write a test that
    4119                 :       // detects when this was wrong for i >= animDelay.num if parent had
    4120                 :       // count for this property not equal to length
    4121               0 :       NS_ABORT_IF_FALSE(i < parentDisplay->mAnimationDelayCount,
    4122                 :                         "animDelay.num computed incorrectly");
    4123               0 :       NS_ABORT_IF_FALSE(!canStoreInRuleTree,
    4124                 :                         "should have made canStoreInRuleTree false above");
    4125               0 :       animation->SetDelay(parentDisplay->mAnimations[i].GetDelay());
    4126               0 :     } else if (animDelay.unit == eCSSUnit_Initial) {
    4127               0 :       animation->SetDelay(0.0);
    4128               0 :     } else if (animDelay.list) {
    4129               0 :       switch (animDelay.list->mValue.GetUnit()) {
    4130                 :         case eCSSUnit_Seconds:
    4131                 :           animation->SetDelay(PR_MSEC_PER_SEC *
    4132               0 :                               animDelay.list->mValue.GetFloatValue());
    4133               0 :           break;
    4134                 :         case eCSSUnit_Milliseconds:
    4135               0 :           animation->SetDelay(animDelay.list->mValue.GetFloatValue());
    4136               0 :           break;
    4137                 :         default:
    4138               0 :           NS_NOTREACHED("Invalid delay unit");
    4139                 :       }
    4140                 :     }
    4141                 : 
    4142               0 :     if (i >= animDuration.num) {
    4143                 :       animation->SetDuration(
    4144               0 :         display->mAnimations[i % animDuration.num].GetDuration());
    4145               0 :     } else if (animDuration.unit == eCSSUnit_Inherit) {
    4146               0 :       NS_ABORT_IF_FALSE(i < parentDisplay->mAnimationDurationCount,
    4147                 :                         "animDuration.num computed incorrectly");
    4148               0 :       NS_ABORT_IF_FALSE(!canStoreInRuleTree,
    4149                 :                         "should have made canStoreInRuleTree false above");
    4150               0 :       animation->SetDuration(parentDisplay->mAnimations[i].GetDuration());
    4151               0 :     } else if (animDuration.unit == eCSSUnit_Initial) {
    4152               0 :       animation->SetDuration(0.0);
    4153               0 :     } else if (animDuration.list) {
    4154               0 :       switch (animDuration.list->mValue.GetUnit()) {
    4155                 :         case eCSSUnit_Seconds:
    4156                 :           animation->SetDuration(PR_MSEC_PER_SEC *
    4157               0 :                                  animDuration.list->mValue.GetFloatValue());
    4158               0 :           break;
    4159                 :         case eCSSUnit_Milliseconds:
    4160               0 :           animation->SetDuration(animDuration.list->mValue.GetFloatValue());
    4161               0 :           break;
    4162                 :         default:
    4163               0 :           NS_NOTREACHED("Invalid duration unit");
    4164                 :       }
    4165                 :     }
    4166                 : 
    4167               0 :     if (i >= animName.num) {
    4168               0 :       animation->SetName(display->mAnimations[i % animName.num].GetName());
    4169               0 :     } else if (animName.unit == eCSSUnit_Inherit) {
    4170               0 :       NS_ABORT_IF_FALSE(i < parentDisplay->mAnimationNameCount,
    4171                 :                         "animName.num computed incorrectly");
    4172               0 :       NS_ABORT_IF_FALSE(!canStoreInRuleTree,
    4173                 :                         "should have made canStoreInRuleTree false above");
    4174               0 :       animation->SetName(parentDisplay->mAnimations[i].GetName());
    4175               0 :     } else if (animName.unit == eCSSUnit_Initial) {
    4176               0 :       animation->SetName(EmptyString());
    4177               0 :     } else if (animName.list) {
    4178               0 :       switch (animName.list->mValue.GetUnit()) {
    4179                 :         case eCSSUnit_Ident: {
    4180                 :           nsDependentString
    4181               0 :             nameStr(animName.list->mValue.GetStringBufferValue());
    4182               0 :           animation->SetName(nameStr);
    4183                 :           break;
    4184                 :         }
    4185                 :         case eCSSUnit_None: {
    4186               0 :           animation->SetName(EmptyString());
    4187               0 :           break;
    4188                 :         }
    4189                 :         default:
    4190               0 :           NS_ABORT_IF_FALSE(false,
    4191                 :             nsPrintfCString(64, "Invalid animation-name unit %d",
    4192                 :                                 animName.list->mValue.GetUnit()).get());
    4193                 :       }
    4194                 :     }
    4195                 : 
    4196               0 :     if (i >= animTimingFunction.num) {
    4197                 :       animation->SetTimingFunction(
    4198               0 :         display->mAnimations[i % animTimingFunction.num].GetTimingFunction());
    4199               0 :     } else if (animTimingFunction.unit == eCSSUnit_Inherit) {
    4200               0 :       NS_ABORT_IF_FALSE(i < parentDisplay->mAnimationTimingFunctionCount,
    4201                 :                         "animTimingFunction.num computed incorrectly");
    4202               0 :       NS_ABORT_IF_FALSE(!canStoreInRuleTree,
    4203                 :                         "should have made canStoreInRuleTree false above");
    4204                 :       animation->SetTimingFunction(
    4205               0 :         parentDisplay->mAnimations[i].GetTimingFunction());
    4206               0 :     } else if (animTimingFunction.unit == eCSSUnit_Initial) {
    4207                 :       animation->SetTimingFunction(
    4208               0 :         nsTimingFunction(NS_STYLE_TRANSITION_TIMING_FUNCTION_EASE));
    4209               0 :     } else if (animTimingFunction.list) {
    4210                 :       ComputeTimingFunction(animTimingFunction.list->mValue,
    4211               0 :                             animation->TimingFunctionSlot());
    4212                 :     }
    4213                 : 
    4214               0 :     if (i >= animDirection.num) {
    4215               0 :       animation->SetDirection(display->mAnimations[i % animDirection.num].GetDirection());
    4216               0 :     } else if (animDirection.unit == eCSSUnit_Inherit) {
    4217               0 :       NS_ABORT_IF_FALSE(i < parentDisplay->mAnimationDirectionCount,
    4218                 :                         "animDirection.num computed incorrectly");
    4219               0 :       NS_ABORT_IF_FALSE(!canStoreInRuleTree,
    4220                 :                         "should have made canStoreInRuleTree false above");
    4221               0 :       animation->SetDirection(parentDisplay->mAnimations[i].GetDirection());
    4222               0 :     } else if (animDirection.unit == eCSSUnit_Initial) {
    4223               0 :       animation->SetDirection(NS_STYLE_ANIMATION_DIRECTION_NORMAL);
    4224               0 :     } else if (animDirection.list) {
    4225               0 :       NS_ABORT_IF_FALSE(animDirection.list->mValue.GetUnit() == eCSSUnit_Enumerated,
    4226                 :                         nsPrintfCString(64,
    4227                 :                                         "Invalid animation-direction unit %d",
    4228                 :                                         animDirection.list->mValue.GetUnit()).get());
    4229                 : 
    4230               0 :       animation->SetDirection(animDirection.list->mValue.GetIntValue());
    4231                 :     }
    4232                 : 
    4233               0 :     if (i >= animFillMode.num) {
    4234               0 :       animation->SetFillMode(display->mAnimations[i % animFillMode.num].GetFillMode());
    4235               0 :     } else if (animFillMode.unit == eCSSUnit_Inherit) {
    4236               0 :       NS_ABORT_IF_FALSE(i < parentDisplay->mAnimationFillModeCount,
    4237                 :                         "animFillMode.num computed incorrectly");
    4238               0 :       NS_ABORT_IF_FALSE(!canStoreInRuleTree,
    4239                 :                         "should have made canStoreInRuleTree false above");
    4240               0 :       animation->SetFillMode(parentDisplay->mAnimations[i].GetFillMode());
    4241               0 :     } else if (animFillMode.unit == eCSSUnit_Initial) {
    4242               0 :       animation->SetFillMode(NS_STYLE_ANIMATION_FILL_MODE_NONE);
    4243               0 :     } else if (animFillMode.list) {
    4244               0 :       NS_ABORT_IF_FALSE(animFillMode.list->mValue.GetUnit() == eCSSUnit_Enumerated,
    4245                 :                         nsPrintfCString(64,
    4246                 :                                         "Invalid animation-fill-mode unit %d",
    4247                 :                                         animFillMode.list->mValue.GetUnit()).get());
    4248                 : 
    4249               0 :       animation->SetFillMode(animFillMode.list->mValue.GetIntValue());
    4250                 :     }
    4251                 : 
    4252               0 :     if (i >= animPlayState.num) {
    4253               0 :       animation->SetPlayState(display->mAnimations[i % animPlayState.num].GetPlayState());
    4254               0 :     } else if (animPlayState.unit == eCSSUnit_Inherit) {
    4255               0 :       NS_ABORT_IF_FALSE(i < parentDisplay->mAnimationPlayStateCount,
    4256                 :                         "animPlayState.num computed incorrectly");
    4257               0 :       NS_ABORT_IF_FALSE(!canStoreInRuleTree,
    4258                 :                         "should have made canStoreInRuleTree false above");
    4259               0 :       animation->SetPlayState(parentDisplay->mAnimations[i].GetPlayState());
    4260               0 :     } else if (animPlayState.unit == eCSSUnit_Initial) {
    4261               0 :       animation->SetPlayState(NS_STYLE_ANIMATION_PLAY_STATE_RUNNING);
    4262               0 :     } else if (animPlayState.list) {
    4263               0 :       NS_ABORT_IF_FALSE(animPlayState.list->mValue.GetUnit() == eCSSUnit_Enumerated,
    4264                 :                         nsPrintfCString(64,
    4265                 :                                         "Invalid animation-play-state unit %d",
    4266                 :                                         animPlayState.list->mValue.GetUnit()).get());
    4267                 : 
    4268               0 :       animation->SetPlayState(animPlayState.list->mValue.GetIntValue());
    4269                 :     }
    4270                 : 
    4271               0 :     if (i >= animIterationCount.num) {
    4272               0 :       animation->SetIterationCount(display->mAnimations[i % animIterationCount.num].GetIterationCount());
    4273               0 :     } else if (animIterationCount.unit == eCSSUnit_Inherit) {
    4274               0 :       NS_ABORT_IF_FALSE(i < parentDisplay->mAnimationIterationCountCount,
    4275                 :                         "animIterationCount.num computed incorrectly");
    4276               0 :       NS_ABORT_IF_FALSE(!canStoreInRuleTree,
    4277                 :                         "should have made canStoreInRuleTree false above");
    4278               0 :       animation->SetIterationCount(parentDisplay->mAnimations[i].GetIterationCount());
    4279               0 :     } else if (animIterationCount.unit == eCSSUnit_Initial) {
    4280               0 :       animation->SetIterationCount(1.0f);
    4281               0 :     } else if (animIterationCount.list) {
    4282               0 :       switch(animIterationCount.list->mValue.GetUnit()) {
    4283                 :         case eCSSUnit_Enumerated:
    4284               0 :           NS_ABORT_IF_FALSE(animIterationCount.list->mValue.GetIntValue() ==
    4285                 :                               NS_STYLE_ANIMATION_ITERATION_COUNT_INFINITE,
    4286                 :                             "unexpected value");
    4287               0 :           animation->SetIterationCount(NS_IEEEPositiveInfinity());
    4288               0 :           break;
    4289                 :         case eCSSUnit_Number:
    4290                 :           animation->SetIterationCount(
    4291               0 :             animIterationCount.list->mValue.GetFloatValue());
    4292               0 :           break;
    4293                 :         default:
    4294               0 :           NS_ABORT_IF_FALSE(false,
    4295                 :                             "unexpected animation-iteration-count unit");
    4296                 :       }
    4297                 :     }
    4298                 : 
    4299               0 :     FOR_ALL_ANIMATION_PROPS(p) {
    4300               0 :       const TransitionPropInfo& info = animationPropInfo[p];
    4301               0 :       TransitionPropData& d = animationPropData[p];
    4302                 : 
    4303                 :       // if we're at the end of the list, start at the beginning and repeat
    4304                 :       // until we're out of animations to populate
    4305               0 :       if (d.list) {
    4306                 :         d.list = d.list->mNext ? d.list->mNext :
    4307               0 :           aRuleData->ValueFor(info.property)->GetListValue();
    4308                 :       }
    4309                 :     }
    4310                 :   }
    4311                 : 
    4312                 :   // opacity: factor, inherit, initial
    4313               0 :   SetFactor(*aRuleData->ValueForOpacity(), display->mOpacity, canStoreInRuleTree,
    4314               0 :             parentDisplay->mOpacity, 1.0f, SETFCT_OPACITY);
    4315                 : 
    4316                 :   // display: enum, inherit, initial
    4317               0 :   SetDiscrete(*aRuleData->ValueForDisplay(), display->mDisplay, canStoreInRuleTree,
    4318                 :               SETDSC_ENUMERATED, parentDisplay->mDisplay,
    4319               0 :               NS_STYLE_DISPLAY_INLINE, 0, 0, 0, 0);
    4320                 :   // Backup original display value for calculation of a hypothetical
    4321                 :   // box (CSS2 10.6.4/10.6.5), in addition to getting our style data right later.
    4322                 :   // See nsHTMLReflowState::CalculateHypotheticalBox
    4323               0 :   display->mOriginalDisplay = display->mDisplay;
    4324                 : 
    4325                 :   // appearance: enum, inherit, initial
    4326               0 :   SetDiscrete(*aRuleData->ValueForAppearance(),
    4327                 :               display->mAppearance, canStoreInRuleTree,
    4328                 :               SETDSC_ENUMERATED, parentDisplay->mAppearance,
    4329               0 :               NS_THEME_NONE, 0, 0, 0, 0);
    4330                 : 
    4331                 :   // binding: url, none, inherit
    4332               0 :   const nsCSSValue* bindingValue = aRuleData->ValueForBinding();
    4333               0 :   if (eCSSUnit_URL == bindingValue->GetUnit()) {
    4334               0 :     nsCSSValue::URL* url = bindingValue->GetURLStructValue();
    4335               0 :     NS_ASSERTION(url, "What's going on here?");
    4336                 : 
    4337               0 :     if (NS_LIKELY(url->GetURI())) {
    4338               0 :       display->mBinding = url;
    4339                 :     } else {
    4340               0 :       display->mBinding = nsnull;
    4341                 :     }
    4342                 :   }
    4343               0 :   else if (eCSSUnit_None == bindingValue->GetUnit() ||
    4344               0 :            eCSSUnit_Initial == bindingValue->GetUnit()) {
    4345               0 :     display->mBinding = nsnull;
    4346                 :   }
    4347               0 :   else if (eCSSUnit_Inherit == bindingValue->GetUnit()) {
    4348               0 :     canStoreInRuleTree = false;
    4349               0 :     display->mBinding = parentDisplay->mBinding;
    4350                 :   }
    4351                 : 
    4352                 :   // position: enum, inherit, initial
    4353               0 :   SetDiscrete(*aRuleData->ValueForPosition(), display->mPosition, canStoreInRuleTree,
    4354                 :               SETDSC_ENUMERATED, parentDisplay->mPosition,
    4355               0 :               NS_STYLE_POSITION_STATIC, 0, 0, 0, 0);
    4356                 : 
    4357                 :   // clear: enum, inherit, initial
    4358               0 :   SetDiscrete(*aRuleData->ValueForClear(), display->mBreakType, canStoreInRuleTree,
    4359                 :               SETDSC_ENUMERATED, parentDisplay->mBreakType,
    4360               0 :               NS_STYLE_CLEAR_NONE, 0, 0, 0, 0);
    4361                 : 
    4362                 :   // temp fix for bug 24000
    4363                 :   // Map 'auto' and 'avoid' to false, and 'always', 'left', and
    4364                 :   // 'right' to true.
    4365                 :   // "A conforming user agent may interpret the values 'left' and
    4366                 :   // 'right' as 'always'." - CSS2.1, section 13.3.1
    4367               0 :   const nsCSSValue* breakBeforeValue = aRuleData->ValueForPageBreakBefore();
    4368               0 :   if (eCSSUnit_Enumerated == breakBeforeValue->GetUnit()) {
    4369                 :     display->mBreakBefore =
    4370               0 :       (NS_STYLE_PAGE_BREAK_AVOID != breakBeforeValue->GetIntValue() &&
    4371               0 :        NS_STYLE_PAGE_BREAK_AUTO  != breakBeforeValue->GetIntValue());
    4372                 :   }
    4373               0 :   else if (eCSSUnit_Initial == breakBeforeValue->GetUnit()) {
    4374               0 :     display->mBreakBefore = false;
    4375                 :   }
    4376               0 :   else if (eCSSUnit_Inherit == breakBeforeValue->GetUnit()) {
    4377               0 :     canStoreInRuleTree = false;
    4378               0 :     display->mBreakBefore = parentDisplay->mBreakBefore;
    4379                 :   }
    4380                 : 
    4381               0 :   const nsCSSValue* breakAfterValue = aRuleData->ValueForPageBreakAfter();
    4382               0 :   if (eCSSUnit_Enumerated == breakAfterValue->GetUnit()) {
    4383                 :     display->mBreakAfter =
    4384               0 :       (NS_STYLE_PAGE_BREAK_AVOID != breakAfterValue->GetIntValue() &&
    4385               0 :        NS_STYLE_PAGE_BREAK_AUTO  != breakAfterValue->GetIntValue());
    4386                 :   }
    4387               0 :   else if (eCSSUnit_Initial == breakAfterValue->GetUnit()) {
    4388               0 :     display->mBreakAfter = false;
    4389                 :   }
    4390               0 :   else if (eCSSUnit_Inherit == breakAfterValue->GetUnit()) {
    4391               0 :     canStoreInRuleTree = false;
    4392               0 :     display->mBreakAfter = parentDisplay->mBreakAfter;
    4393                 :   }
    4394                 :   // end temp fix
    4395                 : 
    4396                 :   // float: enum, inherit, initial
    4397               0 :   SetDiscrete(*aRuleData->ValueForCssFloat(),
    4398                 :               display->mFloats, canStoreInRuleTree,
    4399                 :               SETDSC_ENUMERATED, parentDisplay->mFloats,
    4400               0 :               NS_STYLE_FLOAT_NONE, 0, 0, 0, 0);
    4401                 :   // Save mFloats in mOriginalFloats in case we need it later
    4402               0 :   display->mOriginalFloats = display->mFloats;
    4403                 : 
    4404                 :   // overflow-x: enum, inherit, initial
    4405               0 :   SetDiscrete(*aRuleData->ValueForOverflowX(),
    4406                 :               display->mOverflowX, canStoreInRuleTree,
    4407                 :               SETDSC_ENUMERATED, parentDisplay->mOverflowX,
    4408               0 :               NS_STYLE_OVERFLOW_VISIBLE, 0, 0, 0, 0);
    4409                 : 
    4410                 :   // overflow-y: enum, inherit, initial
    4411               0 :   SetDiscrete(*aRuleData->ValueForOverflowY(),
    4412                 :               display->mOverflowY, canStoreInRuleTree,
    4413                 :               SETDSC_ENUMERATED, parentDisplay->mOverflowY,
    4414               0 :               NS_STYLE_OVERFLOW_VISIBLE, 0, 0, 0, 0);
    4415                 : 
    4416                 :   // CSS3 overflow-x and overflow-y require some fixup as well in some
    4417                 :   // cases.  NS_STYLE_OVERFLOW_VISIBLE and NS_STYLE_OVERFLOW_CLIP are
    4418                 :   // meaningful only when used in both dimensions.
    4419               0 :   if (display->mOverflowX != display->mOverflowY &&
    4420                 :       (display->mOverflowX == NS_STYLE_OVERFLOW_VISIBLE ||
    4421                 :        display->mOverflowX == NS_STYLE_OVERFLOW_CLIP ||
    4422                 :        display->mOverflowY == NS_STYLE_OVERFLOW_VISIBLE ||
    4423                 :        display->mOverflowY == NS_STYLE_OVERFLOW_CLIP)) {
    4424                 :     // We can't store in the rule tree since a more specific rule might
    4425                 :     // change these conditions.
    4426               0 :     canStoreInRuleTree = false;
    4427                 : 
    4428                 :     // NS_STYLE_OVERFLOW_CLIP is a deprecated value, so if it's specified
    4429                 :     // in only one dimension, convert it to NS_STYLE_OVERFLOW_HIDDEN.
    4430               0 :     if (display->mOverflowX == NS_STYLE_OVERFLOW_CLIP)
    4431               0 :       display->mOverflowX = NS_STYLE_OVERFLOW_HIDDEN;
    4432               0 :     if (display->mOverflowY == NS_STYLE_OVERFLOW_CLIP)
    4433               0 :       display->mOverflowY = NS_STYLE_OVERFLOW_HIDDEN;
    4434                 : 
    4435                 :     // If 'visible' is specified but doesn't match the other dimension, it
    4436                 :     // turns into 'auto'.
    4437               0 :     if (display->mOverflowX == NS_STYLE_OVERFLOW_VISIBLE)
    4438               0 :       display->mOverflowX = NS_STYLE_OVERFLOW_AUTO;
    4439               0 :     if (display->mOverflowY == NS_STYLE_OVERFLOW_VISIBLE)
    4440               0 :       display->mOverflowY = NS_STYLE_OVERFLOW_AUTO;
    4441                 :   }
    4442                 : 
    4443               0 :   SetDiscrete(*aRuleData->ValueForResize(), display->mResize, canStoreInRuleTree,
    4444                 :               SETDSC_ENUMERATED, parentDisplay->mResize,
    4445               0 :               NS_STYLE_RESIZE_NONE, 0, 0, 0, 0);
    4446                 : 
    4447                 :   // clip property: length, auto, inherit
    4448               0 :   const nsCSSValue* clipValue = aRuleData->ValueForClip();
    4449               0 :   switch (clipValue->GetUnit()) {
    4450                 :   case eCSSUnit_Inherit:
    4451               0 :     canStoreInRuleTree = false;
    4452               0 :     display->mClipFlags = parentDisplay->mClipFlags;
    4453               0 :     display->mClip = parentDisplay->mClip;
    4454               0 :     break;
    4455                 : 
    4456                 :   case eCSSUnit_Initial:
    4457                 :   case eCSSUnit_Auto:
    4458               0 :     display->mClipFlags = NS_STYLE_CLIP_AUTO;
    4459               0 :     display->mClip.SetRect(0,0,0,0);
    4460               0 :     break;
    4461                 : 
    4462                 :   case eCSSUnit_Null:
    4463               0 :     break;
    4464                 : 
    4465                 :   case eCSSUnit_Rect: {
    4466               0 :     const nsCSSRect& clipRect = clipValue->GetRectValue();
    4467                 : 
    4468               0 :     display->mClipFlags = NS_STYLE_CLIP_RECT;
    4469                 : 
    4470               0 :     if (clipRect.mTop.GetUnit() == eCSSUnit_Auto) {
    4471               0 :       display->mClip.y = 0;
    4472               0 :       display->mClipFlags |= NS_STYLE_CLIP_TOP_AUTO;
    4473                 :     }
    4474               0 :     else if (clipRect.mTop.IsLengthUnit()) {
    4475                 :       display->mClip.y = CalcLength(clipRect.mTop, aContext,
    4476               0 :                                     mPresContext, canStoreInRuleTree);
    4477                 :     }
    4478                 : 
    4479               0 :     if (clipRect.mBottom.GetUnit() == eCSSUnit_Auto) {
    4480                 :       // Setting to NS_MAXSIZE for the 'auto' case ensures that
    4481                 :       // the clip rect is nonempty. It is important that mClip be
    4482                 :       // nonempty if the actual clip rect could be nonempty.
    4483               0 :       display->mClip.height = NS_MAXSIZE;
    4484               0 :       display->mClipFlags |= NS_STYLE_CLIP_BOTTOM_AUTO;
    4485                 :     }
    4486               0 :     else if (clipRect.mBottom.IsLengthUnit()) {
    4487                 :       display->mClip.height = CalcLength(clipRect.mBottom, aContext,
    4488               0 :                                          mPresContext, canStoreInRuleTree) -
    4489               0 :                               display->mClip.y;
    4490                 :     }
    4491                 : 
    4492               0 :     if (clipRect.mLeft.GetUnit() == eCSSUnit_Auto) {
    4493               0 :       display->mClip.x = 0;
    4494               0 :       display->mClipFlags |= NS_STYLE_CLIP_LEFT_AUTO;
    4495                 :     }
    4496               0 :     else if (clipRect.mLeft.IsLengthUnit()) {
    4497                 :       display->mClip.x = CalcLength(clipRect.mLeft, aContext,
    4498               0 :                                     mPresContext, canStoreInRuleTree);
    4499                 :     }
    4500                 : 
    4501               0 :     if (clipRect.mRight.GetUnit() == eCSSUnit_Auto) {
    4502                 :       // Setting to NS_MAXSIZE for the 'auto' case ensures that
    4503                 :       // the clip rect is nonempty. It is important that mClip be
    4504                 :       // nonempty if the actual clip rect could be nonempty.
    4505               0 :       display->mClip.width = NS_MAXSIZE;
    4506               0 :       display->mClipFlags |= NS_STYLE_CLIP_RIGHT_AUTO;
    4507                 :     }
    4508               0 :     else if (clipRect.mRight.IsLengthUnit()) {
    4509                 :       display->mClip.width = CalcLength(clipRect.mRight, aContext,
    4510               0 :                                         mPresContext, canStoreInRuleTree) -
    4511               0 :                              display->mClip.x;
    4512                 :     }
    4513               0 :     break;
    4514                 :   }
    4515                 : 
    4516                 :   default:
    4517               0 :     NS_ABORT_IF_FALSE(false, "unrecognized clip unit");
    4518                 :   }
    4519                 : 
    4520               0 :   if (display->mDisplay != NS_STYLE_DISPLAY_NONE) {
    4521                 :     // CSS2 9.7 specifies display type corrections dealing with 'float'
    4522                 :     // and 'position'.  Since generated content can't be floated or
    4523                 :     // positioned, we can deal with it here.
    4524                 : 
    4525               0 :     if (nsCSSPseudoElements::firstLetter == aContext->GetPseudo()) {
    4526                 :       // a non-floating first-letter must be inline
    4527                 :       // XXX this fix can go away once bug 103189 is fixed correctly
    4528                 :       // Note that we reset mOriginalDisplay to enforce the invariant that it equals mDisplay if we're not positioned or floating.
    4529               0 :       display->mOriginalDisplay = display->mDisplay = NS_STYLE_DISPLAY_INLINE;
    4530                 : 
    4531                 :       // We can't cache the data in the rule tree since if a more specific
    4532                 :       // rule has 'float: left' we'll end up with the wrong 'display'
    4533                 :       // property.
    4534               0 :       canStoreInRuleTree = false;
    4535                 :     }
    4536                 : 
    4537               0 :     if (display->IsAbsolutelyPositioned()) {
    4538                 :       // 1) if position is 'absolute' or 'fixed' then display must be
    4539                 :       // block-level and float must be 'none'
    4540               0 :       EnsureBlockDisplay(display->mDisplay);
    4541               0 :       display->mFloats = NS_STYLE_FLOAT_NONE;
    4542                 : 
    4543                 :       // Note that it's OK to cache this struct in the ruletree
    4544                 :       // because it's fine as-is for any style context that points to
    4545                 :       // it directly, and any use of it as aStartStruct (e.g. if a
    4546                 :       // more specific rule sets "position: static") will use
    4547                 :       // mOriginalDisplay and mOriginalFloats, which we have carefully
    4548                 :       // not changed.
    4549               0 :     } else if (display->mFloats != NS_STYLE_FLOAT_NONE) {
    4550                 :       // 2) if float is not none, and display is not none, then we must
    4551                 :       // set a block-level 'display' type per CSS2.1 section 9.7.
    4552               0 :       EnsureBlockDisplay(display->mDisplay);
    4553                 : 
    4554                 :       // Note that it's OK to cache this struct in the ruletree
    4555                 :       // because it's fine as-is for any style context that points to
    4556                 :       // it directly, and any use of it as aStartStruct (e.g. if a
    4557                 :       // more specific rule sets "float: none") will use
    4558                 :       // mOriginalDisplay, which we have carefully not changed.
    4559                 :     }
    4560                 : 
    4561                 :   }
    4562                 : 
    4563                 :   /* Convert the nsCSSValueList into an nsTArray<nsTransformFunction *>. */
    4564               0 :   const nsCSSValue* transformValue = aRuleData->ValueForTransform();
    4565               0 :   switch (transformValue->GetUnit()) {
    4566                 :   case eCSSUnit_Null:
    4567               0 :     break;
    4568                 : 
    4569                 :   case eCSSUnit_Initial:
    4570                 :   case eCSSUnit_None:
    4571               0 :     display->mSpecifiedTransform = nsnull;
    4572               0 :     break;
    4573                 : 
    4574                 :   case eCSSUnit_Inherit:
    4575               0 :     display->mSpecifiedTransform = parentDisplay->mSpecifiedTransform;
    4576               0 :     canStoreInRuleTree = false;
    4577               0 :     break;
    4578                 : 
    4579                 :   case eCSSUnit_List:
    4580                 :   case eCSSUnit_ListDep: {
    4581               0 :     const nsCSSValueList* head = transformValue->GetListValue();
    4582                 :     // can get a _None in here from transform animation
    4583               0 :     if (head->mValue.GetUnit() == eCSSUnit_None) {
    4584               0 :       NS_ABORT_IF_FALSE(head->mNext == nsnull, "none must be alone");
    4585               0 :       display->mSpecifiedTransform = nsnull;
    4586                 :     } else {
    4587               0 :       display->mSpecifiedTransform = head; // weak pointer, owned by rule
    4588                 :     }
    4589               0 :     break;
    4590                 :   }
    4591                 : 
    4592                 :   default:
    4593               0 :     NS_ABORT_IF_FALSE(false, "unrecognized transform unit");
    4594                 :   }
    4595                 : 
    4596                 :   /* Convert -moz-transform-origin. */
    4597                 :   const nsCSSValue* transformOriginValue =
    4598               0 :     aRuleData->ValueForTransformOrigin();
    4599               0 :   if (transformOriginValue->GetUnit() != eCSSUnit_Null) {
    4600                 :     const nsCSSValue& valX =
    4601               0 :       transformOriginValue->GetUnit() == eCSSUnit_Triplet ?
    4602               0 :         transformOriginValue->GetTripletValue().mXValue : *transformOriginValue;
    4603                 :     const nsCSSValue& valY =
    4604               0 :       transformOriginValue->GetUnit() == eCSSUnit_Triplet ?
    4605               0 :         transformOriginValue->GetTripletValue().mYValue : *transformOriginValue;
    4606                 :     const nsCSSValue& valZ =
    4607               0 :       transformOriginValue->GetUnit() == eCSSUnit_Triplet ?
    4608               0 :         transformOriginValue->GetTripletValue().mZValue : *transformOriginValue;
    4609                 : 
    4610                 :     mozilla::DebugOnly<bool> cX =
    4611                 :        SetCoord(valX, display->mTransformOrigin[0],
    4612                 :                 parentDisplay->mTransformOrigin[0],
    4613                 :                 SETCOORD_LPH | SETCOORD_INITIAL_HALF |
    4614                 :                   SETCOORD_BOX_POSITION | SETCOORD_STORE_CALC,
    4615               0 :                 aContext, mPresContext, canStoreInRuleTree);
    4616                 : 
    4617                 :      mozilla::DebugOnly<bool> cY =
    4618                 :        SetCoord(valY, display->mTransformOrigin[1],
    4619                 :                 parentDisplay->mTransformOrigin[1],
    4620                 :                 SETCOORD_LPH | SETCOORD_INITIAL_HALF |
    4621                 :                   SETCOORD_BOX_POSITION | SETCOORD_STORE_CALC,
    4622               0 :                 aContext, mPresContext, canStoreInRuleTree);
    4623                 : 
    4624               0 :      if (valZ.GetUnit() == eCSSUnit_Null) {
    4625                 :        // Null for the z component means a 0 translation, not
    4626                 :        // unspecified, as we have already checked the triplet
    4627                 :        // value for Null.
    4628               0 :        display->mTransformOrigin[2].SetCoordValue(0);
    4629                 :      } else {
    4630                 :        mozilla::DebugOnly<bool> cZ =
    4631                 :          SetCoord(valZ, display->mTransformOrigin[2],
    4632                 :                   parentDisplay->mTransformOrigin[2],
    4633                 :                   SETCOORD_LH | SETCOORD_INITIAL_ZERO | SETCOORD_STORE_CALC,
    4634               0 :                   aContext, mPresContext, canStoreInRuleTree);
    4635               0 :        NS_ABORT_IF_FALSE(cY == cZ, "changed one but not the other");
    4636                 :      }
    4637               0 :      NS_ABORT_IF_FALSE(cX == cY, "changed one but not the other");
    4638               0 :      NS_ASSERTION(cX, "Malformed -moz-transform-origin parse!");
    4639                 :   }
    4640                 : 
    4641                 :   const nsCSSValue* perspectiveOriginValue =
    4642               0 :     aRuleData->ValueForPerspectiveOrigin();
    4643               0 :   if (perspectiveOriginValue->GetUnit() != eCSSUnit_Null) {
    4644                 :     mozilla::DebugOnly<bool> result =
    4645                 :       SetPairCoords(*perspectiveOriginValue,
    4646                 :                     display->mPerspectiveOrigin[0],
    4647                 :                     display->mPerspectiveOrigin[1],
    4648                 :                     parentDisplay->mPerspectiveOrigin[0],
    4649                 :                     parentDisplay->mPerspectiveOrigin[1],
    4650                 :                     SETCOORD_LPH | SETCOORD_INITIAL_HALF |
    4651                 :                     SETCOORD_BOX_POSITION | SETCOORD_STORE_CALC,
    4652               0 :                     aContext, mPresContext, canStoreInRuleTree);
    4653               0 :     NS_ASSERTION(result, "Malformed -moz-perspective-origin parse!");
    4654                 :   }
    4655                 : 
    4656               0 :   SetCoord(*aRuleData->ValueForPerspective(), 
    4657                 :            display->mChildPerspective, parentDisplay->mChildPerspective,
    4658                 :            SETCOORD_LAH | SETCOORD_INITIAL_ZERO | SETCOORD_NONE,
    4659               0 :            aContext, mPresContext, canStoreInRuleTree);
    4660                 : 
    4661               0 :   SetDiscrete(*aRuleData->ValueForBackfaceVisibility(),
    4662                 :               display->mBackfaceVisibility, canStoreInRuleTree,
    4663                 :               SETDSC_ENUMERATED, parentDisplay->mBackfaceVisibility,
    4664               0 :               NS_STYLE_BACKFACE_VISIBILITY_VISIBLE, 0, 0, 0, 0);
    4665                 : 
    4666                 :   // transform-style: enum, inherit, initial
    4667               0 :   SetDiscrete(*aRuleData->ValueForTransformStyle(),
    4668                 :               display->mTransformStyle, canStoreInRuleTree,
    4669                 :               SETDSC_ENUMERATED, parentDisplay->mTransformStyle,
    4670               0 :               NS_STYLE_TRANSFORM_STYLE_FLAT, 0, 0, 0, 0);
    4671                 : 
    4672                 :   // orient: enum, inherit, initial
    4673               0 :   SetDiscrete(*aRuleData->ValueForOrient(),
    4674                 :               display->mOrient, canStoreInRuleTree,
    4675                 :               SETDSC_ENUMERATED, parentDisplay->mOrient,
    4676               0 :               NS_STYLE_ORIENT_HORIZONTAL, 0, 0, 0, 0);
    4677                 : 
    4678               0 :   COMPUTE_END_RESET(Display, display)
    4679                 : }
    4680                 : 
    4681                 : const void*
    4682               0 : nsRuleNode::ComputeVisibilityData(void* aStartStruct,
    4683                 :                                   const nsRuleData* aRuleData,
    4684                 :                                   nsStyleContext* aContext,
    4685                 :                                   nsRuleNode* aHighestNode,
    4686                 :                                   const RuleDetail aRuleDetail,
    4687                 :                                   const bool aCanStoreInRuleTree)
    4688                 : {
    4689               0 :   COMPUTE_START_INHERITED(Visibility, (mPresContext),
    4690                 :                           visibility, parentVisibility)
    4691                 : 
    4692                 :   // IMPORTANT: No properties in this struct have lengths in them.  We
    4693                 :   // depend on this since CalcLengthWith can call GetStyleVisibility()
    4694                 :   // to get the language for resolving fonts!
    4695                 : 
    4696                 :   // direction: enum, inherit, initial
    4697               0 :   SetDiscrete(*aRuleData->ValueForDirection(), visibility->mDirection,
    4698                 :               canStoreInRuleTree,
    4699                 :               SETDSC_ENUMERATED, parentVisibility->mDirection,
    4700               0 :               (GET_BIDI_OPTION_DIRECTION(mPresContext->GetBidi())
    4701                 :                == IBMBIDI_TEXTDIRECTION_RTL)
    4702                 :               ? NS_STYLE_DIRECTION_RTL : NS_STYLE_DIRECTION_LTR,
    4703               0 :               0, 0, 0, 0);
    4704                 : 
    4705                 :   // visibility: enum, inherit, initial
    4706               0 :   SetDiscrete(*aRuleData->ValueForVisibility(), visibility->mVisible,
    4707                 :               canStoreInRuleTree,
    4708                 :               SETDSC_ENUMERATED, parentVisibility->mVisible,
    4709               0 :               NS_STYLE_VISIBILITY_VISIBLE, 0, 0, 0, 0);
    4710                 : 
    4711                 :   // pointer-events: enum, inherit, initial
    4712               0 :   SetDiscrete(*aRuleData->ValueForPointerEvents(), visibility->mPointerEvents,
    4713                 :               canStoreInRuleTree,
    4714                 :               SETDSC_ENUMERATED, parentVisibility->mPointerEvents,
    4715               0 :               NS_STYLE_POINTER_EVENTS_AUTO, 0, 0, 0, 0);
    4716                 : 
    4717               0 :   COMPUTE_END_INHERITED(Visibility, visibility)
    4718                 : }
    4719                 : 
    4720                 : const void*
    4721               0 : nsRuleNode::ComputeColorData(void* aStartStruct,
    4722                 :                              const nsRuleData* aRuleData,
    4723                 :                              nsStyleContext* aContext,
    4724                 :                              nsRuleNode* aHighestNode,
    4725                 :                              const RuleDetail aRuleDetail,
    4726                 :                              const bool aCanStoreInRuleTree)
    4727                 : {
    4728               0 :   COMPUTE_START_INHERITED(Color, (mPresContext), color, parentColor)
    4729                 : 
    4730                 :   // color: color, string, inherit
    4731                 :   // Special case for currentColor.  According to CSS3, setting color to 'currentColor'
    4732                 :   // should behave as if it is inherited
    4733               0 :   const nsCSSValue* colorValue = aRuleData->ValueForColor();
    4734               0 :   if (colorValue->GetUnit() == eCSSUnit_EnumColor &&
    4735               0 :       colorValue->GetIntValue() == NS_COLOR_CURRENTCOLOR) {
    4736               0 :     color->mColor = parentColor->mColor;
    4737               0 :     canStoreInRuleTree = false;
    4738                 :   }
    4739               0 :   else if (colorValue->GetUnit() == eCSSUnit_Initial) {
    4740               0 :     color->mColor = mPresContext->DefaultColor();
    4741                 :   }
    4742                 :   else {
    4743                 :     SetColor(*colorValue, parentColor->mColor, mPresContext, aContext,
    4744               0 :              color->mColor, canStoreInRuleTree);
    4745                 :   }
    4746                 : 
    4747               0 :   COMPUTE_END_INHERITED(Color, color)
    4748                 : }
    4749                 : 
    4750                 : // information about how to compute values for background-* properties
    4751                 : template <class SpecifiedValueItem>
    4752                 : struct InitialInheritLocationFor {
    4753                 : };
    4754                 : 
    4755                 : template <>
    4756                 : struct InitialInheritLocationFor<nsCSSValueList> {
    4757                 :   static nsCSSValue nsCSSValueList::* Location() {
    4758                 :     return &nsCSSValueList::mValue;
    4759                 :   }
    4760                 : };
    4761                 : 
    4762                 : template <>
    4763                 : struct InitialInheritLocationFor<nsCSSValuePairList> {
    4764                 :   static nsCSSValue nsCSSValuePairList::* Location() {
    4765                 :     return &nsCSSValuePairList::mXValue;
    4766                 :   }
    4767                 : };
    4768                 : 
    4769                 : template <class SpecifiedValueItem, class ComputedValueItem>
    4770                 : struct BackgroundItemComputer {
    4771                 : };
    4772                 : 
    4773                 : template <>
    4774                 : struct BackgroundItemComputer<nsCSSValueList, PRUint8>
    4775                 : {
    4776               0 :   static void ComputeValue(nsStyleContext* aStyleContext,
    4777                 :                            const nsCSSValueList* aSpecifiedValue,
    4778                 :                            PRUint8& aComputedValue,
    4779                 :                            bool& aCanStoreInRuleTree)
    4780                 :   {
    4781                 :     SetDiscrete(aSpecifiedValue->mValue, aComputedValue, aCanStoreInRuleTree,
    4782               0 :                 SETDSC_ENUMERATED, PRUint8(0), 0, 0, 0, 0, 0);
    4783               0 :   }
    4784                 : };
    4785                 : 
    4786                 : template <>
    4787                 : struct BackgroundItemComputer<nsCSSValuePairList, nsStyleBackground::Repeat>
    4788                 : {
    4789               0 :   static void ComputeValue(nsStyleContext* aStyleContext,
    4790                 :                            const nsCSSValuePairList* aSpecifiedValue,
    4791                 :                            nsStyleBackground::Repeat& aComputedValue,
    4792                 :                            bool& aCanStoreInRuleTree)
    4793                 :   {
    4794               0 :     NS_ASSERTION(aSpecifiedValue->mXValue.GetUnit() == eCSSUnit_Enumerated &&
    4795                 :                  (aSpecifiedValue->mYValue.GetUnit() == eCSSUnit_Enumerated ||
    4796                 :                   aSpecifiedValue->mYValue.GetUnit() == eCSSUnit_Null),
    4797                 :                  "Invalid unit");
    4798                 :     
    4799               0 :     bool hasContraction = true;
    4800               0 :     PRUint8 value = aSpecifiedValue->mXValue.GetIntValue();
    4801               0 :     switch (value) {
    4802                 :     case NS_STYLE_BG_REPEAT_REPEAT_X:
    4803               0 :       aComputedValue.mXRepeat = NS_STYLE_BG_REPEAT_REPEAT;
    4804               0 :       aComputedValue.mYRepeat = NS_STYLE_BG_REPEAT_NO_REPEAT;
    4805               0 :       break;
    4806                 :     case NS_STYLE_BG_REPEAT_REPEAT_Y:
    4807               0 :       aComputedValue.mXRepeat = NS_STYLE_BG_REPEAT_NO_REPEAT;
    4808               0 :       aComputedValue.mYRepeat = NS_STYLE_BG_REPEAT_REPEAT;
    4809               0 :       break;
    4810                 :     default:
    4811               0 :       aComputedValue.mXRepeat = value;
    4812               0 :       hasContraction = false;
    4813               0 :       break;
    4814                 :     }
    4815                 :     
    4816               0 :     if (hasContraction) {
    4817               0 :       NS_ASSERTION(aSpecifiedValue->mYValue.GetUnit() == eCSSUnit_Null,
    4818                 :                    "Invalid unit.");
    4819               0 :       return;
    4820                 :     }
    4821                 :     
    4822               0 :     switch (aSpecifiedValue->mYValue.GetUnit()) {
    4823                 :     case eCSSUnit_Null:
    4824               0 :       aComputedValue.mYRepeat = aComputedValue.mXRepeat;
    4825               0 :       break;
    4826                 :     case eCSSUnit_Enumerated:
    4827               0 :       value = aSpecifiedValue->mYValue.GetIntValue();
    4828               0 :       NS_ASSERTION(value == NS_STYLE_BG_REPEAT_NO_REPEAT ||
    4829                 :                    value == NS_STYLE_BG_REPEAT_REPEAT, "Unexpected value");
    4830               0 :       aComputedValue.mYRepeat = value;
    4831               0 :       break;
    4832                 :     default:
    4833               0 :       NS_NOTREACHED("Unexpected CSS value");
    4834               0 :       break;
    4835                 :     }
    4836                 :   }
    4837                 : };
    4838                 : 
    4839                 : template <>
    4840                 : struct BackgroundItemComputer<nsCSSValueList, nsStyleImage>
    4841                 : {
    4842               0 :   static void ComputeValue(nsStyleContext* aStyleContext,
    4843                 :                            const nsCSSValueList* aSpecifiedValue,
    4844                 :                            nsStyleImage& aComputedValue,
    4845                 :                            bool& aCanStoreInRuleTree)
    4846                 :   {
    4847                 :     SetStyleImage(aStyleContext, aSpecifiedValue->mValue, aComputedValue,
    4848               0 :                   aCanStoreInRuleTree);
    4849               0 :   }
    4850                 : };
    4851                 : 
    4852                 : /* Helper function for
    4853                 :  * BackgroundItemComputer<nsCSSValue, nsStyleBackground::Position>
    4854                 :  * It computes a single PositionCoord from an nsCSSValue object
    4855                 :  * (contained in a list).
    4856                 :  */
    4857                 : typedef nsStyleBackground::Position::PositionCoord PositionCoord;
    4858                 : static void
    4859               0 : ComputeBackgroundPositionCoord(nsStyleContext* aStyleContext,
    4860                 :                                const nsCSSValue& aEdge,
    4861                 :                                const nsCSSValue& aOffset,
    4862                 :                                PositionCoord* aResult,
    4863                 :                                bool& aCanStoreInRuleTree)
    4864                 : {
    4865               0 :   if (eCSSUnit_Percent == aOffset.GetUnit()) {
    4866               0 :     aResult->mLength = 0;
    4867               0 :     aResult->mPercent = aOffset.GetPercentValue();
    4868               0 :     aResult->mHasPercent = true;
    4869               0 :   } else if (aOffset.IsLengthUnit()) {
    4870                 :     aResult->mLength = CalcLength(aOffset, aStyleContext,
    4871                 :                                   aStyleContext->PresContext(),
    4872               0 :                                   aCanStoreInRuleTree);
    4873               0 :     aResult->mPercent = 0.0f;
    4874               0 :     aResult->mHasPercent = false;
    4875               0 :   } else if (aOffset.IsCalcUnit()) {
    4876                 :     LengthPercentPairCalcOps ops(aStyleContext,
    4877                 :                                  aStyleContext->PresContext(),
    4878               0 :                                  aCanStoreInRuleTree);
    4879               0 :     nsRuleNode::ComputedCalc vals = ComputeCalc(aOffset, ops);
    4880               0 :     aResult->mLength = vals.mLength;
    4881               0 :     aResult->mPercent = vals.mPercent;
    4882               0 :     aResult->mHasPercent = ops.mHasPercent;
    4883                 :   } else {
    4884               0 :     aResult->mLength = 0;
    4885               0 :     aResult->mPercent = 0.0f;
    4886               0 :     aResult->mHasPercent = false;
    4887               0 :     NS_ASSERTION(aOffset.GetUnit() == eCSSUnit_Null, "unexpected unit");
    4888                 :   }
    4889                 : 
    4890               0 :   if (eCSSUnit_Enumerated == aEdge.GetUnit()) {
    4891                 :     int sign;
    4892               0 :     if (aEdge.GetIntValue() & (NS_STYLE_BG_POSITION_BOTTOM |
    4893                 :                                NS_STYLE_BG_POSITION_RIGHT)) {
    4894               0 :       sign = -1;
    4895                 :     } else {
    4896               0 :       sign = 1;
    4897                 :     }
    4898               0 :     aResult->mPercent = GetFloatFromBoxPosition(aEdge.GetIntValue()) +
    4899               0 :                         sign * aResult->mPercent;
    4900               0 :     aResult->mLength = sign * aResult->mLength;
    4901               0 :     aResult->mHasPercent = true;
    4902                 :   } else {
    4903               0 :     NS_ASSERTION(eCSSUnit_Null == aEdge.GetUnit(), "unexpected unit");
    4904                 :   }
    4905               0 : }
    4906                 : 
    4907                 : template <>
    4908                 : struct BackgroundItemComputer<nsCSSValueList, nsStyleBackground::Position>
    4909                 : {
    4910               0 :   static void ComputeValue(nsStyleContext* aStyleContext,
    4911                 :                            const nsCSSValueList* aSpecifiedValue,
    4912                 :                            nsStyleBackground::Position& aComputedValue,
    4913                 :                            bool& aCanStoreInRuleTree)
    4914                 :   {
    4915               0 :     NS_ASSERTION(aSpecifiedValue->mValue.GetUnit() == eCSSUnit_Array, "bg-position not an array");
    4916                 : 
    4917                 :     nsRefPtr<nsCSSValue::Array> bgPositionArray =
    4918               0 :                                   aSpecifiedValue->mValue.GetArrayValue();
    4919               0 :     const nsCSSValue &xEdge   = bgPositionArray->Item(0);
    4920               0 :     const nsCSSValue &xOffset = bgPositionArray->Item(1);
    4921               0 :     const nsCSSValue &yEdge   = bgPositionArray->Item(2);
    4922               0 :     const nsCSSValue &yOffset = bgPositionArray->Item(3);
    4923                 : 
    4924               0 :     NS_ASSERTION((eCSSUnit_Enumerated == xEdge.GetUnit()  ||
    4925                 :                   eCSSUnit_Null       == xEdge.GetUnit()) &&
    4926                 :                  (eCSSUnit_Enumerated == yEdge.GetUnit()  ||
    4927                 :                   eCSSUnit_Null       == yEdge.GetUnit()) &&
    4928                 :                   eCSSUnit_Enumerated != xOffset.GetUnit()  &&
    4929                 :                   eCSSUnit_Enumerated != yOffset.GetUnit(),
    4930                 :                   "Invalid background position");
    4931                 : 
    4932                 :     ComputeBackgroundPositionCoord(aStyleContext, xEdge, xOffset,
    4933                 :                                    &aComputedValue.mXPosition,
    4934               0 :                                    aCanStoreInRuleTree);
    4935                 : 
    4936                 :     ComputeBackgroundPositionCoord(aStyleContext, yEdge, yOffset,
    4937                 :                                    &aComputedValue.mYPosition,
    4938               0 :                                    aCanStoreInRuleTree);
    4939               0 :   }
    4940                 : };
    4941                 : 
    4942                 : 
    4943                 : struct BackgroundSizeAxis {
    4944                 :   nsCSSValue nsCSSValuePairList::* specified;
    4945                 :   nsStyleBackground::Size::Dimension nsStyleBackground::Size::* result;
    4946                 :   PRUint8 nsStyleBackground::Size::* type;
    4947                 : };
    4948                 : 
    4949                 : static const BackgroundSizeAxis gBGSizeAxes[] = {
    4950                 :   { &nsCSSValuePairList::mXValue,
    4951                 :     &nsStyleBackground::Size::mWidth,
    4952                 :     &nsStyleBackground::Size::mWidthType },
    4953                 :   { &nsCSSValuePairList::mYValue,
    4954                 :     &nsStyleBackground::Size::mHeight,
    4955                 :     &nsStyleBackground::Size::mHeightType }
    4956                 : };
    4957                 : 
    4958                 : template <>
    4959                 : struct BackgroundItemComputer<nsCSSValuePairList, nsStyleBackground::Size>
    4960                 : {
    4961               0 :   static void ComputeValue(nsStyleContext* aStyleContext,
    4962                 :                            const nsCSSValuePairList* aSpecifiedValue,
    4963                 :                            nsStyleBackground::Size& aComputedValue,
    4964                 :                            bool& aCanStoreInRuleTree)
    4965                 :   {
    4966               0 :     nsStyleBackground::Size &size = aComputedValue;
    4967               0 :     for (const BackgroundSizeAxis *axis = gBGSizeAxes,
    4968               0 :                         *axis_end = ArrayEnd(gBGSizeAxes);
    4969                 :          axis < axis_end; ++axis) {
    4970               0 :       const nsCSSValue &specified = aSpecifiedValue->*(axis->specified);
    4971               0 :       if (eCSSUnit_Auto == specified.GetUnit()) {
    4972               0 :         size.*(axis->type) = nsStyleBackground::Size::eAuto;
    4973                 :       }
    4974               0 :       else if (eCSSUnit_Enumerated == specified.GetUnit()) {
    4975                 :         MOZ_STATIC_ASSERT(nsStyleBackground::Size::eContain ==
    4976                 :                           NS_STYLE_BG_SIZE_CONTAIN &&
    4977                 :                           nsStyleBackground::Size::eCover ==
    4978                 :                           NS_STYLE_BG_SIZE_COVER,
    4979                 :                           "background size constants out of sync");
    4980               0 :         NS_ABORT_IF_FALSE(specified.GetIntValue() == NS_STYLE_BG_SIZE_CONTAIN ||
    4981                 :                           specified.GetIntValue() == NS_STYLE_BG_SIZE_COVER,
    4982                 :                           "invalid enumerated value for size coordinate");
    4983               0 :         size.*(axis->type) = specified.GetIntValue();
    4984                 :       }
    4985               0 :       else if (eCSSUnit_Null == specified.GetUnit()) {
    4986               0 :         NS_ABORT_IF_FALSE(axis == gBGSizeAxes + 1,
    4987                 :                           "null allowed only as height value, and only "
    4988                 :                           "for contain/cover/initial/inherit");
    4989                 : #ifdef DEBUG
    4990                 :         {
    4991               0 :           const nsCSSValue &widthValue = aSpecifiedValue->mXValue;
    4992               0 :           NS_ABORT_IF_FALSE(widthValue.GetUnit() != eCSSUnit_Inherit &&
    4993                 :                             widthValue.GetUnit() != eCSSUnit_Initial,
    4994                 :                             "initial/inherit should already have been handled");
    4995               0 :           NS_ABORT_IF_FALSE(widthValue.GetUnit() == eCSSUnit_Enumerated &&
    4996                 :                             (widthValue.GetIntValue() == NS_STYLE_BG_SIZE_CONTAIN ||
    4997                 :                              widthValue.GetIntValue() == NS_STYLE_BG_SIZE_COVER),
    4998                 :                             "null height value not corresponding to allowable "
    4999                 :                             "non-null width value");
    5000                 :         }
    5001                 : #endif
    5002               0 :         size.*(axis->type) = size.mWidthType;
    5003                 :       }
    5004               0 :       else if (eCSSUnit_Percent == specified.GetUnit()) {
    5005               0 :         (size.*(axis->result)).mLength = 0;
    5006               0 :         (size.*(axis->result)).mPercent = specified.GetPercentValue();
    5007               0 :         (size.*(axis->result)).mHasPercent = true;
    5008               0 :         size.*(axis->type) = nsStyleBackground::Size::eLengthPercentage;
    5009                 :       }
    5010               0 :       else if (specified.IsLengthUnit()) {
    5011                 :         (size.*(axis->result)).mLength =
    5012                 :           CalcLength(specified, aStyleContext, aStyleContext->PresContext(),
    5013               0 :                      aCanStoreInRuleTree);
    5014               0 :         (size.*(axis->result)).mPercent = 0.0f;
    5015               0 :         (size.*(axis->result)).mHasPercent = false;
    5016               0 :         size.*(axis->type) = nsStyleBackground::Size::eLengthPercentage;
    5017                 :       } else {
    5018               0 :         NS_ABORT_IF_FALSE(specified.IsCalcUnit(), "unexpected unit");
    5019                 :         LengthPercentPairCalcOps ops(aStyleContext,
    5020                 :                                      aStyleContext->PresContext(),
    5021               0 :                                      aCanStoreInRuleTree);
    5022               0 :         nsRuleNode::ComputedCalc vals = ComputeCalc(specified, ops);
    5023               0 :         (size.*(axis->result)).mLength = vals.mLength;
    5024               0 :         (size.*(axis->result)).mPercent = vals.mPercent;
    5025               0 :         (size.*(axis->result)).mHasPercent = ops.mHasPercent;
    5026               0 :         size.*(axis->type) = nsStyleBackground::Size::eLengthPercentage;
    5027                 :       }
    5028                 :     }
    5029                 : 
    5030               0 :     NS_ABORT_IF_FALSE(size.mWidthType < nsStyleBackground::Size::eDimensionType_COUNT,
    5031                 :                       "bad width type");
    5032               0 :     NS_ABORT_IF_FALSE(size.mHeightType < nsStyleBackground::Size::eDimensionType_COUNT,
    5033                 :                       "bad height type");
    5034               0 :     NS_ABORT_IF_FALSE((size.mWidthType != nsStyleBackground::Size::eContain &&
    5035                 :                        size.mWidthType != nsStyleBackground::Size::eCover) ||
    5036                 :                       size.mWidthType == size.mHeightType,
    5037                 :                       "contain/cover apply to both dimensions or to neither");
    5038               0 :   }
    5039                 : };
    5040                 : 
    5041                 : template <class ComputedValueItem>
    5042                 : static void
    5043               0 : SetBackgroundList(nsStyleContext* aStyleContext,
    5044                 :                   const nsCSSValue& aValue,
    5045                 :                   nsAutoTArray< nsStyleBackground::Layer, 1> &aLayers,
    5046                 :                   const nsAutoTArray<nsStyleBackground::Layer, 1> &aParentLayers,
    5047                 :                   ComputedValueItem nsStyleBackground::Layer::* aResultLocation,
    5048                 :                   ComputedValueItem aInitialValue,
    5049                 :                   PRUint32 aParentItemCount,
    5050                 :                   PRUint32& aItemCount,
    5051                 :                   PRUint32& aMaxItemCount,
    5052                 :                   bool& aRebuild,
    5053                 :                   bool& aCanStoreInRuleTree)
    5054                 : {
    5055               0 :   switch (aValue.GetUnit()) {
    5056                 :   case eCSSUnit_Null:
    5057               0 :     break;
    5058                 : 
    5059                 :   case eCSSUnit_Inherit:
    5060               0 :     aRebuild = true;
    5061               0 :     aCanStoreInRuleTree = false;
    5062               0 :     if (!aLayers.EnsureLengthAtLeast(aParentItemCount)) {
    5063               0 :       NS_WARNING("out of memory");
    5064               0 :       aParentItemCount = aLayers.Length();
    5065                 :     }
    5066               0 :     aItemCount = aParentItemCount;
    5067               0 :     for (PRUint32 i = 0; i < aParentItemCount; ++i) {
    5068               0 :       aLayers[i].*aResultLocation = aParentLayers[i].*aResultLocation;
    5069                 :     }
    5070               0 :     break;
    5071                 : 
    5072                 :   case eCSSUnit_Initial:
    5073               0 :     aRebuild = true;
    5074               0 :     aItemCount = 1;
    5075               0 :     aLayers[0].*aResultLocation = aInitialValue;
    5076               0 :     break;
    5077                 : 
    5078                 :   case eCSSUnit_List:
    5079                 :   case eCSSUnit_ListDep: {
    5080               0 :     aRebuild = true;
    5081               0 :     aItemCount = 0;
    5082               0 :     const nsCSSValueList* item = aValue.GetListValue();
    5083               0 :     do {
    5084               0 :       NS_ASSERTION(item->mValue.GetUnit() != eCSSUnit_Null &&
    5085                 :                    item->mValue.GetUnit() != eCSSUnit_Inherit &&
    5086                 :                    item->mValue.GetUnit() != eCSSUnit_Initial,
    5087                 :                    "unexpected unit");
    5088               0 :       ++aItemCount;
    5089               0 :       if (!aLayers.EnsureLengthAtLeast(aItemCount)) {
    5090               0 :         NS_WARNING("out of memory");
    5091               0 :         --aItemCount;
    5092               0 :         break;
    5093                 :       }
    5094               0 :       BackgroundItemComputer<nsCSSValueList, ComputedValueItem>
    5095                 :         ::ComputeValue(aStyleContext, item,
    5096                 :                        aLayers[aItemCount-1].*aResultLocation,
    5097                 :                        aCanStoreInRuleTree);
    5098               0 :       item = item->mNext;
    5099                 :     } while (item);
    5100               0 :     break;
    5101                 :   }
    5102                 : 
    5103                 :   default:
    5104               0 :     NS_ABORT_IF_FALSE(false,
    5105                 :                       nsPrintfCString(32, "unexpected unit %d",
    5106                 :                                       aValue.GetUnit()).get());
    5107                 :   }
    5108                 : 
    5109               0 :   if (aItemCount > aMaxItemCount)
    5110               0 :     aMaxItemCount = aItemCount;
    5111               0 : }
    5112                 : 
    5113                 : template <class ComputedValueItem>
    5114                 : static void
    5115               0 : SetBackgroundPairList(nsStyleContext* aStyleContext,
    5116                 :                       const nsCSSValue& aValue,
    5117                 :                       nsAutoTArray< nsStyleBackground::Layer, 1> &aLayers,
    5118                 :                       const nsAutoTArray<nsStyleBackground::Layer, 1>
    5119                 :                                                                  &aParentLayers,
    5120                 :                       ComputedValueItem nsStyleBackground::Layer::*
    5121                 :                                                                 aResultLocation,
    5122                 :                       ComputedValueItem aInitialValue,
    5123                 :                       PRUint32 aParentItemCount,
    5124                 :                       PRUint32& aItemCount,
    5125                 :                       PRUint32& aMaxItemCount,
    5126                 :                       bool& aRebuild,
    5127                 :                       bool& aCanStoreInRuleTree)
    5128                 : {
    5129               0 :   switch (aValue.GetUnit()) {
    5130                 :   case eCSSUnit_Null:
    5131               0 :     break;
    5132                 : 
    5133                 :   case eCSSUnit_Inherit:
    5134               0 :     aRebuild = true;
    5135               0 :     aCanStoreInRuleTree = false;
    5136               0 :     if (!aLayers.EnsureLengthAtLeast(aParentItemCount)) {
    5137               0 :       NS_WARNING("out of memory");
    5138               0 :       aParentItemCount = aLayers.Length();
    5139                 :     }
    5140               0 :     aItemCount = aParentItemCount;
    5141               0 :     for (PRUint32 i = 0; i < aParentItemCount; ++i) {
    5142               0 :       aLayers[i].*aResultLocation = aParentLayers[i].*aResultLocation;
    5143                 :     }
    5144               0 :     break;
    5145                 : 
    5146                 :   case eCSSUnit_Initial:
    5147               0 :     aRebuild = true;
    5148               0 :     aItemCount = 1;
    5149               0 :     aLayers[0].*aResultLocation = aInitialValue;
    5150               0 :     break;
    5151                 : 
    5152                 :   case eCSSUnit_PairList:
    5153                 :   case eCSSUnit_PairListDep: {
    5154               0 :     aRebuild = true;
    5155               0 :     aItemCount = 0;
    5156               0 :     const nsCSSValuePairList* item = aValue.GetPairListValue();
    5157               0 :     do {
    5158               0 :       NS_ASSERTION(item->mXValue.GetUnit() != eCSSUnit_Inherit &&
    5159                 :                    item->mXValue.GetUnit() != eCSSUnit_Initial &&
    5160                 :                    item->mYValue.GetUnit() != eCSSUnit_Inherit &&
    5161                 :                    item->mYValue.GetUnit() != eCSSUnit_Initial,
    5162                 :                    "unexpected unit");
    5163               0 :       ++aItemCount;
    5164               0 :       if (!aLayers.EnsureLengthAtLeast(aItemCount)) {
    5165               0 :         NS_WARNING("out of memory");
    5166               0 :         --aItemCount;
    5167               0 :         break;
    5168                 :       }
    5169               0 :       BackgroundItemComputer<nsCSSValuePairList, ComputedValueItem>
    5170                 :         ::ComputeValue(aStyleContext, item,
    5171                 :                        aLayers[aItemCount-1].*aResultLocation,
    5172                 :                        aCanStoreInRuleTree);
    5173               0 :       item = item->mNext;
    5174                 :     } while (item);
    5175               0 :     break;
    5176                 :   }
    5177                 : 
    5178                 :   default:
    5179               0 :     NS_ABORT_IF_FALSE(false,
    5180                 :                       nsPrintfCString(32, "unexpected unit %d",
    5181                 :                                       aValue.GetUnit()).get());
    5182                 :   }
    5183                 : 
    5184               0 :   if (aItemCount > aMaxItemCount)
    5185               0 :     aMaxItemCount = aItemCount;
    5186               0 : }
    5187                 : 
    5188                 : template <class ComputedValueItem>
    5189                 : static void
    5190               0 : FillBackgroundList(nsAutoTArray< nsStyleBackground::Layer, 1> &aLayers,
    5191                 :     ComputedValueItem nsStyleBackground::Layer::* aResultLocation,
    5192                 :     PRUint32 aItemCount, PRUint32 aFillCount)
    5193                 : {
    5194               0 :   NS_PRECONDITION(aFillCount <= aLayers.Length(), "unexpected array length");
    5195               0 :   for (PRUint32 sourceLayer = 0, destLayer = aItemCount;
    5196                 :        destLayer < aFillCount;
    5197                 :        ++sourceLayer, ++destLayer) {
    5198               0 :     aLayers[destLayer].*aResultLocation =
    5199                 :       aLayers[sourceLayer].*aResultLocation;
    5200                 :   }
    5201               0 : }
    5202                 : 
    5203                 : const void*
    5204               0 : nsRuleNode::ComputeBackgroundData(void* aStartStruct,
    5205                 :                                   const nsRuleData* aRuleData,
    5206                 :                                   nsStyleContext* aContext,
    5207                 :                                   nsRuleNode* aHighestNode,
    5208                 :                                   const RuleDetail aRuleDetail,
    5209                 :                                   const bool aCanStoreInRuleTree)
    5210                 : {
    5211               0 :   COMPUTE_START_RESET(Background, (), bg, parentBG)
    5212                 : 
    5213                 :   // background-color: color, string, inherit
    5214               0 :   const nsCSSValue* backColorValue = aRuleData->ValueForBackgroundColor();
    5215               0 :   if (eCSSUnit_Initial == backColorValue->GetUnit()) {
    5216               0 :     bg->mBackgroundColor = NS_RGBA(0, 0, 0, 0);
    5217               0 :   } else if (!SetColor(*backColorValue, parentBG->mBackgroundColor,
    5218                 :                        mPresContext, aContext, bg->mBackgroundColor,
    5219               0 :                        canStoreInRuleTree)) {
    5220               0 :     NS_ASSERTION(eCSSUnit_Null == backColorValue->GetUnit(),
    5221                 :                  "unexpected color unit");
    5222                 :   }
    5223                 : 
    5224               0 :   PRUint32 maxItemCount = 1;
    5225               0 :   bool rebuild = false;
    5226                 : 
    5227                 :   // background-image: url (stored as image), none, inherit [list]
    5228               0 :   nsStyleImage initialImage;
    5229               0 :   SetBackgroundList(aContext, *aRuleData->ValueForBackgroundImage(),
    5230                 :                     bg->mLayers,
    5231                 :                     parentBG->mLayers, &nsStyleBackground::Layer::mImage,
    5232                 :                     initialImage, parentBG->mImageCount, bg->mImageCount,
    5233               0 :                     maxItemCount, rebuild, canStoreInRuleTree);
    5234                 : 
    5235                 :   // background-repeat: enum, inherit, initial [pair list]
    5236               0 :   nsStyleBackground::Repeat initialRepeat;
    5237               0 :   initialRepeat.SetInitialValues();
    5238               0 :   SetBackgroundPairList(aContext, *aRuleData->ValueForBackgroundRepeat(),
    5239                 :                         bg->mLayers,
    5240                 :                         parentBG->mLayers, &nsStyleBackground::Layer::mRepeat,
    5241                 :                         initialRepeat, parentBG->mRepeatCount,
    5242                 :                         bg->mRepeatCount, maxItemCount, rebuild, 
    5243               0 :                         canStoreInRuleTree);
    5244                 : 
    5245                 :   // background-attachment: enum, inherit, initial [list]
    5246               0 :   SetBackgroundList(aContext, *aRuleData->ValueForBackgroundAttachment(),
    5247                 :                     bg->mLayers, parentBG->mLayers,
    5248                 :                     &nsStyleBackground::Layer::mAttachment,
    5249                 :                     PRUint8(NS_STYLE_BG_ATTACHMENT_SCROLL),
    5250                 :                     parentBG->mAttachmentCount,
    5251                 :                     bg->mAttachmentCount, maxItemCount, rebuild,
    5252               0 :                     canStoreInRuleTree);
    5253                 : 
    5254                 :   // background-clip: enum, inherit, initial [list]
    5255               0 :   SetBackgroundList(aContext, *aRuleData->ValueForBackgroundClip(),
    5256                 :                     bg->mLayers,
    5257                 :                     parentBG->mLayers, &nsStyleBackground::Layer::mClip,
    5258                 :                     PRUint8(NS_STYLE_BG_CLIP_BORDER), parentBG->mClipCount,
    5259               0 :                     bg->mClipCount, maxItemCount, rebuild, canStoreInRuleTree);
    5260                 : 
    5261                 :   // background-inline-policy: enum, inherit, initial
    5262               0 :   SetDiscrete(*aRuleData->ValueForBackgroundInlinePolicy(),
    5263                 :               bg->mBackgroundInlinePolicy,
    5264                 :               canStoreInRuleTree, SETDSC_ENUMERATED,
    5265                 :               parentBG->mBackgroundInlinePolicy,
    5266               0 :               NS_STYLE_BG_INLINE_POLICY_CONTINUOUS, 0, 0, 0, 0);
    5267                 : 
    5268                 :   // background-origin: enum, inherit, initial [list]
    5269               0 :   SetBackgroundList(aContext, *aRuleData->ValueForBackgroundOrigin(),
    5270                 :                     bg->mLayers,
    5271                 :                     parentBG->mLayers, &nsStyleBackground::Layer::mOrigin,
    5272                 :                     PRUint8(NS_STYLE_BG_ORIGIN_PADDING), parentBG->mOriginCount,
    5273                 :                     bg->mOriginCount, maxItemCount, rebuild,
    5274               0 :                     canStoreInRuleTree);
    5275                 : 
    5276                 :   // background-position: enum, length, percent (flags), inherit [pair list]
    5277               0 :   nsStyleBackground::Position initialPosition;
    5278               0 :   initialPosition.SetInitialValues();
    5279               0 :   SetBackgroundList(aContext, *aRuleData->ValueForBackgroundPosition(),
    5280                 :                     bg->mLayers,
    5281                 :                     parentBG->mLayers, &nsStyleBackground::Layer::mPosition,
    5282                 :                     initialPosition, parentBG->mPositionCount,
    5283                 :                     bg->mPositionCount, maxItemCount, rebuild,
    5284               0 :                     canStoreInRuleTree);
    5285                 : 
    5286                 :   // background-size: enum, length, auto, inherit, initial [pair list]
    5287               0 :   nsStyleBackground::Size initialSize;
    5288               0 :   initialSize.SetInitialValues();
    5289               0 :   SetBackgroundPairList(aContext, *aRuleData->ValueForBackgroundSize(),
    5290                 :                         bg->mLayers,
    5291                 :                         parentBG->mLayers, &nsStyleBackground::Layer::mSize,
    5292                 :                         initialSize, parentBG->mSizeCount,
    5293                 :                         bg->mSizeCount, maxItemCount, rebuild,
    5294               0 :                         canStoreInRuleTree);
    5295                 : 
    5296               0 :   if (rebuild) {
    5297                 :     // Delete any extra items.  We need to keep layers in which any
    5298                 :     // property was specified.
    5299               0 :     bg->mLayers.TruncateLength(maxItemCount);
    5300                 : 
    5301               0 :     PRUint32 fillCount = bg->mImageCount;
    5302                 :     FillBackgroundList(bg->mLayers, &nsStyleBackground::Layer::mImage,
    5303               0 :                        bg->mImageCount, fillCount);
    5304                 :     FillBackgroundList(bg->mLayers, &nsStyleBackground::Layer::mRepeat,
    5305               0 :                        bg->mRepeatCount, fillCount);
    5306                 :     FillBackgroundList(bg->mLayers, &nsStyleBackground::Layer::mAttachment,
    5307               0 :                        bg->mAttachmentCount, fillCount);
    5308                 :     FillBackgroundList(bg->mLayers, &nsStyleBackground::Layer::mClip,
    5309               0 :                        bg->mClipCount, fillCount);
    5310                 :     FillBackgroundList(bg->mLayers, &nsStyleBackground::Layer::mOrigin,
    5311               0 :                        bg->mOriginCount, fillCount);
    5312                 :     FillBackgroundList(bg->mLayers, &nsStyleBackground::Layer::mPosition,
    5313               0 :                        bg->mPositionCount, fillCount);
    5314                 :     FillBackgroundList(bg->mLayers, &nsStyleBackground::Layer::mSize,
    5315               0 :                        bg->mSizeCount, fillCount);
    5316                 :   }
    5317                 : 
    5318                 :   // Now that the dust has settled, register the images with the document
    5319               0 :   for (PRUint32 i = 0; i < bg->mImageCount; ++i)
    5320               0 :     bg->mLayers[i].TrackImages(aContext->PresContext());
    5321                 : 
    5322               0 :   COMPUTE_END_RESET(Background, bg)
    5323                 : }
    5324                 : 
    5325                 : const void*
    5326               0 : nsRuleNode::ComputeMarginData(void* aStartStruct,
    5327                 :                               const nsRuleData* aRuleData,
    5328                 :                               nsStyleContext* aContext,
    5329                 :                               nsRuleNode* aHighestNode,
    5330                 :                               const RuleDetail aRuleDetail,
    5331                 :                               const bool aCanStoreInRuleTree)
    5332                 : {
    5333               0 :   COMPUTE_START_RESET(Margin, (), margin, parentMargin)
    5334                 : 
    5335                 :   // margin: length, percent, auto, inherit
    5336               0 :   nsStyleCoord  coord;
    5337               0 :   nsCSSRect ourMargin;
    5338               0 :   ourMargin.mTop = *aRuleData->ValueForMarginTop();
    5339               0 :   ourMargin.mRight = *aRuleData->ValueForMarginRightValue();
    5340               0 :   ourMargin.mBottom = *aRuleData->ValueForMarginBottom();
    5341               0 :   ourMargin.mLeft = *aRuleData->ValueForMarginLeftValue();
    5342                 :   AdjustLogicalBoxProp(aContext,
    5343               0 :                        *aRuleData->ValueForMarginLeftLTRSource(),
    5344               0 :                        *aRuleData->ValueForMarginLeftRTLSource(),
    5345               0 :                        *aRuleData->ValueForMarginStartValue(),
    5346               0 :                        *aRuleData->ValueForMarginEndValue(),
    5347               0 :                        NS_SIDE_LEFT, ourMargin, canStoreInRuleTree);
    5348                 :   AdjustLogicalBoxProp(aContext,
    5349               0 :                        *aRuleData->ValueForMarginRightLTRSource(),
    5350               0 :                        *aRuleData->ValueForMarginRightRTLSource(),
    5351               0 :                        *aRuleData->ValueForMarginEndValue(),
    5352               0 :                        *aRuleData->ValueForMarginStartValue(),
    5353               0 :                        NS_SIDE_RIGHT, ourMargin, canStoreInRuleTree);
    5354               0 :   NS_FOR_CSS_SIDES(side) {
    5355               0 :     nsStyleCoord parentCoord = parentMargin->mMargin.Get(side);
    5356               0 :     if (SetCoord(ourMargin.*(nsCSSRect::sides[side]),
    5357                 :                  coord, parentCoord,
    5358                 :                  SETCOORD_LPAH | SETCOORD_INITIAL_ZERO | SETCOORD_STORE_CALC,
    5359               0 :                  aContext, mPresContext, canStoreInRuleTree)) {
    5360               0 :       margin->mMargin.Set(side, coord);
    5361                 :     }
    5362                 :   }
    5363                 : 
    5364               0 :   margin->RecalcData();
    5365               0 :   COMPUTE_END_RESET(Margin, margin)
    5366                 : }
    5367                 : 
    5368                 : static void
    5369               0 : SetBorderImageRect(const nsCSSValue& aValue,
    5370                 :                    /** outparam */ nsCSSRect& aRect)
    5371                 : {
    5372               0 :   switch (aValue.GetUnit()) {
    5373                 :   case eCSSUnit_Null:
    5374               0 :     aRect.Reset();
    5375               0 :     break;
    5376                 :   case eCSSUnit_Rect:
    5377               0 :     aRect = aValue.GetRectValue();
    5378               0 :     break;
    5379                 :   case eCSSUnit_Inherit:
    5380                 :   case eCSSUnit_Initial:
    5381               0 :     aRect.SetAllSidesTo(aValue);
    5382               0 :     break;
    5383                 :   default:
    5384               0 :     NS_ASSERTION(false, "Unexpected border image value for rect.");
    5385                 :   }
    5386               0 : }
    5387                 : 
    5388                 : static void
    5389               0 : SetBorderImagePair(const nsCSSValue& aValue,
    5390                 :                    /** outparam */ nsCSSValuePair& aPair)
    5391                 : {
    5392               0 :   switch (aValue.GetUnit()) {
    5393                 :   case eCSSUnit_Null:
    5394               0 :     aPair.Reset();
    5395               0 :     break;
    5396                 :   case eCSSUnit_Pair:
    5397               0 :     aPair = aValue.GetPairValue();
    5398               0 :     break;
    5399                 :   case eCSSUnit_Inherit:
    5400                 :   case eCSSUnit_Initial:
    5401               0 :     aPair.SetBothValuesTo(aValue);
    5402               0 :     break;
    5403                 :   default:
    5404               0 :     NS_ASSERTION(false, "Unexpected border image value for pair.");
    5405                 :   }
    5406               0 : }
    5407                 : 
    5408                 : static void
    5409               0 : SetBorderImageSlice(const nsCSSValue& aValue,
    5410                 :                     /** outparam */ nsCSSValue& aSlice,
    5411                 :                     /** outparam */ nsCSSValue& aFill)
    5412                 : {
    5413                 :   const nsCSSValueList* valueList;
    5414               0 :   switch (aValue.GetUnit()) {
    5415                 :   case eCSSUnit_Null:
    5416               0 :     aSlice.Reset();
    5417               0 :     aFill.Reset();
    5418               0 :     break;
    5419                 :   case eCSSUnit_List:
    5420                 :     // Get slice dimensions.
    5421               0 :     valueList = aValue.GetListValue();
    5422               0 :     aSlice = valueList->mValue;
    5423                 : 
    5424                 :     // Get "fill" keyword.
    5425               0 :     valueList = valueList->mNext;
    5426               0 :     if (valueList) {
    5427               0 :       aFill = valueList->mValue;
    5428                 :     } else {
    5429               0 :       aFill.SetInitialValue();
    5430                 :     }
    5431               0 :     break;
    5432                 :   case eCSSUnit_Inherit:
    5433                 :   case eCSSUnit_Initial:
    5434               0 :     aSlice = aValue;
    5435               0 :     aFill = aValue;
    5436               0 :     break;
    5437                 :   default:
    5438               0 :     NS_ASSERTION(false, "Unexpected border image value for pair.");
    5439                 :   }
    5440               0 : }
    5441                 : 
    5442                 : const void*
    5443               0 : nsRuleNode::ComputeBorderData(void* aStartStruct,
    5444                 :                               const nsRuleData* aRuleData,
    5445                 :                               nsStyleContext* aContext,
    5446                 :                               nsRuleNode* aHighestNode,
    5447                 :                               const RuleDetail aRuleDetail,
    5448                 :                               const bool aCanStoreInRuleTree)
    5449                 : {
    5450               0 :   COMPUTE_START_RESET(Border, (mPresContext), border, parentBorder)
    5451                 : 
    5452                 :   // box-shadow: none, list, inherit, initial
    5453               0 :   const nsCSSValue* boxShadowValue = aRuleData->ValueForBoxShadow();
    5454               0 :   switch (boxShadowValue->GetUnit()) {
    5455                 :   case eCSSUnit_Null:
    5456               0 :     break;
    5457                 : 
    5458                 :   case eCSSUnit_Initial:
    5459                 :   case eCSSUnit_None:
    5460               0 :     border->mBoxShadow = nsnull;
    5461               0 :     break;
    5462                 : 
    5463                 :   case eCSSUnit_Inherit:
    5464               0 :     border->mBoxShadow = parentBorder->mBoxShadow;
    5465               0 :     canStoreInRuleTree = false;
    5466               0 :     break;
    5467                 : 
    5468                 :   case eCSSUnit_List:
    5469                 :   case eCSSUnit_ListDep:
    5470                 :     border->mBoxShadow = GetShadowData(boxShadowValue->GetListValue(),
    5471               0 :                                        aContext, true, canStoreInRuleTree);
    5472               0 :     break;
    5473                 : 
    5474                 :   default:
    5475               0 :     NS_ABORT_IF_FALSE(false,
    5476                 :                       nsPrintfCString(64, "unrecognized shadow unit %d",
    5477                 :                                       boxShadowValue->GetUnit()).get());
    5478                 :   }
    5479                 : 
    5480                 :   // border-width, border-*-width: length, enum, inherit
    5481               0 :   nsStyleCoord  coord;
    5482               0 :   nsCSSRect ourBorderWidth;
    5483               0 :   ourBorderWidth.mTop = *aRuleData->ValueForBorderTopWidth();
    5484               0 :   ourBorderWidth.mRight = *aRuleData->ValueForBorderRightWidthValue();
    5485               0 :   ourBorderWidth.mBottom = *aRuleData->ValueForBorderBottomWidth();
    5486               0 :   ourBorderWidth.mLeft = *aRuleData->ValueForBorderLeftWidthValue();
    5487                 :   AdjustLogicalBoxProp(aContext,
    5488               0 :                        *aRuleData->ValueForBorderLeftWidthLTRSource(),
    5489               0 :                        *aRuleData->ValueForBorderLeftWidthRTLSource(),
    5490               0 :                        *aRuleData->ValueForBorderStartWidthValue(),
    5491               0 :                        *aRuleData->ValueForBorderEndWidthValue(),
    5492               0 :                        NS_SIDE_LEFT, ourBorderWidth, canStoreInRuleTree);
    5493                 :   AdjustLogicalBoxProp(aContext,
    5494               0 :                        *aRuleData->ValueForBorderRightWidthLTRSource(),
    5495               0 :                        *aRuleData->ValueForBorderRightWidthRTLSource(),
    5496               0 :                        *aRuleData->ValueForBorderEndWidthValue(),
    5497               0 :                        *aRuleData->ValueForBorderStartWidthValue(),
    5498               0 :                        NS_SIDE_RIGHT, ourBorderWidth, canStoreInRuleTree);
    5499                 :   { // scope for compilers with broken |for| loop scoping
    5500               0 :     NS_FOR_CSS_SIDES(side) {
    5501               0 :       const nsCSSValue &value = ourBorderWidth.*(nsCSSRect::sides[side]);
    5502               0 :       NS_ASSERTION(eCSSUnit_Percent != value.GetUnit(),
    5503                 :                    "Percentage borders not implemented yet "
    5504                 :                    "If implementing, make sure to fix all consumers of "
    5505                 :                    "nsStyleBorder, the IsPercentageAwareChild method, "
    5506                 :                    "the nsAbsoluteContainingBlock::FrameDependsOnContainer "
    5507                 :                    "method, the "
    5508                 :                    "nsLineLayout::IsPercentageAwareReplacedElement method "
    5509                 :                    "and probably some other places");
    5510               0 :       if (eCSSUnit_Enumerated == value.GetUnit()) {
    5511               0 :         NS_ASSERTION(value.GetIntValue() == NS_STYLE_BORDER_WIDTH_THIN ||
    5512                 :                      value.GetIntValue() == NS_STYLE_BORDER_WIDTH_MEDIUM ||
    5513                 :                      value.GetIntValue() == NS_STYLE_BORDER_WIDTH_THICK,
    5514                 :                      "Unexpected enum value");
    5515                 :         border->SetBorderWidth(side,
    5516               0 :                                (mPresContext->GetBorderWidthTable())[value.GetIntValue()]);
    5517                 :       }
    5518                 :       // OK to pass bad aParentCoord since we're not passing SETCOORD_INHERIT
    5519               0 :       else if (SetCoord(value, coord, nsStyleCoord(),
    5520                 :                         SETCOORD_LENGTH | SETCOORD_CALC_LENGTH_ONLY,
    5521               0 :                         aContext, mPresContext, canStoreInRuleTree)) {
    5522               0 :         NS_ASSERTION(coord.GetUnit() == eStyleUnit_Coord, "unexpected unit");
    5523                 :         // clamp negative calc() to 0.
    5524               0 :         border->SetBorderWidth(side, NS_MAX(coord.GetCoordValue(), 0));
    5525                 :       }
    5526               0 :       else if (eCSSUnit_Inherit == value.GetUnit()) {
    5527               0 :         canStoreInRuleTree = false;
    5528                 :         border->SetBorderWidth(side,
    5529               0 :                                parentBorder->GetComputedBorder().Side(side));
    5530                 :       }
    5531               0 :       else if (eCSSUnit_Initial == value.GetUnit()) {
    5532                 :         border->SetBorderWidth(side,
    5533               0 :           (mPresContext->GetBorderWidthTable())[NS_STYLE_BORDER_WIDTH_MEDIUM]);
    5534                 :       }
    5535                 :       else {
    5536               0 :         NS_ASSERTION(eCSSUnit_Null == value.GetUnit(),
    5537                 :                      "missing case handling border width");
    5538                 :       }
    5539                 :     }
    5540                 :   }
    5541                 : 
    5542                 :   // border-style, border-*-style: enum, inherit
    5543               0 :   nsCSSRect ourBorderStyle;
    5544               0 :   ourBorderStyle.mTop = *aRuleData->ValueForBorderTopStyle();
    5545               0 :   ourBorderStyle.mRight = *aRuleData->ValueForBorderRightStyleValue();
    5546               0 :   ourBorderStyle.mBottom = *aRuleData->ValueForBorderBottomStyle();
    5547               0 :   ourBorderStyle.mLeft = *aRuleData->ValueForBorderLeftStyleValue();
    5548                 :   AdjustLogicalBoxProp(aContext,
    5549               0 :                        *aRuleData->ValueForBorderLeftStyleLTRSource(),
    5550               0 :                        *aRuleData->ValueForBorderLeftStyleRTLSource(),
    5551               0 :                        *aRuleData->ValueForBorderStartStyleValue(),
    5552               0 :                        *aRuleData->ValueForBorderEndStyleValue(),
    5553               0 :                        NS_SIDE_LEFT, ourBorderStyle, canStoreInRuleTree);
    5554                 :   AdjustLogicalBoxProp(aContext,
    5555               0 :                        *aRuleData->ValueForBorderRightStyleLTRSource(),
    5556               0 :                        *aRuleData->ValueForBorderRightStyleRTLSource(),
    5557               0 :                        *aRuleData->ValueForBorderEndStyleValue(),
    5558               0 :                        *aRuleData->ValueForBorderStartStyleValue(),
    5559               0 :                        NS_SIDE_RIGHT, ourBorderStyle, canStoreInRuleTree);
    5560                 :   { // scope for compilers with broken |for| loop scoping
    5561               0 :     NS_FOR_CSS_SIDES(side) {
    5562               0 :       const nsCSSValue &value = ourBorderStyle.*(nsCSSRect::sides[side]);
    5563               0 :       nsCSSUnit unit = value.GetUnit();
    5564               0 :       NS_ABORT_IF_FALSE(eCSSUnit_None != unit,
    5565                 :                         "'none' should be handled as enumerated value");
    5566               0 :       if (eCSSUnit_Enumerated == unit) {
    5567               0 :         border->SetBorderStyle(side, value.GetIntValue());
    5568                 :       }
    5569               0 :       else if (eCSSUnit_Initial == unit) {
    5570               0 :         border->SetBorderStyle(side, NS_STYLE_BORDER_STYLE_NONE);
    5571                 :       }
    5572               0 :       else if (eCSSUnit_Inherit == unit) {
    5573               0 :         canStoreInRuleTree = false;
    5574               0 :         border->SetBorderStyle(side, parentBorder->GetBorderStyle(side));
    5575                 :       }
    5576                 :     }
    5577                 :   }
    5578                 : 
    5579                 :   // -moz-border-*-colors: color, string, enum, none, inherit/initial
    5580                 :   nscolor borderColor;
    5581               0 :   nscolor unused = NS_RGB(0,0,0);
    5582                 : 
    5583                 :   static const nsCSSProperty borderColorsProps[] = {
    5584                 :     eCSSProperty_border_top_colors,
    5585                 :     eCSSProperty_border_right_colors,
    5586                 :     eCSSProperty_border_bottom_colors,
    5587                 :     eCSSProperty_border_left_colors
    5588                 :   };
    5589                 : 
    5590               0 :   NS_FOR_CSS_SIDES(side) {
    5591               0 :     const nsCSSValue& value = *aRuleData->ValueFor(borderColorsProps[side]);
    5592               0 :     switch (value.GetUnit()) {
    5593                 :     case eCSSUnit_Null:
    5594               0 :       break;
    5595                 : 
    5596                 :     case eCSSUnit_Initial:
    5597                 :     case eCSSUnit_None:
    5598               0 :       border->ClearBorderColors(side);
    5599               0 :       break;
    5600                 : 
    5601                 :     case eCSSUnit_Inherit: {
    5602               0 :       canStoreInRuleTree = false;
    5603                 :       nsBorderColors *parentColors;
    5604               0 :       parentBorder->GetCompositeColors(side, &parentColors);
    5605               0 :       if (parentColors) {
    5606               0 :         border->EnsureBorderColors();
    5607               0 :         border->ClearBorderColors(side);
    5608               0 :         border->mBorderColors[side] = parentColors->Clone();
    5609                 :       } else {
    5610               0 :         border->ClearBorderColors(side);
    5611                 :       }
    5612               0 :       break;
    5613                 :     }
    5614                 : 
    5615                 :     case eCSSUnit_List:
    5616                 :     case eCSSUnit_ListDep: {
    5617                 :       // Some composite border color information has been specified for this
    5618                 :       // border side.
    5619               0 :       border->EnsureBorderColors();
    5620               0 :       border->ClearBorderColors(side);
    5621               0 :       const nsCSSValueList* list = value.GetListValue();
    5622               0 :       while (list) {
    5623               0 :         if (SetColor(list->mValue, unused, mPresContext,
    5624               0 :                      aContext, borderColor, canStoreInRuleTree))
    5625               0 :           border->AppendBorderColor(side, borderColor);
    5626                 :         else {
    5627               0 :           NS_NOTREACHED("unexpected item in -moz-border-*-colors list");
    5628                 :         }
    5629               0 :         list = list->mNext;
    5630                 :       }
    5631               0 :       break;
    5632                 :     }
    5633                 : 
    5634                 :     default:
    5635               0 :       NS_ABORT_IF_FALSE(false, "unrecognized border color unit");
    5636                 :     }
    5637                 :   }
    5638                 : 
    5639                 :   // border-color, border-*-color: color, string, enum, inherit
    5640                 :   bool foreground;
    5641               0 :   nsCSSRect ourBorderColor;
    5642               0 :   ourBorderColor.mTop = *aRuleData->ValueForBorderTopColor();
    5643               0 :   ourBorderColor.mRight = *aRuleData->ValueForBorderRightColorValue();
    5644               0 :   ourBorderColor.mBottom = *aRuleData->ValueForBorderBottomColor();
    5645               0 :   ourBorderColor.mLeft = *aRuleData->ValueForBorderLeftColorValue();
    5646                 :   AdjustLogicalBoxProp(aContext,
    5647               0 :                        *aRuleData->ValueForBorderLeftColorLTRSource(),
    5648               0 :                        *aRuleData->ValueForBorderLeftColorRTLSource(),
    5649               0 :                        *aRuleData->ValueForBorderStartColorValue(),
    5650               0 :                        *aRuleData->ValueForBorderEndColorValue(),
    5651               0 :                        NS_SIDE_LEFT, ourBorderColor, canStoreInRuleTree);
    5652                 :   AdjustLogicalBoxProp(aContext,
    5653               0 :                        *aRuleData->ValueForBorderRightColorLTRSource(),
    5654               0 :                        *aRuleData->ValueForBorderRightColorRTLSource(),
    5655               0 :                        *aRuleData->ValueForBorderEndColorValue(),
    5656               0 :                        *aRuleData->ValueForBorderStartColorValue(),
    5657               0 :                        NS_SIDE_RIGHT, ourBorderColor, canStoreInRuleTree);
    5658                 :   { // scope for compilers with broken |for| loop scoping
    5659               0 :     NS_FOR_CSS_SIDES(side) {
    5660               0 :       const nsCSSValue &value = ourBorderColor.*(nsCSSRect::sides[side]);
    5661               0 :       if (eCSSUnit_Inherit == value.GetUnit()) {
    5662               0 :         canStoreInRuleTree = false;
    5663               0 :         if (parentContext) {
    5664               0 :           parentBorder->GetBorderColor(side, borderColor, foreground);
    5665               0 :           if (foreground) {
    5666                 :             // We want to inherit the color from the parent, not use the
    5667                 :             // color on the element where this chunk of style data will be
    5668                 :             // used.  We can ensure that the data for the parent are fully
    5669                 :             // computed (unlike for the element where this will be used, for
    5670                 :             // which the color could be specified on a more specific rule).
    5671               0 :             border->SetBorderColor(side, parentContext->GetStyleColor()->mColor);
    5672                 :           } else
    5673               0 :             border->SetBorderColor(side, borderColor);
    5674                 :         } else {
    5675                 :           // We're the root
    5676               0 :           border->SetBorderToForeground(side);
    5677                 :         }
    5678                 :       }
    5679               0 :       else if (SetColor(value, unused, mPresContext, aContext, borderColor,
    5680               0 :                         canStoreInRuleTree)) {
    5681               0 :         border->SetBorderColor(side, borderColor);
    5682                 :       }
    5683               0 :       else if (eCSSUnit_Enumerated == value.GetUnit()) {
    5684               0 :         switch (value.GetIntValue()) {
    5685                 :           case NS_STYLE_COLOR_MOZ_USE_TEXT_COLOR:
    5686               0 :             border->SetBorderToForeground(side);
    5687               0 :             break;
    5688                 :           default:
    5689               0 :             NS_NOTREACHED("Unexpected enumerated color");
    5690               0 :             break;
    5691                 :         }
    5692                 :       }
    5693               0 :       else if (eCSSUnit_Initial == value.GetUnit()) {
    5694               0 :         border->SetBorderToForeground(side);
    5695                 :       }
    5696                 :     }
    5697                 :   }
    5698                 : 
    5699                 :   // border-radius: length, percent, inherit
    5700                 :   {
    5701                 :     const nsCSSProperty* subprops =
    5702               0 :       nsCSSProps::SubpropertyEntryFor(eCSSProperty_border_radius);
    5703               0 :     NS_FOR_CSS_FULL_CORNERS(corner) {
    5704               0 :       int cx = NS_FULL_TO_HALF_CORNER(corner, false);
    5705               0 :       int cy = NS_FULL_TO_HALF_CORNER(corner, true);
    5706               0 :       const nsCSSValue& radius = *aRuleData->ValueFor(subprops[corner]);
    5707               0 :       nsStyleCoord parentX = parentBorder->mBorderRadius.Get(cx);
    5708               0 :       nsStyleCoord parentY = parentBorder->mBorderRadius.Get(cy);
    5709               0 :       nsStyleCoord coordX, coordY;
    5710                 : 
    5711               0 :       if (SetPairCoords(radius, coordX, coordY, parentX, parentY,
    5712                 :                         SETCOORD_LPH | SETCOORD_INITIAL_ZERO |
    5713                 :                           SETCOORD_STORE_CALC,
    5714               0 :                         aContext, mPresContext, canStoreInRuleTree)) {
    5715               0 :         border->mBorderRadius.Set(cx, coordX);
    5716               0 :         border->mBorderRadius.Set(cy, coordY);
    5717                 :       }
    5718                 :     }
    5719                 :   }
    5720                 : 
    5721                 :   // float-edge: enum, inherit, initial
    5722               0 :   SetDiscrete(*aRuleData->ValueForFloatEdge(),
    5723                 :               border->mFloatEdge, canStoreInRuleTree,
    5724                 :               SETDSC_ENUMERATED, parentBorder->mFloatEdge,
    5725               0 :               NS_STYLE_FLOAT_EDGE_CONTENT, 0, 0, 0, 0);
    5726                 : 
    5727                 :   // border-image-source
    5728               0 :   const nsCSSValue* borderImageSource = aRuleData->ValueForBorderImageSource();
    5729               0 :   if (borderImageSource->GetUnit() == eCSSUnit_Image) {
    5730               0 :     NS_SET_IMAGE_REQUEST(border->SetBorderImage, aContext,
    5731                 :                          borderImageSource->GetImageValue());
    5732               0 :   } else if (borderImageSource->GetUnit() == eCSSUnit_Inherit) {
    5733               0 :     canStoreInRuleTree = false;
    5734               0 :     NS_SET_IMAGE_REQUEST(border->SetBorderImage, aContext,
    5735                 :                          parentBorder->GetBorderImage());
    5736               0 :   } else if (borderImageSource->GetUnit() == eCSSUnit_Initial ||
    5737               0 :              borderImageSource->GetUnit() == eCSSUnit_None) {
    5738               0 :     border->SetBorderImage(nsnull);
    5739                 :   }
    5740                 : 
    5741               0 :   nsCSSValue borderImageSliceValue;
    5742               0 :   nsCSSValue borderImageSliceFill;
    5743               0 :   SetBorderImageSlice(*aRuleData->ValueForBorderImageSlice(),
    5744               0 :                       borderImageSliceValue, borderImageSliceFill);
    5745                 : 
    5746                 :   // border-image-slice: fill
    5747                 :   SetDiscrete(borderImageSliceFill,
    5748                 :               border->mBorderImageFill,
    5749                 :               canStoreInRuleTree, SETDSC_ENUMERATED,
    5750                 :               parentBorder->mBorderImageFill,
    5751               0 :               NS_STYLE_BORDER_IMAGE_SLICE_NOFILL, 0, 0, 0, 0);
    5752                 : 
    5753               0 :   nsCSSRect borderImageSlice;
    5754               0 :   SetBorderImageRect(borderImageSliceValue, borderImageSlice);
    5755                 : 
    5756               0 :   nsCSSRect borderImageWidth;
    5757               0 :   SetBorderImageRect(*aRuleData->ValueForBorderImageWidth(),
    5758               0 :                      borderImageWidth);
    5759                 : 
    5760               0 :   nsCSSRect borderImageOutset;
    5761               0 :   SetBorderImageRect(*aRuleData->ValueForBorderImageOutset(),
    5762               0 :                      borderImageOutset);
    5763                 : 
    5764               0 :   NS_FOR_CSS_SIDES (side) {
    5765                 :     // border-image-slice
    5766               0 :     if (SetCoord(borderImageSlice.*(nsCSSRect::sides[side]), coord,
    5767                 :                  parentBorder->mBorderImageSlice.Get(side),
    5768                 :                  SETCOORD_FACTOR | SETCOORD_PERCENT |
    5769                 :                  SETCOORD_INHERIT | SETCOORD_INITIAL_HUNDRED_PCT,
    5770               0 :                  aContext, mPresContext, canStoreInRuleTree)) {
    5771               0 :       border->mBorderImageSlice.Set(side, coord);
    5772                 :     }
    5773                 : 
    5774                 :     // border-image-width
    5775                 :     // 'auto' here means "same as slice"
    5776               0 :     if (SetCoord(borderImageWidth.*(nsCSSRect::sides[side]), coord,
    5777                 :                  parentBorder->mBorderImageWidth.Get(side),
    5778                 :                  SETCOORD_LPAH | SETCOORD_FACTOR | SETCOORD_INITIAL_FACTOR_ONE,
    5779               0 :                  aContext, mPresContext, canStoreInRuleTree)) {
    5780               0 :       border->mBorderImageWidth.Set(side, coord);
    5781                 :     }
    5782                 : 
    5783                 :     // border-image-outset
    5784               0 :     if (SetCoord(borderImageOutset.*(nsCSSRect::sides[side]), coord,
    5785                 :                  parentBorder->mBorderImageOutset.Get(side),
    5786                 :                  SETCOORD_LENGTH | SETCOORD_FACTOR |
    5787                 :                  SETCOORD_INHERIT | SETCOORD_INITIAL_FACTOR_ZERO,
    5788               0 :                  aContext, mPresContext, canStoreInRuleTree)) {
    5789               0 :       border->mBorderImageOutset.Set(side, coord);
    5790                 :     }
    5791                 :   }
    5792                 : 
    5793                 :   // border-image-repeat
    5794               0 :   nsCSSValuePair borderImageRepeat;
    5795               0 :   SetBorderImagePair(*aRuleData->ValueForBorderImageRepeat(),
    5796               0 :                      borderImageRepeat);
    5797                 : 
    5798                 :   SetDiscrete(borderImageRepeat.mXValue,
    5799                 :               border->mBorderImageRepeatH,
    5800                 :               canStoreInRuleTree, SETDSC_ENUMERATED,
    5801                 :               parentBorder->mBorderImageRepeatH,
    5802               0 :               NS_STYLE_BORDER_IMAGE_REPEAT_STRETCH, 0, 0, 0, 0);
    5803                 : 
    5804                 :   SetDiscrete(borderImageRepeat.mYValue,
    5805                 :               border->mBorderImageRepeatV,
    5806                 :               canStoreInRuleTree, SETDSC_ENUMERATED,
    5807                 :               parentBorder->mBorderImageRepeatV,
    5808               0 :               NS_STYLE_BORDER_IMAGE_REPEAT_STRETCH, 0, 0, 0, 0);
    5809                 : 
    5810               0 :   if (border->HasBorderImage())
    5811               0 :     border->TrackImage(aContext->PresContext());
    5812                 : 
    5813               0 :   COMPUTE_END_RESET(Border, border)
    5814                 : }
    5815                 : 
    5816                 : const void*
    5817               0 : nsRuleNode::ComputePaddingData(void* aStartStruct,
    5818                 :                                const nsRuleData* aRuleData,
    5819                 :                                nsStyleContext* aContext,
    5820                 :                                nsRuleNode* aHighestNode,
    5821                 :                                const RuleDetail aRuleDetail,
    5822                 :                                const bool aCanStoreInRuleTree)
    5823                 : {
    5824               0 :   COMPUTE_START_RESET(Padding, (), padding, parentPadding)
    5825                 : 
    5826                 :   // padding: length, percent, inherit
    5827               0 :   nsStyleCoord  coord;
    5828               0 :   nsCSSRect ourPadding;
    5829               0 :   ourPadding.mTop = *aRuleData->ValueForPaddingTop();
    5830               0 :   ourPadding.mRight = *aRuleData->ValueForPaddingRightValue();
    5831               0 :   ourPadding.mBottom = *aRuleData->ValueForPaddingBottom();
    5832               0 :   ourPadding.mLeft = *aRuleData->ValueForPaddingLeftValue();
    5833                 :   AdjustLogicalBoxProp(aContext,
    5834               0 :                        *aRuleData->ValueForPaddingLeftLTRSource(),
    5835               0 :                        *aRuleData->ValueForPaddingLeftRTLSource(),
    5836               0 :                        *aRuleData->ValueForPaddingStartValue(),
    5837               0 :                        *aRuleData->ValueForPaddingEndValue(),
    5838               0 :                        NS_SIDE_LEFT, ourPadding, canStoreInRuleTree);
    5839                 :   AdjustLogicalBoxProp(aContext,
    5840               0 :                        *aRuleData->ValueForPaddingRightLTRSource(),
    5841               0 :                        *aRuleData->ValueForPaddingRightRTLSource(),
    5842               0 :                        *aRuleData->ValueForPaddingEndValue(),
    5843               0 :                        *aRuleData->ValueForPaddingStartValue(),
    5844               0 :                        NS_SIDE_RIGHT, ourPadding, canStoreInRuleTree);
    5845               0 :   NS_FOR_CSS_SIDES(side) {
    5846               0 :     nsStyleCoord parentCoord = parentPadding->mPadding.Get(side);
    5847               0 :     if (SetCoord(ourPadding.*(nsCSSRect::sides[side]),
    5848                 :                  coord, parentCoord,
    5849                 :                  SETCOORD_LPH | SETCOORD_INITIAL_ZERO | SETCOORD_STORE_CALC,
    5850               0 :                  aContext, mPresContext, canStoreInRuleTree)) {
    5851               0 :       padding->mPadding.Set(side, coord);
    5852                 :     }
    5853                 :   }
    5854                 : 
    5855               0 :   padding->RecalcData();
    5856               0 :   COMPUTE_END_RESET(Padding, padding)
    5857                 : }
    5858                 : 
    5859                 : const void*
    5860               0 : nsRuleNode::ComputeOutlineData(void* aStartStruct,
    5861                 :                                const nsRuleData* aRuleData,
    5862                 :                                nsStyleContext* aContext,
    5863                 :                                nsRuleNode* aHighestNode,
    5864                 :                                const RuleDetail aRuleDetail,
    5865                 :                                const bool aCanStoreInRuleTree)
    5866                 : {
    5867               0 :   COMPUTE_START_RESET(Outline, (mPresContext), outline, parentOutline)
    5868                 : 
    5869                 :   // outline-width: length, enum, inherit
    5870               0 :   const nsCSSValue* outlineWidthValue = aRuleData->ValueForOutlineWidth();
    5871               0 :   if (eCSSUnit_Initial == outlineWidthValue->GetUnit()) {
    5872                 :     outline->mOutlineWidth =
    5873               0 :       nsStyleCoord(NS_STYLE_BORDER_WIDTH_MEDIUM, eStyleUnit_Enumerated);
    5874                 :   }
    5875                 :   else {
    5876                 :     SetCoord(*outlineWidthValue, outline->mOutlineWidth,
    5877                 :              parentOutline->mOutlineWidth,
    5878                 :              SETCOORD_LEH | SETCOORD_CALC_LENGTH_ONLY, aContext,
    5879               0 :              mPresContext, canStoreInRuleTree);
    5880                 :   }
    5881                 : 
    5882                 :   // outline-offset: length, inherit
    5883               0 :   nsStyleCoord tempCoord;
    5884               0 :   const nsCSSValue* outlineOffsetValue = aRuleData->ValueForOutlineOffset();
    5885               0 :   if (SetCoord(*outlineOffsetValue, tempCoord,
    5886                 :                nsStyleCoord(parentOutline->mOutlineOffset,
    5887                 :                             nsStyleCoord::CoordConstructor),
    5888                 :                SETCOORD_LH | SETCOORD_INITIAL_ZERO | SETCOORD_CALC_LENGTH_ONLY,
    5889               0 :                aContext, mPresContext, canStoreInRuleTree)) {
    5890               0 :     outline->mOutlineOffset = tempCoord.GetCoordValue();
    5891                 :   } else {
    5892               0 :     NS_ASSERTION(outlineOffsetValue->GetUnit() == eCSSUnit_Null,
    5893                 :                  "unexpected unit");
    5894                 :   }
    5895                 : 
    5896                 :   // outline-color: color, string, enum, inherit
    5897                 :   nscolor outlineColor;
    5898               0 :   nscolor unused = NS_RGB(0,0,0);
    5899               0 :   const nsCSSValue* outlineColorValue = aRuleData->ValueForOutlineColor();
    5900               0 :   if (eCSSUnit_Inherit == outlineColorValue->GetUnit()) {
    5901               0 :     canStoreInRuleTree = false;
    5902               0 :     if (parentContext) {
    5903               0 :       if (parentOutline->GetOutlineColor(outlineColor))
    5904               0 :         outline->SetOutlineColor(outlineColor);
    5905                 :       else {
    5906                 :         // We want to inherit the color from the parent, not use the
    5907                 :         // color on the element where this chunk of style data will be
    5908                 :         // used.  We can ensure that the data for the parent are fully
    5909                 :         // computed (unlike for the element where this will be used, for
    5910                 :         // which the color could be specified on a more specific rule).
    5911               0 :         outline->SetOutlineColor(parentContext->GetStyleColor()->mColor);
    5912                 :       }
    5913                 :     } else {
    5914               0 :       outline->SetOutlineInitialColor();
    5915                 :     }
    5916                 :   }
    5917               0 :   else if (SetColor(*outlineColorValue, unused, mPresContext,
    5918               0 :                     aContext, outlineColor, canStoreInRuleTree))
    5919               0 :     outline->SetOutlineColor(outlineColor);
    5920               0 :   else if (eCSSUnit_Enumerated == outlineColorValue->GetUnit() ||
    5921               0 :            eCSSUnit_Initial == outlineColorValue->GetUnit()) {
    5922               0 :     outline->SetOutlineInitialColor();
    5923                 :   }
    5924                 : 
    5925                 :   // -moz-outline-radius: length, percent, inherit
    5926                 :   {
    5927                 :     const nsCSSProperty* subprops =
    5928               0 :       nsCSSProps::SubpropertyEntryFor(eCSSProperty__moz_outline_radius);
    5929               0 :     NS_FOR_CSS_FULL_CORNERS(corner) {
    5930               0 :       int cx = NS_FULL_TO_HALF_CORNER(corner, false);
    5931               0 :       int cy = NS_FULL_TO_HALF_CORNER(corner, true);
    5932               0 :       const nsCSSValue& radius = *aRuleData->ValueFor(subprops[corner]);
    5933               0 :       nsStyleCoord parentX = parentOutline->mOutlineRadius.Get(cx);
    5934               0 :       nsStyleCoord parentY = parentOutline->mOutlineRadius.Get(cy);
    5935               0 :       nsStyleCoord coordX, coordY;
    5936                 : 
    5937               0 :       if (SetPairCoords(radius, coordX, coordY, parentX, parentY,
    5938                 :                         SETCOORD_LPH | SETCOORD_INITIAL_ZERO |
    5939                 :                           SETCOORD_STORE_CALC,
    5940               0 :                         aContext, mPresContext, canStoreInRuleTree)) {
    5941               0 :         outline->mOutlineRadius.Set(cx, coordX);
    5942               0 :         outline->mOutlineRadius.Set(cy, coordY);
    5943                 :       }
    5944                 :     }
    5945                 :   }
    5946                 : 
    5947                 :   // outline-style: enum, inherit, initial
    5948                 :   // cannot use SetDiscrete because of SetOutlineStyle
    5949               0 :   const nsCSSValue* outlineStyleValue = aRuleData->ValueForOutlineStyle();
    5950               0 :   nsCSSUnit unit = outlineStyleValue->GetUnit();
    5951               0 :   NS_ABORT_IF_FALSE(eCSSUnit_None != unit && eCSSUnit_Auto != unit,
    5952                 :                     "'none' and 'auto' should be handled as enumerated values");
    5953               0 :   if (eCSSUnit_Enumerated == unit) {
    5954               0 :     outline->SetOutlineStyle(outlineStyleValue->GetIntValue());
    5955               0 :   } else if (eCSSUnit_Initial == unit) {
    5956               0 :     outline->SetOutlineStyle(NS_STYLE_BORDER_STYLE_NONE);
    5957               0 :   } else if (eCSSUnit_Inherit == unit) {
    5958               0 :     canStoreInRuleTree = false;
    5959               0 :     outline->SetOutlineStyle(parentOutline->GetOutlineStyle());
    5960                 :   }
    5961                 : 
    5962               0 :   outline->RecalcData(mPresContext);
    5963               0 :   COMPUTE_END_RESET(Outline, outline)
    5964                 : }
    5965                 : 
    5966                 : const void*
    5967               0 : nsRuleNode::ComputeListData(void* aStartStruct,
    5968                 :                             const nsRuleData* aRuleData,
    5969                 :                             nsStyleContext* aContext,
    5970                 :                             nsRuleNode* aHighestNode,
    5971                 :                             const RuleDetail aRuleDetail,
    5972                 :                             const bool aCanStoreInRuleTree)
    5973                 : {
    5974               0 :   COMPUTE_START_INHERITED(List, (), list, parentList)
    5975                 : 
    5976                 :   // list-style-type: enum, inherit, initial
    5977               0 :   SetDiscrete(*aRuleData->ValueForListStyleType(),
    5978                 :               list->mListStyleType, canStoreInRuleTree,
    5979                 :               SETDSC_ENUMERATED, parentList->mListStyleType,
    5980               0 :               NS_STYLE_LIST_STYLE_DISC, 0, 0, 0, 0);
    5981                 : 
    5982                 :   // list-style-image: url, none, inherit
    5983               0 :   const nsCSSValue* imageValue = aRuleData->ValueForListStyleImage();
    5984               0 :   if (eCSSUnit_Image == imageValue->GetUnit()) {
    5985               0 :     NS_SET_IMAGE_REQUEST(list->SetListStyleImage,
    5986                 :                          aContext,
    5987                 :                          imageValue->GetImageValue())
    5988                 :   }
    5989               0 :   else if (eCSSUnit_None == imageValue->GetUnit() ||
    5990               0 :            eCSSUnit_Initial == imageValue->GetUnit()) {
    5991               0 :     list->SetListStyleImage(nsnull);
    5992                 :   }
    5993               0 :   else if (eCSSUnit_Inherit == imageValue->GetUnit()) {
    5994               0 :     canStoreInRuleTree = false;
    5995               0 :     NS_SET_IMAGE_REQUEST(list->SetListStyleImage,
    5996                 :                          aContext,
    5997                 :                          parentList->GetListStyleImage())
    5998                 :   }
    5999                 : 
    6000                 :   // list-style-position: enum, inherit, initial
    6001               0 :   SetDiscrete(*aRuleData->ValueForListStylePosition(),
    6002                 :               list->mListStylePosition, canStoreInRuleTree,
    6003                 :               SETDSC_ENUMERATED, parentList->mListStylePosition,
    6004               0 :               NS_STYLE_LIST_STYLE_POSITION_OUTSIDE, 0, 0, 0, 0);
    6005                 : 
    6006                 :   // image region property: length, auto, inherit
    6007               0 :   const nsCSSValue* imageRegionValue = aRuleData->ValueForImageRegion();
    6008               0 :   switch (imageRegionValue->GetUnit()) {
    6009                 :   case eCSSUnit_Inherit:
    6010               0 :     canStoreInRuleTree = false;
    6011               0 :     list->mImageRegion = parentList->mImageRegion;
    6012               0 :     break;
    6013                 : 
    6014                 :   case eCSSUnit_Initial:
    6015                 :   case eCSSUnit_Auto:
    6016               0 :     list->mImageRegion.SetRect(0,0,0,0);
    6017               0 :     break;
    6018                 : 
    6019                 :   case eCSSUnit_Null:
    6020               0 :     break;
    6021                 : 
    6022                 :   case eCSSUnit_Rect: {
    6023               0 :     const nsCSSRect& rgnRect = imageRegionValue->GetRectValue();
    6024                 : 
    6025               0 :     if (rgnRect.mTop.GetUnit() == eCSSUnit_Auto)
    6026               0 :       list->mImageRegion.y = 0;
    6027               0 :     else if (rgnRect.mTop.IsLengthUnit())
    6028                 :       list->mImageRegion.y =
    6029               0 :         CalcLength(rgnRect.mTop, aContext, mPresContext, canStoreInRuleTree);
    6030                 : 
    6031               0 :     if (rgnRect.mBottom.GetUnit() == eCSSUnit_Auto)
    6032               0 :       list->mImageRegion.height = 0;
    6033               0 :     else if (rgnRect.mBottom.IsLengthUnit())
    6034                 :       list->mImageRegion.height =
    6035                 :         CalcLength(rgnRect.mBottom, aContext, mPresContext,
    6036               0 :                    canStoreInRuleTree) - list->mImageRegion.y;
    6037                 : 
    6038               0 :     if (rgnRect.mLeft.GetUnit() == eCSSUnit_Auto)
    6039               0 :       list->mImageRegion.x = 0;
    6040               0 :     else if (rgnRect.mLeft.IsLengthUnit())
    6041                 :       list->mImageRegion.x =
    6042               0 :         CalcLength(rgnRect.mLeft, aContext, mPresContext, canStoreInRuleTree);
    6043                 : 
    6044               0 :     if (rgnRect.mRight.GetUnit() == eCSSUnit_Auto)
    6045               0 :       list->mImageRegion.width = 0;
    6046               0 :     else if (rgnRect.mRight.IsLengthUnit())
    6047                 :       list->mImageRegion.width =
    6048                 :         CalcLength(rgnRect.mRight, aContext, mPresContext,
    6049               0 :                    canStoreInRuleTree) - list->mImageRegion.x;
    6050               0 :     break;
    6051                 :   }
    6052                 : 
    6053                 :   default:
    6054               0 :     NS_ABORT_IF_FALSE(false, "unrecognized image-region unit");
    6055                 :   }
    6056                 : 
    6057               0 :   COMPUTE_END_INHERITED(List, list)
    6058                 : }
    6059                 : 
    6060                 : const void*
    6061               0 : nsRuleNode::ComputePositionData(void* aStartStruct,
    6062                 :                                 const nsRuleData* aRuleData,
    6063                 :                                 nsStyleContext* aContext,
    6064                 :                                 nsRuleNode* aHighestNode,
    6065                 :                                 const RuleDetail aRuleDetail,
    6066                 :                                 const bool aCanStoreInRuleTree)
    6067                 : {
    6068               0 :   COMPUTE_START_RESET(Position, (), pos, parentPos)
    6069                 : 
    6070                 :   // box offsets: length, percent, calc, auto, inherit
    6071                 :   static const nsCSSProperty offsetProps[] = {
    6072                 :     eCSSProperty_top,
    6073                 :     eCSSProperty_right,
    6074                 :     eCSSProperty_bottom,
    6075                 :     eCSSProperty_left
    6076                 :   };
    6077               0 :   nsStyleCoord  coord;
    6078               0 :   NS_FOR_CSS_SIDES(side) {
    6079               0 :     nsStyleCoord parentCoord = parentPos->mOffset.Get(side);
    6080               0 :     if (SetCoord(*aRuleData->ValueFor(offsetProps[side]),
    6081                 :                  coord, parentCoord,
    6082                 :                  SETCOORD_LPAH | SETCOORD_INITIAL_AUTO | SETCOORD_STORE_CALC,
    6083               0 :                  aContext, mPresContext, canStoreInRuleTree)) {
    6084               0 :       pos->mOffset.Set(side, coord);
    6085                 :     }
    6086                 :   }
    6087                 : 
    6088               0 :   SetCoord(*aRuleData->ValueForWidth(), pos->mWidth, parentPos->mWidth,
    6089                 :            SETCOORD_LPAEH | SETCOORD_INITIAL_AUTO | SETCOORD_STORE_CALC,
    6090               0 :            aContext, mPresContext, canStoreInRuleTree);
    6091               0 :   SetCoord(*aRuleData->ValueForMinWidth(), pos->mMinWidth, parentPos->mMinWidth,
    6092                 :            SETCOORD_LPEH | SETCOORD_INITIAL_ZERO | SETCOORD_STORE_CALC,
    6093               0 :            aContext, mPresContext, canStoreInRuleTree);
    6094               0 :   SetCoord(*aRuleData->ValueForMaxWidth(), pos->mMaxWidth, parentPos->mMaxWidth,
    6095                 :            SETCOORD_LPOEH | SETCOORD_INITIAL_NONE | SETCOORD_STORE_CALC,
    6096               0 :            aContext, mPresContext, canStoreInRuleTree);
    6097                 : 
    6098               0 :   SetCoord(*aRuleData->ValueForHeight(), pos->mHeight, parentPos->mHeight,
    6099                 :            SETCOORD_LPAH | SETCOORD_INITIAL_AUTO | SETCOORD_STORE_CALC,
    6100               0 :            aContext, mPresContext, canStoreInRuleTree);
    6101               0 :   SetCoord(*aRuleData->ValueForMinHeight(), pos->mMinHeight, parentPos->mMinHeight,
    6102                 :            SETCOORD_LPH | SETCOORD_INITIAL_ZERO | SETCOORD_STORE_CALC,
    6103               0 :            aContext, mPresContext, canStoreInRuleTree);
    6104               0 :   SetCoord(*aRuleData->ValueForMaxHeight(), pos->mMaxHeight, parentPos->mMaxHeight,
    6105                 :            SETCOORD_LPOH | SETCOORD_INITIAL_NONE | SETCOORD_STORE_CALC,
    6106               0 :            aContext, mPresContext, canStoreInRuleTree);
    6107                 : 
    6108                 :   // box-sizing: enum, inherit, initial
    6109               0 :   SetDiscrete(*aRuleData->ValueForBoxSizing(),
    6110                 :               pos->mBoxSizing, canStoreInRuleTree,
    6111                 :               SETDSC_ENUMERATED, parentPos->mBoxSizing,
    6112               0 :               NS_STYLE_BOX_SIZING_CONTENT, 0, 0, 0, 0);
    6113                 : 
    6114                 :   // z-index
    6115               0 :   const nsCSSValue* zIndexValue = aRuleData->ValueForZIndex();
    6116               0 :   if (! SetCoord(*zIndexValue, pos->mZIndex, parentPos->mZIndex,
    6117                 :                  SETCOORD_IA | SETCOORD_INITIAL_AUTO, aContext,
    6118               0 :                  nsnull, canStoreInRuleTree)) {
    6119               0 :     if (eCSSUnit_Inherit == zIndexValue->GetUnit()) {
    6120                 :       // handle inherit, because it's ok to inherit 'auto' here
    6121               0 :       canStoreInRuleTree = false;
    6122               0 :       pos->mZIndex = parentPos->mZIndex;
    6123                 :     }
    6124                 :   }
    6125                 : 
    6126               0 :   COMPUTE_END_RESET(Position, pos)
    6127                 : }
    6128                 : 
    6129                 : const void*
    6130               0 : nsRuleNode::ComputeTableData(void* aStartStruct,
    6131                 :                              const nsRuleData* aRuleData,
    6132                 :                              nsStyleContext* aContext,
    6133                 :                              nsRuleNode* aHighestNode,
    6134                 :                              const RuleDetail aRuleDetail,
    6135                 :                              const bool aCanStoreInRuleTree)
    6136                 : {
    6137               0 :   COMPUTE_START_RESET(Table, (), table, parentTable)
    6138                 : 
    6139                 :   // table-layout: enum, inherit, initial
    6140               0 :   SetDiscrete(*aRuleData->ValueForTableLayout(),
    6141                 :               table->mLayoutStrategy, canStoreInRuleTree,
    6142                 :               SETDSC_ENUMERATED, parentTable->mLayoutStrategy,
    6143               0 :               NS_STYLE_TABLE_LAYOUT_AUTO, 0, 0, 0, 0);
    6144                 : 
    6145                 :   // cols: enum, int (not a real CSS prop)
    6146               0 :   const nsCSSValue* colsValue = aRuleData->ValueForCols();
    6147               0 :   if (eCSSUnit_Enumerated == colsValue->GetUnit() ||
    6148               0 :       eCSSUnit_Integer == colsValue->GetUnit())
    6149               0 :     table->mCols = colsValue->GetIntValue();
    6150                 : 
    6151                 :   // span: pixels (not a real CSS prop)
    6152               0 :   const nsCSSValue* spanValue = aRuleData->ValueForSpan();
    6153               0 :   if (eCSSUnit_Enumerated == spanValue->GetUnit() ||
    6154               0 :       eCSSUnit_Integer == spanValue->GetUnit())
    6155               0 :     table->mSpan = spanValue->GetIntValue();
    6156                 : 
    6157               0 :   COMPUTE_END_RESET(Table, table)
    6158                 : }
    6159                 : 
    6160                 : const void*
    6161               0 : nsRuleNode::ComputeTableBorderData(void* aStartStruct,
    6162                 :                                    const nsRuleData* aRuleData,
    6163                 :                                    nsStyleContext* aContext,
    6164                 :                                    nsRuleNode* aHighestNode,
    6165                 :                                    const RuleDetail aRuleDetail,
    6166                 :                                    const bool aCanStoreInRuleTree)
    6167                 : {
    6168               0 :   COMPUTE_START_INHERITED(TableBorder, (mPresContext), table, parentTable)
    6169                 : 
    6170                 :   // border-collapse: enum, inherit, initial
    6171               0 :   SetDiscrete(*aRuleData->ValueForBorderCollapse(), table->mBorderCollapse,
    6172                 :               canStoreInRuleTree,
    6173                 :               SETDSC_ENUMERATED, parentTable->mBorderCollapse,
    6174               0 :               NS_STYLE_BORDER_SEPARATE, 0, 0, 0, 0);
    6175                 : 
    6176               0 :   const nsCSSValue* borderSpacingValue = aRuleData->ValueForBorderSpacing();
    6177               0 :   if (borderSpacingValue->GetUnit() != eCSSUnit_Null) {
    6178                 :     // border-spacing-x/y: length, inherit
    6179                 :     nsStyleCoord parentX(parentTable->mBorderSpacingX,
    6180               0 :                          nsStyleCoord::CoordConstructor);
    6181                 :     nsStyleCoord parentY(parentTable->mBorderSpacingY,
    6182               0 :                          nsStyleCoord::CoordConstructor);
    6183               0 :     nsStyleCoord coordX, coordY;
    6184                 : 
    6185                 : #ifdef DEBUG
    6186                 :     bool result =
    6187                 : #endif
    6188                 :       SetPairCoords(*borderSpacingValue,
    6189                 :                     coordX, coordY, parentX, parentY,
    6190                 :                     SETCOORD_LH | SETCOORD_INITIAL_ZERO |
    6191                 :                     SETCOORD_CALC_LENGTH_ONLY |
    6192                 :                     SETCOORD_CALC_CLAMP_NONNEGATIVE,
    6193               0 :                     aContext, mPresContext, canStoreInRuleTree);
    6194               0 :     NS_ASSERTION(result, "malformed table border value");
    6195               0 :     table->mBorderSpacingX = coordX.GetCoordValue();
    6196               0 :     table->mBorderSpacingY = coordY.GetCoordValue();
    6197                 :   }
    6198                 : 
    6199                 :   // caption-side: enum, inherit, initial
    6200               0 :   SetDiscrete(*aRuleData->ValueForCaptionSide(),
    6201                 :               table->mCaptionSide, canStoreInRuleTree,
    6202                 :               SETDSC_ENUMERATED, parentTable->mCaptionSide,
    6203               0 :               NS_STYLE_CAPTION_SIDE_TOP, 0, 0, 0, 0);
    6204                 : 
    6205                 :   // empty-cells: enum, inherit, initial
    6206               0 :   SetDiscrete(*aRuleData->ValueForEmptyCells(),
    6207                 :               table->mEmptyCells, canStoreInRuleTree,
    6208                 :               SETDSC_ENUMERATED, parentTable->mEmptyCells,
    6209               0 :               (mPresContext->CompatibilityMode() == eCompatibility_NavQuirks)
    6210                 :               ? NS_STYLE_TABLE_EMPTY_CELLS_SHOW_BACKGROUND
    6211                 :               : NS_STYLE_TABLE_EMPTY_CELLS_SHOW,
    6212               0 :               0, 0, 0, 0);
    6213                 : 
    6214               0 :   COMPUTE_END_INHERITED(TableBorder, table)
    6215                 : }
    6216                 : 
    6217                 : const void*
    6218               0 : nsRuleNode::ComputeContentData(void* aStartStruct,
    6219                 :                                const nsRuleData* aRuleData,
    6220                 :                                nsStyleContext* aContext,
    6221                 :                                nsRuleNode* aHighestNode,
    6222                 :                                const RuleDetail aRuleDetail,
    6223                 :                                const bool aCanStoreInRuleTree)
    6224                 : {
    6225                 :   PRUint32 count;
    6226               0 :   nsAutoString buffer;
    6227                 : 
    6228               0 :   COMPUTE_START_RESET(Content, (), content, parentContent)
    6229                 : 
    6230                 :   // content: [string, url, counter, attr, enum]+, normal, none, inherit
    6231               0 :   const nsCSSValue* contentValue = aRuleData->ValueForContent();
    6232               0 :   switch (contentValue->GetUnit()) {
    6233                 :   case eCSSUnit_Null:
    6234               0 :     break;
    6235                 : 
    6236                 :   case eCSSUnit_Normal:
    6237                 :   case eCSSUnit_None:
    6238                 :   case eCSSUnit_Initial:
    6239                 :     // "normal", "none", and "initial" all mean no content
    6240               0 :     content->AllocateContents(0);
    6241               0 :     break;
    6242                 : 
    6243                 :   case eCSSUnit_Inherit:
    6244               0 :     canStoreInRuleTree = false;
    6245               0 :     count = parentContent->ContentCount();
    6246               0 :     if (NS_SUCCEEDED(content->AllocateContents(count))) {
    6247               0 :       while (0 < count--) {
    6248               0 :         content->ContentAt(count) = parentContent->ContentAt(count);
    6249                 :       }
    6250                 :     }
    6251               0 :     break;
    6252                 : 
    6253                 :   case eCSSUnit_Enumerated: {
    6254               0 :     NS_ABORT_IF_FALSE(contentValue->GetIntValue() ==
    6255                 :                       NS_STYLE_CONTENT_ALT_CONTENT,
    6256                 :                       "unrecognized solitary content keyword");
    6257               0 :     content->AllocateContents(1);
    6258               0 :     nsStyleContentData& data = content->ContentAt(0);
    6259               0 :     data.mType = eStyleContentType_AltContent;
    6260               0 :     data.mContent.mString = nsnull;
    6261               0 :     break;
    6262                 :   }
    6263                 : 
    6264                 :   case eCSSUnit_List:
    6265                 :   case eCSSUnit_ListDep: {
    6266               0 :     const nsCSSValueList* contentValueList = contentValue->GetListValue();
    6267               0 :       count = 0;
    6268               0 :       while (contentValueList) {
    6269               0 :         count++;
    6270               0 :         contentValueList = contentValueList->mNext;
    6271                 :       }
    6272               0 :       if (NS_SUCCEEDED(content->AllocateContents(count))) {
    6273               0 :         const nsAutoString  nullStr;
    6274               0 :         count = 0;
    6275               0 :         contentValueList = contentValue->GetListValue();
    6276               0 :         while (contentValueList) {
    6277               0 :           const nsCSSValue& value = contentValueList->mValue;
    6278               0 :           nsCSSUnit unit = value.GetUnit();
    6279                 :           nsStyleContentType type;
    6280               0 :           nsStyleContentData &data = content->ContentAt(count++);
    6281               0 :           switch (unit) {
    6282               0 :           case eCSSUnit_String:   type = eStyleContentType_String;    break;
    6283               0 :           case eCSSUnit_Image:    type = eStyleContentType_Image;     break;
    6284               0 :           case eCSSUnit_Attr:     type = eStyleContentType_Attr;      break;
    6285               0 :           case eCSSUnit_Counter:  type = eStyleContentType_Counter;   break;
    6286               0 :           case eCSSUnit_Counters: type = eStyleContentType_Counters;  break;
    6287                 :           case eCSSUnit_Enumerated:
    6288               0 :             switch (value.GetIntValue()) {
    6289                 :             case NS_STYLE_CONTENT_OPEN_QUOTE:
    6290               0 :               type = eStyleContentType_OpenQuote;     break;
    6291                 :             case NS_STYLE_CONTENT_CLOSE_QUOTE:
    6292               0 :               type = eStyleContentType_CloseQuote;    break;
    6293                 :             case NS_STYLE_CONTENT_NO_OPEN_QUOTE:
    6294               0 :               type = eStyleContentType_NoOpenQuote;   break;
    6295                 :             case NS_STYLE_CONTENT_NO_CLOSE_QUOTE:
    6296               0 :               type = eStyleContentType_NoCloseQuote;  break;
    6297                 :             default:
    6298               0 :               NS_ERROR("bad content value");
    6299                 :             }
    6300               0 :             break;
    6301                 :           default:
    6302               0 :             NS_ERROR("bad content type");
    6303                 :           }
    6304               0 :           data.mType = type;
    6305               0 :           if (type == eStyleContentType_Image) {
    6306               0 :             NS_SET_IMAGE_REQUEST(data.SetImage, aContext, value.GetImageValue());
    6307                 :           }
    6308               0 :           else if (type <= eStyleContentType_Attr) {
    6309               0 :             value.GetStringValue(buffer);
    6310               0 :             data.mContent.mString = NS_strdup(buffer.get());
    6311                 :           }
    6312               0 :           else if (type <= eStyleContentType_Counters) {
    6313               0 :             data.mContent.mCounters = value.GetArrayValue();
    6314               0 :             data.mContent.mCounters->AddRef();
    6315                 :           }
    6316                 :           else {
    6317               0 :             data.mContent.mString = nsnull;
    6318                 :           }
    6319               0 :           contentValueList = contentValueList->mNext;
    6320                 :         }
    6321                 :       }
    6322               0 :       break;
    6323                 :   }
    6324                 : 
    6325                 :   default:
    6326               0 :     NS_ABORT_IF_FALSE(false,
    6327                 :                       nsPrintfCString(64, "unrecognized content unit %d",
    6328                 :                                       contentValue->GetUnit()).get());
    6329                 :   }
    6330                 : 
    6331                 :   // counter-increment: [string [int]]+, none, inherit
    6332                 :   const nsCSSValue* counterIncrementValue =
    6333               0 :     aRuleData->ValueForCounterIncrement();
    6334               0 :   switch (counterIncrementValue->GetUnit()) {
    6335                 :   case eCSSUnit_Null:
    6336               0 :     break;
    6337                 : 
    6338                 :   case eCSSUnit_None:
    6339                 :   case eCSSUnit_Initial:
    6340               0 :     content->AllocateCounterIncrements(0);
    6341               0 :     break;
    6342                 : 
    6343                 :   case eCSSUnit_Inherit:
    6344               0 :     canStoreInRuleTree = false;
    6345               0 :     count = parentContent->CounterIncrementCount();
    6346               0 :     if (NS_SUCCEEDED(content->AllocateCounterIncrements(count))) {
    6347               0 :       while (0 < count--) {
    6348                 :         const nsStyleCounterData *data =
    6349               0 :           parentContent->GetCounterIncrementAt(count);
    6350               0 :         content->SetCounterIncrementAt(count, data->mCounter, data->mValue);
    6351                 :       }
    6352                 :     }
    6353               0 :     break;
    6354                 : 
    6355                 :   case eCSSUnit_PairList:
    6356                 :   case eCSSUnit_PairListDep: {
    6357                 :     const nsCSSValuePairList* ourIncrement =
    6358               0 :       counterIncrementValue->GetPairListValue();
    6359               0 :     NS_ABORT_IF_FALSE(ourIncrement->mXValue.GetUnit() == eCSSUnit_Ident,
    6360                 :                       "unexpected value unit");
    6361               0 :     count = ListLength(ourIncrement);
    6362               0 :     if (NS_FAILED(content->AllocateCounterIncrements(count))) {
    6363               0 :       break;
    6364                 :     }
    6365                 : 
    6366               0 :     count = 0;
    6367               0 :     for (const nsCSSValuePairList* p = ourIncrement; p; p = p->mNext, count++) {
    6368                 :       PRInt32 increment;
    6369               0 :       if (p->mYValue.GetUnit() == eCSSUnit_Integer) {
    6370               0 :         increment = p->mYValue.GetIntValue();
    6371                 :       } else {
    6372               0 :         increment = 1;
    6373                 :       }
    6374               0 :       p->mXValue.GetStringValue(buffer);
    6375               0 :       content->SetCounterIncrementAt(count, buffer, increment);
    6376                 :     }
    6377               0 :     break;
    6378                 :   }
    6379                 : 
    6380                 :   default:
    6381               0 :     NS_ABORT_IF_FALSE(false, "unexpected value unit");
    6382                 :   }
    6383                 : 
    6384                 :   // counter-reset: [string [int]]+, none, inherit
    6385               0 :   const nsCSSValue* counterResetValue = aRuleData->ValueForCounterReset();
    6386               0 :   switch (counterResetValue->GetUnit()) {
    6387                 :   case eCSSUnit_Null:
    6388               0 :     break;
    6389                 : 
    6390                 :   case eCSSUnit_None:
    6391                 :   case eCSSUnit_Initial:
    6392               0 :     content->AllocateCounterResets(0);
    6393               0 :     break;
    6394                 : 
    6395                 :   case eCSSUnit_Inherit:
    6396               0 :     canStoreInRuleTree = false;
    6397               0 :     count = parentContent->CounterResetCount();
    6398               0 :     if (NS_SUCCEEDED(content->AllocateCounterResets(count))) {
    6399               0 :       while (0 < count--) {
    6400                 :         const nsStyleCounterData *data =
    6401               0 :           parentContent->GetCounterResetAt(count);
    6402               0 :         content->SetCounterResetAt(count, data->mCounter, data->mValue);
    6403                 :       }
    6404                 :     }
    6405               0 :     break;
    6406                 : 
    6407                 :   case eCSSUnit_PairList:
    6408                 :   case eCSSUnit_PairListDep: {
    6409                 :     const nsCSSValuePairList* ourReset =
    6410               0 :       counterResetValue->GetPairListValue();
    6411               0 :     NS_ABORT_IF_FALSE(ourReset->mXValue.GetUnit() == eCSSUnit_Ident,
    6412                 :                       "unexpected value unit");
    6413               0 :     count = ListLength(ourReset);
    6414               0 :     if (NS_FAILED(content->AllocateCounterResets(count))) {
    6415               0 :       break;
    6416                 :     }
    6417                 : 
    6418               0 :     count = 0;
    6419               0 :     for (const nsCSSValuePairList* p = ourReset; p; p = p->mNext, count++) {
    6420                 :       PRInt32 reset;
    6421               0 :       if (p->mYValue.GetUnit() == eCSSUnit_Integer) {
    6422               0 :         reset = p->mYValue.GetIntValue();
    6423                 :       } else {
    6424               0 :         reset = 0;
    6425                 :       }
    6426               0 :       p->mXValue.GetStringValue(buffer);
    6427               0 :       content->SetCounterResetAt(count, buffer, reset);
    6428                 :     }
    6429               0 :     break;
    6430                 :   }
    6431                 : 
    6432                 :   default:
    6433               0 :     NS_ABORT_IF_FALSE(false, "unexpected value unit");
    6434                 :   }
    6435                 : 
    6436                 :   // marker-offset: length, auto, inherit
    6437               0 :   SetCoord(*aRuleData->ValueForMarkerOffset(), content->mMarkerOffset, parentContent->mMarkerOffset,
    6438                 :            SETCOORD_LH | SETCOORD_AUTO | SETCOORD_INITIAL_AUTO |
    6439                 :              SETCOORD_CALC_LENGTH_ONLY,
    6440               0 :            aContext, mPresContext, canStoreInRuleTree);
    6441                 : 
    6442                 :   // If we ended up with an image, track it.
    6443               0 :   for (PRUint32 i = 0; i < content->ContentCount(); ++i) {
    6444               0 :     if ((content->ContentAt(i).mType == eStyleContentType_Image) &&
    6445               0 :         content->ContentAt(i).mContent.mImage) {
    6446               0 :       content->ContentAt(i).TrackImage(aContext->PresContext());
    6447                 :     }
    6448                 :   }
    6449                 : 
    6450               0 :   COMPUTE_END_RESET(Content, content)
    6451                 : }
    6452                 : 
    6453                 : const void*
    6454               0 : nsRuleNode::ComputeQuotesData(void* aStartStruct,
    6455                 :                               const nsRuleData* aRuleData,
    6456                 :                               nsStyleContext* aContext,
    6457                 :                               nsRuleNode* aHighestNode,
    6458                 :                               const RuleDetail aRuleDetail,
    6459                 :                               const bool aCanStoreInRuleTree)
    6460                 : {
    6461               0 :   COMPUTE_START_INHERITED(Quotes, (), quotes, parentQuotes)
    6462                 : 
    6463                 :   // quotes: inherit, initial, none, [string string]+
    6464               0 :   const nsCSSValue* quotesValue = aRuleData->ValueForQuotes();
    6465               0 :   switch (quotesValue->GetUnit()) {
    6466                 :   case eCSSUnit_Null:
    6467               0 :     break;
    6468                 :   case eCSSUnit_Inherit:
    6469               0 :     canStoreInRuleTree = false;
    6470               0 :     quotes->CopyFrom(*parentQuotes);
    6471               0 :     break;
    6472                 :   case eCSSUnit_Initial:
    6473               0 :     quotes->SetInitial();
    6474               0 :     break;
    6475                 :   case eCSSUnit_None:
    6476               0 :     quotes->AllocateQuotes(0);
    6477               0 :     break;
    6478                 :   case eCSSUnit_PairList:
    6479                 :   case eCSSUnit_PairListDep: {
    6480                 :     const nsCSSValuePairList* ourQuotes
    6481               0 :       = quotesValue->GetPairListValue();
    6482               0 :     nsAutoString buffer;
    6483               0 :     nsAutoString closeBuffer;
    6484               0 :     PRUint32 count = ListLength(ourQuotes);
    6485               0 :     if (NS_FAILED(quotes->AllocateQuotes(count))) {
    6486                 :       break;
    6487                 :     }
    6488               0 :     count = 0;
    6489               0 :     while (ourQuotes) {
    6490               0 :       NS_ABORT_IF_FALSE(ourQuotes->mXValue.GetUnit() == eCSSUnit_String &&
    6491                 :                         ourQuotes->mYValue.GetUnit() == eCSSUnit_String,
    6492                 :                         "improper list contents for quotes");
    6493               0 :       ourQuotes->mXValue.GetStringValue(buffer);
    6494               0 :       ourQuotes->mYValue.GetStringValue(closeBuffer);
    6495               0 :       quotes->SetQuotesAt(count++, buffer, closeBuffer);
    6496               0 :       ourQuotes = ourQuotes->mNext;
    6497                 :     }
    6498                 :     break;
    6499                 :   }
    6500                 :   default:
    6501               0 :     NS_ABORT_IF_FALSE(false, "unexpected value unit");
    6502                 :   }
    6503                 : 
    6504               0 :   COMPUTE_END_INHERITED(Quotes, quotes)
    6505                 : }
    6506                 : 
    6507                 : const void*
    6508               0 : nsRuleNode::ComputeXULData(void* aStartStruct,
    6509                 :                            const nsRuleData* aRuleData,
    6510                 :                            nsStyleContext* aContext,
    6511                 :                            nsRuleNode* aHighestNode,
    6512                 :                            const RuleDetail aRuleDetail,
    6513                 :                            const bool aCanStoreInRuleTree)
    6514                 : {
    6515               0 :   COMPUTE_START_RESET(XUL, (), xul, parentXUL)
    6516                 : 
    6517                 :   // box-align: enum, inherit, initial
    6518               0 :   SetDiscrete(*aRuleData->ValueForBoxAlign(),
    6519                 :               xul->mBoxAlign, canStoreInRuleTree,
    6520                 :               SETDSC_ENUMERATED, parentXUL->mBoxAlign,
    6521               0 :               NS_STYLE_BOX_ALIGN_STRETCH, 0, 0, 0, 0);
    6522                 : 
    6523                 :   // box-direction: enum, inherit, initial
    6524               0 :   SetDiscrete(*aRuleData->ValueForBoxDirection(),
    6525                 :               xul->mBoxDirection, canStoreInRuleTree,
    6526                 :               SETDSC_ENUMERATED, parentXUL->mBoxDirection,
    6527               0 :               NS_STYLE_BOX_DIRECTION_NORMAL, 0, 0, 0, 0);
    6528                 : 
    6529                 :   // box-flex: factor, inherit
    6530               0 :   SetFactor(*aRuleData->ValueForBoxFlex(),
    6531                 :             xul->mBoxFlex, canStoreInRuleTree,
    6532               0 :             parentXUL->mBoxFlex, 0.0f);
    6533                 : 
    6534                 :   // box-orient: enum, inherit, initial
    6535               0 :   SetDiscrete(*aRuleData->ValueForBoxOrient(),
    6536                 :               xul->mBoxOrient, canStoreInRuleTree,
    6537                 :               SETDSC_ENUMERATED, parentXUL->mBoxOrient,
    6538               0 :               NS_STYLE_BOX_ORIENT_HORIZONTAL, 0, 0, 0, 0);
    6539                 : 
    6540                 :   // box-pack: enum, inherit, initial
    6541               0 :   SetDiscrete(*aRuleData->ValueForBoxPack(),
    6542                 :               xul->mBoxPack, canStoreInRuleTree,
    6543                 :               SETDSC_ENUMERATED, parentXUL->mBoxPack,
    6544               0 :               NS_STYLE_BOX_PACK_START, 0, 0, 0, 0);
    6545                 : 
    6546                 :   // box-ordinal-group: integer, inherit, initial
    6547               0 :   SetDiscrete(*aRuleData->ValueForBoxOrdinalGroup(),
    6548                 :               xul->mBoxOrdinal, canStoreInRuleTree,
    6549                 :               SETDSC_INTEGER, parentXUL->mBoxOrdinal, 1,
    6550               0 :               0, 0, 0, 0);
    6551                 : 
    6552               0 :   const nsCSSValue* stackSizingValue = aRuleData->ValueForStackSizing();
    6553               0 :   if (eCSSUnit_Inherit == stackSizingValue->GetUnit()) {
    6554               0 :     canStoreInRuleTree = false;
    6555               0 :     xul->mStretchStack = parentXUL->mStretchStack;
    6556               0 :   } else if (eCSSUnit_Initial == stackSizingValue->GetUnit()) {
    6557               0 :     xul->mStretchStack = true;
    6558               0 :   } else if (eCSSUnit_Enumerated == stackSizingValue->GetUnit()) {
    6559               0 :     xul->mStretchStack = stackSizingValue->GetIntValue() ==
    6560               0 :       NS_STYLE_STACK_SIZING_STRETCH_TO_FIT;
    6561                 :   }
    6562                 : 
    6563               0 :   COMPUTE_END_RESET(XUL, xul)
    6564                 : }
    6565                 : 
    6566                 : const void*
    6567               0 : nsRuleNode::ComputeColumnData(void* aStartStruct,
    6568                 :                               const nsRuleData* aRuleData,
    6569                 :                               nsStyleContext* aContext,
    6570                 :                               nsRuleNode* aHighestNode,
    6571                 :                               const RuleDetail aRuleDetail,
    6572                 :                               const bool aCanStoreInRuleTree)
    6573                 : {
    6574               0 :   COMPUTE_START_RESET(Column, (mPresContext), column, parent)
    6575                 : 
    6576                 :   // column-width: length, auto, inherit
    6577               0 :   SetCoord(*aRuleData->ValueForColumnWidth(),
    6578                 :            column->mColumnWidth, parent->mColumnWidth,
    6579                 :            SETCOORD_LAH | SETCOORD_INITIAL_AUTO |
    6580                 :            SETCOORD_CALC_LENGTH_ONLY | SETCOORD_CALC_CLAMP_NONNEGATIVE,
    6581               0 :            aContext, mPresContext, canStoreInRuleTree);
    6582                 : 
    6583                 :   // column-gap: length, inherit, normal
    6584               0 :   SetCoord(*aRuleData->ValueForColumnGap(),
    6585                 :            column->mColumnGap, parent->mColumnGap,
    6586                 :            SETCOORD_LH | SETCOORD_NORMAL | SETCOORD_INITIAL_NORMAL |
    6587                 :            SETCOORD_CALC_LENGTH_ONLY,
    6588               0 :            aContext, mPresContext, canStoreInRuleTree);
    6589                 :   // clamp negative calc() to 0
    6590               0 :   if (column->mColumnGap.GetUnit() == eStyleUnit_Coord) {
    6591                 :     column->mColumnGap.SetCoordValue(
    6592               0 :       NS_MAX(column->mColumnGap.GetCoordValue(), 0));
    6593                 :   }
    6594                 : 
    6595                 :   // column-count: auto, integer, inherit
    6596               0 :   const nsCSSValue* columnCountValue = aRuleData->ValueForColumnCount();
    6597               0 :   if (eCSSUnit_Auto == columnCountValue->GetUnit() ||
    6598               0 :       eCSSUnit_Initial == columnCountValue->GetUnit()) {
    6599               0 :     column->mColumnCount = NS_STYLE_COLUMN_COUNT_AUTO;
    6600               0 :   } else if (eCSSUnit_Integer == columnCountValue->GetUnit()) {
    6601               0 :     column->mColumnCount = columnCountValue->GetIntValue();
    6602                 :     // Max 1000 columns - wallpaper for bug 345583.
    6603               0 :     column->mColumnCount = NS_MIN(column->mColumnCount, 1000U);
    6604               0 :   } else if (eCSSUnit_Inherit == columnCountValue->GetUnit()) {
    6605               0 :     canStoreInRuleTree = false;
    6606               0 :     column->mColumnCount = parent->mColumnCount;
    6607                 :   }
    6608                 : 
    6609                 :   // column-rule-width: length, enum, inherit
    6610               0 :   const nsCSSValue& widthValue = *aRuleData->ValueForColumnRuleWidth();
    6611               0 :   if (eCSSUnit_Initial == widthValue.GetUnit()) {
    6612                 :     column->SetColumnRuleWidth(
    6613               0 :         (mPresContext->GetBorderWidthTable())[NS_STYLE_BORDER_WIDTH_MEDIUM]);
    6614                 :   }
    6615               0 :   else if (eCSSUnit_Enumerated == widthValue.GetUnit()) {
    6616               0 :     NS_ASSERTION(widthValue.GetIntValue() == NS_STYLE_BORDER_WIDTH_THIN ||
    6617                 :                  widthValue.GetIntValue() == NS_STYLE_BORDER_WIDTH_MEDIUM ||
    6618                 :                  widthValue.GetIntValue() == NS_STYLE_BORDER_WIDTH_THICK,
    6619                 :                  "Unexpected enum value");
    6620                 :     column->SetColumnRuleWidth(
    6621               0 :         (mPresContext->GetBorderWidthTable())[widthValue.GetIntValue()]);
    6622                 :   }
    6623               0 :   else if (eCSSUnit_Inherit == widthValue.GetUnit()) {
    6624               0 :     column->SetColumnRuleWidth(parent->GetComputedColumnRuleWidth());
    6625               0 :     canStoreInRuleTree = false;
    6626                 :   }
    6627               0 :   else if (widthValue.IsLengthUnit() || widthValue.IsCalcUnit()) {
    6628                 :     nscoord len =
    6629               0 :       CalcLength(widthValue, aContext, mPresContext, canStoreInRuleTree);
    6630               0 :     if (len < 0) {
    6631                 :       // FIXME: This is untested (by test_value_storage.html) for
    6632                 :       // column-rule-width since it gets covered up by the border
    6633                 :       // rounding code.
    6634               0 :       NS_ASSERTION(widthValue.IsCalcUnit(),
    6635                 :                    "parser should have rejected negative length");
    6636               0 :       len = 0;
    6637                 :     }
    6638               0 :     column->SetColumnRuleWidth(len);
    6639                 :   }
    6640                 : 
    6641                 :   // column-rule-style: enum, inherit
    6642               0 :   const nsCSSValue& styleValue = *aRuleData->ValueForColumnRuleStyle();
    6643               0 :   NS_ABORT_IF_FALSE(eCSSUnit_None != styleValue.GetUnit(),
    6644                 :                     "'none' should be handled as enumerated value");
    6645               0 :   if (eCSSUnit_Enumerated == styleValue.GetUnit()) {
    6646               0 :     column->mColumnRuleStyle = styleValue.GetIntValue();
    6647                 :   }
    6648               0 :   else if (eCSSUnit_Initial == styleValue.GetUnit()) {
    6649               0 :     column->mColumnRuleStyle = NS_STYLE_BORDER_STYLE_NONE;
    6650                 :   }
    6651               0 :   else if (eCSSUnit_Inherit == styleValue.GetUnit()) {
    6652               0 :     canStoreInRuleTree = false;
    6653               0 :     column->mColumnRuleStyle = parent->mColumnRuleStyle;
    6654                 :   }
    6655                 : 
    6656                 :   // column-rule-color: color, inherit
    6657               0 :   const nsCSSValue& colorValue = *aRuleData->ValueForColumnRuleColor();
    6658               0 :   if (eCSSUnit_Inherit == colorValue.GetUnit()) {
    6659               0 :     canStoreInRuleTree = false;
    6660               0 :     column->mColumnRuleColorIsForeground = false;
    6661               0 :     if (parent->mColumnRuleColorIsForeground) {
    6662               0 :       column->mColumnRuleColor = parentContext->GetStyleColor()->mColor;
    6663                 :     } else {
    6664               0 :       column->mColumnRuleColor = parent->mColumnRuleColor;
    6665                 :     }
    6666                 :   }
    6667               0 :   else if (eCSSUnit_Initial == colorValue.GetUnit() ||
    6668               0 :            eCSSUnit_Enumerated == colorValue.GetUnit()) {
    6669               0 :     column->mColumnRuleColorIsForeground = true;
    6670                 :   }
    6671               0 :   else if (SetColor(colorValue, 0, mPresContext, aContext,
    6672               0 :                     column->mColumnRuleColor, canStoreInRuleTree)) {
    6673               0 :     column->mColumnRuleColorIsForeground = false;
    6674                 :   }
    6675                 : 
    6676                 :   // column-fill: enum
    6677               0 :   SetDiscrete(*aRuleData->ValueForColumnFill(),
    6678                 :               column->mColumnFill, canStoreInRuleTree,
    6679                 :               SETDSC_ENUMERATED, parent->mColumnFill,
    6680                 :               NS_STYLE_COLUMN_FILL_BALANCE,
    6681               0 :               0, 0, 0, 0);
    6682                 : 
    6683               0 :   COMPUTE_END_RESET(Column, column)
    6684                 : }
    6685                 : 
    6686                 : static void
    6687               0 : SetSVGPaint(const nsCSSValue& aValue, const nsStyleSVGPaint& parentPaint,
    6688                 :             nsPresContext* aPresContext, nsStyleContext *aContext,
    6689                 :             nsStyleSVGPaint& aResult, nsStyleSVGPaintType aInitialPaintType,
    6690                 :             bool& aCanStoreInRuleTree)
    6691                 : {
    6692                 :   nscolor color;
    6693                 : 
    6694               0 :   if (aValue.GetUnit() == eCSSUnit_Inherit) {
    6695               0 :     aResult = parentPaint;
    6696               0 :     aCanStoreInRuleTree = false;
    6697               0 :   } else if (aValue.GetUnit() == eCSSUnit_None) {
    6698               0 :     aResult.SetType(eStyleSVGPaintType_None);
    6699               0 :   } else if (aValue.GetUnit() == eCSSUnit_Initial) {
    6700               0 :     aResult.SetType(aInitialPaintType);
    6701               0 :     aResult.mPaint.mColor = NS_RGB(0, 0, 0);
    6702               0 :     aResult.mFallbackColor = NS_RGB(0, 0, 0);
    6703               0 :   } else if (SetColor(aValue, NS_RGB(0, 0, 0), aPresContext, aContext,
    6704                 :                       color, aCanStoreInRuleTree)) {
    6705               0 :     aResult.SetType(eStyleSVGPaintType_Color);
    6706               0 :     aResult.mPaint.mColor = color;
    6707               0 :   } else if (aValue.GetUnit() == eCSSUnit_Pair) {
    6708               0 :     const nsCSSValuePair& pair = aValue.GetPairValue();
    6709               0 :     NS_ABORT_IF_FALSE(pair.mXValue.GetUnit() == eCSSUnit_URL,
    6710                 :                       "malformed paint server value");
    6711                 : 
    6712               0 :     aResult.SetType(eStyleSVGPaintType_Server);
    6713               0 :     aResult.mPaint.mPaintServer = pair.mXValue.GetURLValue();
    6714               0 :     NS_IF_ADDREF(aResult.mPaint.mPaintServer);
    6715                 : 
    6716               0 :     if (pair.mYValue.GetUnit() == eCSSUnit_None) {
    6717               0 :       aResult.mFallbackColor = NS_RGBA(0, 0, 0, 0);
    6718                 :     } else {
    6719               0 :       NS_ABORT_IF_FALSE(pair.mYValue.GetUnit() != eCSSUnit_Inherit,
    6720                 :                         "cannot inherit fallback colour");
    6721                 :       SetColor(pair.mYValue, NS_RGB(0, 0, 0), aPresContext, aContext,
    6722               0 :                aResult.mFallbackColor, aCanStoreInRuleTree);
    6723                 :     }
    6724                 :   } else {
    6725               0 :     NS_ABORT_IF_FALSE(aValue.GetUnit() == eCSSUnit_Null,
    6726                 :                       "malformed paint server value");
    6727                 :   }
    6728               0 : }
    6729                 : 
    6730                 : const void*
    6731               0 : nsRuleNode::ComputeSVGData(void* aStartStruct,
    6732                 :                            const nsRuleData* aRuleData,
    6733                 :                            nsStyleContext* aContext,
    6734                 :                            nsRuleNode* aHighestNode,
    6735                 :                            const RuleDetail aRuleDetail,
    6736                 :                            const bool aCanStoreInRuleTree)
    6737                 : {
    6738               0 :   COMPUTE_START_INHERITED(SVG, (), svg, parentSVG)
    6739                 : 
    6740                 :   // clip-rule: enum, inherit, initial
    6741               0 :   SetDiscrete(*aRuleData->ValueForClipRule(),
    6742                 :               svg->mClipRule, canStoreInRuleTree,
    6743                 :               SETDSC_ENUMERATED, parentSVG->mClipRule,
    6744               0 :               NS_STYLE_FILL_RULE_NONZERO, 0, 0, 0, 0);
    6745                 : 
    6746                 :   // color-interpolation: enum, inherit, initial
    6747               0 :   SetDiscrete(*aRuleData->ValueForColorInterpolation(),
    6748                 :               svg->mColorInterpolation, canStoreInRuleTree,
    6749                 :               SETDSC_ENUMERATED, parentSVG->mColorInterpolation,
    6750               0 :               NS_STYLE_COLOR_INTERPOLATION_SRGB, 0, 0, 0, 0);
    6751                 : 
    6752                 :   // color-interpolation-filters: enum, inherit, initial
    6753               0 :   SetDiscrete(*aRuleData->ValueForColorInterpolationFilters(),
    6754                 :               svg->mColorInterpolationFilters, canStoreInRuleTree,
    6755                 :               SETDSC_ENUMERATED, parentSVG->mColorInterpolationFilters,
    6756               0 :               NS_STYLE_COLOR_INTERPOLATION_LINEARRGB, 0, 0, 0, 0);
    6757                 : 
    6758                 :   // fill:
    6759               0 :   SetSVGPaint(*aRuleData->ValueForFill(),
    6760                 :               parentSVG->mFill, mPresContext, aContext,
    6761               0 :               svg->mFill, eStyleSVGPaintType_Color, canStoreInRuleTree);
    6762                 : 
    6763                 :   // fill-opacity: factor, inherit, initial
    6764               0 :   SetFactor(*aRuleData->ValueForFillOpacity(),
    6765                 :             svg->mFillOpacity, canStoreInRuleTree,
    6766               0 :             parentSVG->mFillOpacity, 1.0f, SETFCT_OPACITY);
    6767                 : 
    6768                 :   // fill-rule: enum, inherit, initial
    6769               0 :   SetDiscrete(*aRuleData->ValueForFillRule(),
    6770                 :               svg->mFillRule, canStoreInRuleTree,
    6771                 :               SETDSC_ENUMERATED, parentSVG->mFillRule,
    6772               0 :               NS_STYLE_FILL_RULE_NONZERO, 0, 0, 0, 0);
    6773                 : 
    6774                 :   // image-rendering: enum, inherit
    6775               0 :   SetDiscrete(*aRuleData->ValueForImageRendering(),
    6776                 :               svg->mImageRendering, canStoreInRuleTree,
    6777                 :               SETDSC_ENUMERATED, parentSVG->mImageRendering,
    6778               0 :               NS_STYLE_IMAGE_RENDERING_AUTO, 0, 0, 0, 0);
    6779                 : 
    6780                 :   // marker-end: url, none, inherit
    6781               0 :   const nsCSSValue* markerEndValue = aRuleData->ValueForMarkerEnd();
    6782               0 :   if (eCSSUnit_URL == markerEndValue->GetUnit()) {
    6783               0 :     svg->mMarkerEnd = markerEndValue->GetURLValue();
    6784               0 :   } else if (eCSSUnit_None == markerEndValue->GetUnit() ||
    6785               0 :              eCSSUnit_Initial == markerEndValue->GetUnit()) {
    6786               0 :     svg->mMarkerEnd = nsnull;
    6787               0 :   } else if (eCSSUnit_Inherit == markerEndValue->GetUnit()) {
    6788               0 :     canStoreInRuleTree = false;
    6789               0 :     svg->mMarkerEnd = parentSVG->mMarkerEnd;
    6790                 :   }
    6791                 : 
    6792                 :   // marker-mid: url, none, inherit
    6793               0 :   const nsCSSValue* markerMidValue = aRuleData->ValueForMarkerMid();
    6794               0 :   if (eCSSUnit_URL == markerMidValue->GetUnit()) {
    6795               0 :     svg->mMarkerMid = markerMidValue->GetURLValue();
    6796               0 :   } else if (eCSSUnit_None == markerMidValue->GetUnit() ||
    6797               0 :              eCSSUnit_Initial == markerMidValue->GetUnit()) {
    6798               0 :     svg->mMarkerMid = nsnull;
    6799               0 :   } else if (eCSSUnit_Inherit == markerMidValue->GetUnit()) {
    6800               0 :     canStoreInRuleTree = false;
    6801               0 :     svg->mMarkerMid = parentSVG->mMarkerMid;
    6802                 :   }
    6803                 : 
    6804                 :   // marker-start: url, none, inherit
    6805               0 :   const nsCSSValue* markerStartValue = aRuleData->ValueForMarkerStart();
    6806               0 :   if (eCSSUnit_URL == markerStartValue->GetUnit()) {
    6807               0 :     svg->mMarkerStart = markerStartValue->GetURLValue();
    6808               0 :   } else if (eCSSUnit_None == markerStartValue->GetUnit() ||
    6809               0 :              eCSSUnit_Initial == markerStartValue->GetUnit()) {
    6810               0 :     svg->mMarkerStart = nsnull;
    6811               0 :   } else if (eCSSUnit_Inherit == markerStartValue->GetUnit()) {
    6812               0 :     canStoreInRuleTree = false;
    6813               0 :     svg->mMarkerStart = parentSVG->mMarkerStart;
    6814                 :   }
    6815                 : 
    6816                 :   // shape-rendering: enum, inherit
    6817               0 :   SetDiscrete(*aRuleData->ValueForShapeRendering(),
    6818                 :               svg->mShapeRendering, canStoreInRuleTree,
    6819                 :               SETDSC_ENUMERATED, parentSVG->mShapeRendering,
    6820               0 :               NS_STYLE_SHAPE_RENDERING_AUTO, 0, 0, 0, 0);
    6821                 : 
    6822                 :   // stroke:
    6823               0 :   SetSVGPaint(*aRuleData->ValueForStroke(),
    6824                 :               parentSVG->mStroke, mPresContext, aContext,
    6825               0 :               svg->mStroke, eStyleSVGPaintType_None, canStoreInRuleTree);
    6826                 : 
    6827                 :   // stroke-dasharray: <dasharray>, none, inherit
    6828               0 :   const nsCSSValue* strokeDasharrayValue = aRuleData->ValueForStrokeDasharray();
    6829               0 :   switch (strokeDasharrayValue->GetUnit()) {
    6830                 :   case eCSSUnit_Null:
    6831               0 :     break;
    6832                 : 
    6833                 :   case eCSSUnit_Inherit:
    6834               0 :     canStoreInRuleTree = false;
    6835                 :     // only do the copy if weren't already set up by the copy constructor
    6836                 :     // FIXME Bug 389408: This is broken when aStartStruct is non-null!
    6837               0 :     if (!svg->mStrokeDasharray) {
    6838               0 :       svg->mStrokeDasharrayLength = parentSVG->mStrokeDasharrayLength;
    6839               0 :       if (svg->mStrokeDasharrayLength) {
    6840               0 :         svg->mStrokeDasharray = new nsStyleCoord[svg->mStrokeDasharrayLength];
    6841               0 :         if (svg->mStrokeDasharray)
    6842                 :           memcpy(svg->mStrokeDasharray,
    6843                 :                  parentSVG->mStrokeDasharray,
    6844               0 :                  svg->mStrokeDasharrayLength * sizeof(nsStyleCoord));
    6845                 :         else
    6846               0 :           svg->mStrokeDasharrayLength = 0;
    6847                 :       }
    6848                 :     }
    6849               0 :     break;
    6850                 : 
    6851                 :   case eCSSUnit_Initial:
    6852                 :   case eCSSUnit_None:
    6853               0 :     delete [] svg->mStrokeDasharray;
    6854               0 :     svg->mStrokeDasharray = nsnull;
    6855               0 :     svg->mStrokeDasharrayLength = 0;
    6856               0 :     break;
    6857                 : 
    6858                 :   case eCSSUnit_List:
    6859                 :   case eCSSUnit_ListDep: {
    6860               0 :     delete [] svg->mStrokeDasharray;
    6861               0 :     svg->mStrokeDasharray = nsnull;
    6862               0 :     svg->mStrokeDasharrayLength = 0;
    6863                 : 
    6864                 :     // count number of values
    6865               0 :     const nsCSSValueList *value = strokeDasharrayValue->GetListValue();
    6866               0 :     svg->mStrokeDasharrayLength = ListLength(value);
    6867                 : 
    6868               0 :     NS_ASSERTION(svg->mStrokeDasharrayLength != 0, "no dasharray items");
    6869                 : 
    6870               0 :     svg->mStrokeDasharray = new nsStyleCoord[svg->mStrokeDasharrayLength];
    6871                 : 
    6872               0 :     if (svg->mStrokeDasharray) {
    6873               0 :       PRUint32 i = 0;
    6874               0 :       while (nsnull != value) {
    6875                 :         SetCoord(value->mValue,
    6876               0 :                  svg->mStrokeDasharray[i++], nsStyleCoord(),
    6877                 :                  SETCOORD_LP | SETCOORD_FACTOR,
    6878               0 :                  aContext, mPresContext, canStoreInRuleTree);
    6879               0 :         value = value->mNext;
    6880                 :       }
    6881                 :     } else {
    6882               0 :       svg->mStrokeDasharrayLength = 0;
    6883                 :     }
    6884               0 :     break;
    6885                 :   }
    6886                 : 
    6887                 :   default:
    6888               0 :     NS_ABORT_IF_FALSE(false, "unrecognized dasharray unit");
    6889                 :   }
    6890                 : 
    6891                 :   // stroke-dashoffset: <dashoffset>, inherit
    6892               0 :   SetCoord(*aRuleData->ValueForStrokeDashoffset(),
    6893                 :            svg->mStrokeDashoffset, parentSVG->mStrokeDashoffset,
    6894                 :            SETCOORD_LPH | SETCOORD_FACTOR | SETCOORD_INITIAL_ZERO,
    6895               0 :            aContext, mPresContext, canStoreInRuleTree);
    6896                 : 
    6897                 :   // stroke-linecap: enum, inherit, initial
    6898               0 :   SetDiscrete(*aRuleData->ValueForStrokeLinecap(),
    6899                 :               svg->mStrokeLinecap, canStoreInRuleTree,
    6900                 :               SETDSC_ENUMERATED, parentSVG->mStrokeLinecap,
    6901               0 :               NS_STYLE_STROKE_LINECAP_BUTT, 0, 0, 0, 0);
    6902                 : 
    6903                 :   // stroke-linejoin: enum, inherit, initial
    6904               0 :   SetDiscrete(*aRuleData->ValueForStrokeLinejoin(),
    6905                 :               svg->mStrokeLinejoin, canStoreInRuleTree,
    6906                 :               SETDSC_ENUMERATED, parentSVG->mStrokeLinejoin,
    6907               0 :               NS_STYLE_STROKE_LINEJOIN_MITER, 0, 0, 0, 0);
    6908                 : 
    6909                 :   // stroke-miterlimit: <miterlimit>, inherit
    6910               0 :   SetFactor(*aRuleData->ValueForStrokeMiterlimit(),
    6911                 :             svg->mStrokeMiterlimit,
    6912                 :             canStoreInRuleTree,
    6913               0 :             parentSVG->mStrokeMiterlimit, 4.0f);
    6914                 : 
    6915                 :   // stroke-opacity:
    6916               0 :   SetFactor(*aRuleData->ValueForStrokeOpacity(),
    6917                 :             svg->mStrokeOpacity, canStoreInRuleTree,
    6918               0 :             parentSVG->mStrokeOpacity, 1.0f, SETFCT_OPACITY);
    6919                 : 
    6920                 :   // stroke-width:
    6921               0 :   const nsCSSValue* strokeWidthValue = aRuleData->ValueForStrokeWidth();
    6922               0 :   if (eCSSUnit_Initial == strokeWidthValue->GetUnit()) {
    6923               0 :     svg->mStrokeWidth.SetCoordValue(nsPresContext::CSSPixelsToAppUnits(1));
    6924                 :   } else {
    6925                 :     SetCoord(*strokeWidthValue,
    6926                 :              svg->mStrokeWidth, parentSVG->mStrokeWidth,
    6927                 :              SETCOORD_LPH | SETCOORD_FACTOR,
    6928               0 :              aContext, mPresContext, canStoreInRuleTree);
    6929                 :   }
    6930                 : 
    6931                 :   // text-anchor: enum, inherit, initial
    6932               0 :   SetDiscrete(*aRuleData->ValueForTextAnchor(),
    6933                 :               svg->mTextAnchor, canStoreInRuleTree,
    6934                 :               SETDSC_ENUMERATED, parentSVG->mTextAnchor,
    6935               0 :               NS_STYLE_TEXT_ANCHOR_START, 0, 0, 0, 0);
    6936                 : 
    6937                 :   // text-rendering: enum, inherit, initial
    6938               0 :   SetDiscrete(*aRuleData->ValueForTextRendering(),
    6939                 :               svg->mTextRendering, canStoreInRuleTree,
    6940                 :               SETDSC_ENUMERATED, parentSVG->mTextRendering,
    6941               0 :               NS_STYLE_TEXT_RENDERING_AUTO, 0, 0, 0, 0);
    6942                 : 
    6943               0 :   COMPUTE_END_INHERITED(SVG, svg)
    6944                 : }
    6945                 : 
    6946                 : const void*
    6947               0 : nsRuleNode::ComputeSVGResetData(void* aStartStruct,
    6948                 :                                 const nsRuleData* aRuleData,
    6949                 :                                 nsStyleContext* aContext,
    6950                 :                                 nsRuleNode* aHighestNode,
    6951                 :                                 const RuleDetail aRuleDetail,
    6952                 :                                 const bool aCanStoreInRuleTree)
    6953                 : {
    6954               0 :   COMPUTE_START_RESET(SVGReset, (), svgReset, parentSVGReset)
    6955                 : 
    6956                 :   // stop-color:
    6957               0 :   const nsCSSValue* stopColorValue = aRuleData->ValueForStopColor();
    6958               0 :   if (eCSSUnit_Initial == stopColorValue->GetUnit()) {
    6959               0 :     svgReset->mStopColor = NS_RGB(0, 0, 0);
    6960                 :   } else {
    6961                 :     SetColor(*stopColorValue, parentSVGReset->mStopColor,
    6962               0 :              mPresContext, aContext, svgReset->mStopColor, canStoreInRuleTree);
    6963                 :   }
    6964                 : 
    6965                 :   // flood-color:
    6966               0 :   const nsCSSValue* floodColorValue = aRuleData->ValueForFloodColor();
    6967               0 :   if (eCSSUnit_Initial == floodColorValue->GetUnit()) {
    6968               0 :     svgReset->mFloodColor = NS_RGB(0, 0, 0);
    6969                 :   } else {
    6970                 :     SetColor(*floodColorValue, parentSVGReset->mFloodColor,
    6971               0 :              mPresContext, aContext, svgReset->mFloodColor, canStoreInRuleTree);
    6972                 :   }
    6973                 : 
    6974                 :   // lighting-color:
    6975               0 :   const nsCSSValue* lightingColorValue = aRuleData->ValueForLightingColor();
    6976               0 :   if (eCSSUnit_Initial == lightingColorValue->GetUnit()) {
    6977               0 :     svgReset->mLightingColor = NS_RGB(255, 255, 255);
    6978                 :   } else {
    6979                 :     SetColor(*lightingColorValue, parentSVGReset->mLightingColor,
    6980                 :              mPresContext, aContext, svgReset->mLightingColor,
    6981               0 :              canStoreInRuleTree);
    6982                 :   }
    6983                 : 
    6984                 :   // clip-path: url, none, inherit
    6985               0 :   const nsCSSValue* clipPathValue = aRuleData->ValueForClipPath();
    6986               0 :   if (eCSSUnit_URL == clipPathValue->GetUnit()) {
    6987               0 :     svgReset->mClipPath = clipPathValue->GetURLValue();
    6988               0 :   } else if (eCSSUnit_None == clipPathValue->GetUnit() ||
    6989               0 :              eCSSUnit_Initial == clipPathValue->GetUnit()) {
    6990               0 :     svgReset->mClipPath = nsnull;
    6991               0 :   } else if (eCSSUnit_Inherit == clipPathValue->GetUnit()) {
    6992               0 :     canStoreInRuleTree = false;
    6993               0 :     svgReset->mClipPath = parentSVGReset->mClipPath;
    6994                 :   }
    6995                 : 
    6996                 :   // stop-opacity:
    6997               0 :   SetFactor(*aRuleData->ValueForStopOpacity(),
    6998                 :             svgReset->mStopOpacity, canStoreInRuleTree,
    6999               0 :             parentSVGReset->mStopOpacity, 1.0f, SETFCT_OPACITY);
    7000                 : 
    7001                 :   // flood-opacity:
    7002               0 :   SetFactor(*aRuleData->ValueForFloodOpacity(),
    7003                 :             svgReset->mFloodOpacity, canStoreInRuleTree,
    7004               0 :             parentSVGReset->mFloodOpacity, 1.0f, SETFCT_OPACITY);
    7005                 : 
    7006                 :   // dominant-baseline: enum, inherit, initial
    7007               0 :   SetDiscrete(*aRuleData->ValueForDominantBaseline(),
    7008                 :               svgReset->mDominantBaseline,
    7009                 :               canStoreInRuleTree, SETDSC_ENUMERATED,
    7010                 :               parentSVGReset->mDominantBaseline,
    7011               0 :               NS_STYLE_DOMINANT_BASELINE_AUTO, 0, 0, 0, 0);
    7012                 : 
    7013                 :   // filter: url, none, inherit
    7014               0 :   const nsCSSValue* filterValue = aRuleData->ValueForFilter();
    7015               0 :   if (eCSSUnit_URL == filterValue->GetUnit()) {
    7016               0 :     svgReset->mFilter = filterValue->GetURLValue();
    7017               0 :   } else if (eCSSUnit_None == filterValue->GetUnit() ||
    7018               0 :              eCSSUnit_Initial == filterValue->GetUnit()) {
    7019               0 :     svgReset->mFilter = nsnull;
    7020               0 :   } else if (eCSSUnit_Inherit == filterValue->GetUnit()) {
    7021               0 :     canStoreInRuleTree = false;
    7022               0 :     svgReset->mFilter = parentSVGReset->mFilter;
    7023                 :   }
    7024                 : 
    7025                 :   // mask: url, none, inherit
    7026               0 :   const nsCSSValue* maskValue = aRuleData->ValueForMask();
    7027               0 :   if (eCSSUnit_URL == maskValue->GetUnit()) {
    7028               0 :     svgReset->mMask = maskValue->GetURLValue();
    7029               0 :   } else if (eCSSUnit_None == maskValue->GetUnit() ||
    7030               0 :              eCSSUnit_Initial == maskValue->GetUnit()) {
    7031               0 :     svgReset->mMask = nsnull;
    7032               0 :   } else if (eCSSUnit_Inherit == maskValue->GetUnit()) {
    7033               0 :     canStoreInRuleTree = false;
    7034               0 :     svgReset->mMask = parentSVGReset->mMask;
    7035                 :   }
    7036                 : 
    7037               0 :   COMPUTE_END_RESET(SVGReset, svgReset)
    7038                 : }
    7039                 : 
    7040                 : inline const void*
    7041               0 : nsRuleNode::GetParentData(const nsStyleStructID aSID)
    7042                 : {
    7043               0 :   NS_PRECONDITION(mDependentBits & nsCachedStyleData::GetBitForSID(aSID),
    7044                 :                   "should be called when node depends on parent data");
    7045               0 :   NS_ASSERTION(mStyleData.GetStyleData(aSID) == nsnull,
    7046                 :                "both struct and dependent bits present");
    7047                 :   // Walk up the rule tree from this rule node (towards less specific
    7048                 :   // rules).
    7049               0 :   PRUint32 bit = nsCachedStyleData::GetBitForSID(aSID);
    7050               0 :   nsRuleNode *ruleNode = mParent;
    7051               0 :   while (ruleNode->mDependentBits & bit) {
    7052               0 :     NS_ASSERTION(ruleNode->mStyleData.GetStyleData(aSID) == nsnull,
    7053                 :                  "both struct and dependent bits present");
    7054               0 :     ruleNode = ruleNode->mParent;
    7055                 :   }
    7056                 : 
    7057               0 :   return ruleNode->mStyleData.GetStyleData(aSID);
    7058                 : }
    7059                 : 
    7060                 : #define STYLE_STRUCT(name_, checkdata_cb_, ctor_args_)                      \
    7061                 : inline const nsStyle##name_ *                                               \
    7062                 : nsRuleNode::GetParent##name_()                                              \
    7063                 : {                                                                           \
    7064                 :   NS_PRECONDITION(mDependentBits &                                          \
    7065                 :                   nsCachedStyleData::GetBitForSID(eStyleStruct_##name_),    \
    7066                 :                   "should be called when node depends on parent data");     \
    7067                 :   NS_ASSERTION(mStyleData.GetStyle##name_() == nsnull,                      \
    7068                 :                "both struct and dependent bits present");                   \
    7069                 :   /* Walk up the rule tree from this rule node (towards less specific */    \
    7070                 :   /* rules). */                                                             \
    7071                 :   PRUint32 bit = nsCachedStyleData::GetBitForSID(eStyleStruct_##name_);     \
    7072                 :   nsRuleNode *ruleNode = mParent;                                           \
    7073                 :   while (ruleNode->mDependentBits & bit) {                                  \
    7074                 :     NS_ASSERTION(ruleNode->mStyleData.GetStyle##name_() == nsnull,          \
    7075                 :                  "both struct and dependent bits present");                 \
    7076                 :     ruleNode = ruleNode->mParent;                                           \
    7077                 :   }                                                                         \
    7078                 :                                                                             \
    7079                 :   return ruleNode->mStyleData.GetStyle##name_();                            \
    7080                 : }
    7081                 : #include "nsStyleStructList.h"
    7082                 : #undef STYLE_STRUCT
    7083                 : 
    7084                 : const void*
    7085               0 : nsRuleNode::GetStyleData(nsStyleStructID aSID,
    7086                 :                          nsStyleContext* aContext,
    7087                 :                          bool aComputeData)
    7088                 : {
    7089                 :   const void *data;
    7090               0 :   if (mDependentBits & nsCachedStyleData::GetBitForSID(aSID)) {
    7091                 :     // We depend on an ancestor for this struct since the cached struct
    7092                 :     // it has is also appropriate for this rule node.  Just go up the
    7093                 :     // rule tree and return the first cached struct we find.
    7094               0 :     data = GetParentData(aSID);
    7095               0 :     NS_ASSERTION(data, "dependent bits set but no cached struct present");
    7096               0 :     return data;
    7097                 :   }
    7098                 : 
    7099               0 :   data = mStyleData.GetStyleData(aSID);
    7100               0 :   if (NS_LIKELY(data != nsnull))
    7101               0 :     return data; // We have a fully specified struct. Just return it.
    7102                 : 
    7103               0 :   if (NS_UNLIKELY(!aComputeData))
    7104               0 :     return nsnull;
    7105                 : 
    7106                 :   // Nothing is cached.  We'll have to delve further and examine our rules.
    7107               0 :   data = WalkRuleTree(aSID, aContext);
    7108                 : 
    7109               0 :   if (NS_LIKELY(data != nsnull))
    7110               0 :     return data;
    7111                 : 
    7112               0 :   NS_NOTREACHED("could not create style struct");
    7113                 :   // To ensure that |GetStyleData| never returns null (even when we're
    7114                 :   // out of memory), we'll get the style set and get a copy of the
    7115                 :   // default values for the given style struct from the set.  Note that
    7116                 :   // this works fine even if |this| is a rule node that has been
    7117                 :   // destroyed (leftover from a previous rule tree) but is somehow still
    7118                 :   // used.
    7119                 :   return mPresContext->PresShell()->StyleSet()->
    7120               0 :     DefaultStyleData()->GetStyleData(aSID);
    7121                 : }
    7122                 : 
    7123                 : // See comments above in GetStyleData for an explanation of what the
    7124                 : // code below does.
    7125                 : #define STYLE_STRUCT(name_, checkdata_cb_, ctor_args_)                        \
    7126                 : const nsStyle##name_*                                                         \
    7127                 : nsRuleNode::GetStyle##name_(nsStyleContext* aContext, bool aComputeData)    \
    7128                 : {                                                                             \
    7129                 :   const nsStyle##name_ *data;                                                 \
    7130                 :   if (mDependentBits &                                                        \
    7131                 :       nsCachedStyleData::GetBitForSID(eStyleStruct_##name_)) {                \
    7132                 :     data = GetParent##name_();                                                \
    7133                 :     NS_ASSERTION(data, "dependent bits set but no cached struct present");    \
    7134                 :     return data;                                                              \
    7135                 :   }                                                                           \
    7136                 :                                                                               \
    7137                 :   data = mStyleData.GetStyle##name_();                                        \
    7138                 :   if (NS_LIKELY(data != nsnull))                                              \
    7139                 :     return data;                                                              \
    7140                 :                                                                               \
    7141                 :   if (NS_UNLIKELY(!aComputeData))                                             \
    7142                 :     return nsnull;                                                            \
    7143                 :                                                                               \
    7144                 :   data = static_cast<const nsStyle##name_ *>                                  \
    7145                 :            (WalkRuleTree(eStyleStruct_##name_, aContext));                    \
    7146                 :                                                                               \
    7147                 :   if (NS_LIKELY(data != nsnull))                                              \
    7148                 :     return data;                                                              \
    7149                 :                                                                               \
    7150                 :   NS_NOTREACHED("could not create style struct");                             \
    7151                 :   return                                                                      \
    7152                 :     static_cast<const nsStyle##name_ *>(                                      \
    7153                 :                    mPresContext->PresShell()->StyleSet()->                    \
    7154                 :                      DefaultStyleData()->GetStyleData(eStyleStruct_##name_)); \
    7155                 : }
    7156                 : #include "nsStyleStructList.h"
    7157                 : #undef STYLE_STRUCT
    7158                 : 
    7159                 : void
    7160               0 : nsRuleNode::Mark()
    7161                 : {
    7162               0 :   for (nsRuleNode *node = this;
    7163               0 :        node && !(node->mDependentBits & NS_RULE_NODE_GC_MARK);
    7164                 :        node = node->mParent)
    7165               0 :     node->mDependentBits |= NS_RULE_NODE_GC_MARK;
    7166               0 : }
    7167                 : 
    7168                 : static PLDHashOperator
    7169               0 : SweepRuleNodeChildren(PLDHashTable *table, PLDHashEntryHdr *hdr,
    7170                 :                       PRUint32 number, void *arg)
    7171                 : {
    7172               0 :   ChildrenHashEntry *entry = static_cast<ChildrenHashEntry*>(hdr);
    7173               0 :   if (entry->mRuleNode->Sweep())
    7174               0 :     return PL_DHASH_REMOVE; // implies NEXT, unless |ed with STOP
    7175               0 :   return PL_DHASH_NEXT;
    7176                 : }
    7177                 : 
    7178                 : bool
    7179               0 : nsRuleNode::Sweep()
    7180                 : {
    7181                 :   // If we're not marked, then we have to delete ourself.
    7182                 :   // However, we never allow the root node to GC itself, because nsStyleSet
    7183                 :   // wants to hold onto the root node and not worry about re-creating a
    7184                 :   // rule walker if the root node is deleted.
    7185               0 :   if (!(mDependentBits & NS_RULE_NODE_GC_MARK) &&
    7186                 :       // Skip this only if we're the *current* root and not an old one.
    7187               0 :       !(IsRoot() && mPresContext->StyleSet()->GetRuleTree() == this)) {
    7188               0 :     Destroy();
    7189               0 :     return true;
    7190                 :   }
    7191                 : 
    7192                 :   // Clear our mark, for the next time around.
    7193               0 :   mDependentBits &= ~NS_RULE_NODE_GC_MARK;
    7194                 : 
    7195                 :   // Call sweep on the children, since some may not be marked, and
    7196                 :   // remove any deleted children from the child lists.
    7197               0 :   if (HaveChildren()) {
    7198                 :     PRUint32 childrenDestroyed;
    7199               0 :     if (ChildrenAreHashed()) {
    7200               0 :       PLDHashTable *children = ChildrenHash();
    7201               0 :       PRUint32 oldChildCount = children->entryCount;
    7202               0 :       PL_DHashTableEnumerate(children, SweepRuleNodeChildren, nsnull);
    7203               0 :       childrenDestroyed = children->entryCount - oldChildCount;
    7204                 :     } else {
    7205               0 :       childrenDestroyed = 0;
    7206               0 :       for (nsRuleNode **children = ChildrenListPtr(); *children; ) {
    7207               0 :         nsRuleNode *next = (*children)->mNextSibling;
    7208               0 :         if ((*children)->Sweep()) {
    7209                 :           // This rule node was destroyed, so implicitly advance by
    7210                 :           // making *children point to the next entry.
    7211               0 :           *children = next;
    7212               0 :           ++childrenDestroyed;
    7213                 :         } else {
    7214                 :           // Advance.
    7215               0 :           children = &(*children)->mNextSibling;
    7216                 :         }
    7217                 :       }
    7218                 :     }
    7219               0 :     mRefCnt -= childrenDestroyed;
    7220               0 :     NS_POSTCONDITION(IsRoot() || mRefCnt > 0,
    7221                 :                      "We didn't get swept, so we'd better have style contexts "
    7222                 :                      "pointing to us or to one of our descendants, which means "
    7223                 :                      "we'd better have a nonzero mRefCnt here!");
    7224                 :   }
    7225               0 :   return false;
    7226                 : }
    7227                 : 
    7228                 : /* static */ bool
    7229               0 : nsRuleNode::HasAuthorSpecifiedRules(nsStyleContext* aStyleContext,
    7230                 :                                     PRUint32 ruleTypeMask,
    7231                 :                                     bool aAuthorColorsAllowed)
    7232                 : {
    7233               0 :   PRUint32 inheritBits = 0;
    7234               0 :   if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BACKGROUND)
    7235               0 :     inheritBits |= NS_STYLE_INHERIT_BIT(Background);
    7236                 : 
    7237               0 :   if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BORDER)
    7238               0 :     inheritBits |= NS_STYLE_INHERIT_BIT(Border);
    7239                 : 
    7240               0 :   if (ruleTypeMask & NS_AUTHOR_SPECIFIED_PADDING)
    7241               0 :     inheritBits |= NS_STYLE_INHERIT_BIT(Padding);
    7242                 : 
    7243                 :   // properties in the SIDS, whether or not we care about them
    7244               0 :   size_t nprops = 0, backgroundOffset, borderOffset, paddingOffset;
    7245                 : 
    7246               0 :   if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BACKGROUND) {
    7247               0 :     backgroundOffset = nprops;
    7248               0 :     nprops += nsCSSProps::PropertyCountInStruct(eStyleStruct_Background);
    7249                 :   }
    7250                 : 
    7251               0 :   if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BORDER) {
    7252               0 :     borderOffset = nprops;
    7253               0 :     nprops += nsCSSProps::PropertyCountInStruct(eStyleStruct_Border);
    7254                 :   }
    7255                 : 
    7256               0 :   if (ruleTypeMask & NS_AUTHOR_SPECIFIED_PADDING) {
    7257               0 :     paddingOffset = nprops;
    7258               0 :     nprops += nsCSSProps::PropertyCountInStruct(eStyleStruct_Padding);
    7259                 :   }
    7260                 : 
    7261               0 :   void* dataStorage = alloca(nprops * sizeof(nsCSSValue));
    7262               0 :   AutoCSSValueArray dataArray(dataStorage, nprops);
    7263                 : 
    7264                 :   /* We're relying on the use of |aStyleContext| not mutating it! */
    7265                 :   nsRuleData ruleData(inheritBits, dataArray.get(),
    7266               0 :                       aStyleContext->PresContext(), aStyleContext);
    7267                 : 
    7268               0 :   if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BACKGROUND) {
    7269               0 :     ruleData.mValueOffsets[eStyleStruct_Background] = backgroundOffset;
    7270                 :   }
    7271                 : 
    7272               0 :   if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BORDER) {
    7273               0 :     ruleData.mValueOffsets[eStyleStruct_Border] = borderOffset;
    7274                 :   }
    7275                 : 
    7276               0 :   if (ruleTypeMask & NS_AUTHOR_SPECIFIED_PADDING) {
    7277               0 :     ruleData.mValueOffsets[eStyleStruct_Padding] = paddingOffset;
    7278                 :   }
    7279                 : 
    7280                 :   static const nsCSSProperty backgroundValues[] = {
    7281                 :     eCSSProperty_background_color,
    7282                 :     eCSSProperty_background_image,
    7283                 :   };
    7284                 : 
    7285                 :   static const nsCSSProperty borderValues[] = {
    7286                 :     eCSSProperty_border_top_color,
    7287                 :     eCSSProperty_border_top_style,
    7288                 :     eCSSProperty_border_top_width,
    7289                 :     eCSSProperty_border_right_color_value,
    7290                 :     eCSSProperty_border_right_style_value,
    7291                 :     eCSSProperty_border_right_width_value,
    7292                 :     eCSSProperty_border_bottom_color,
    7293                 :     eCSSProperty_border_bottom_style,
    7294                 :     eCSSProperty_border_bottom_width,
    7295                 :     eCSSProperty_border_left_color_value,
    7296                 :     eCSSProperty_border_left_style_value,
    7297                 :     eCSSProperty_border_left_width_value,
    7298                 :     eCSSProperty_border_start_color_value,
    7299                 :     eCSSProperty_border_start_style_value,
    7300                 :     eCSSProperty_border_start_width_value,
    7301                 :     eCSSProperty_border_end_color_value,
    7302                 :     eCSSProperty_border_end_style_value,
    7303                 :     eCSSProperty_border_end_width_value,
    7304                 :     eCSSProperty_border_top_left_radius,
    7305                 :     eCSSProperty_border_top_right_radius,
    7306                 :     eCSSProperty_border_bottom_right_radius,
    7307                 :     eCSSProperty_border_bottom_left_radius,
    7308                 :   };
    7309                 : 
    7310                 :   static const nsCSSProperty paddingValues[] = {
    7311                 :     eCSSProperty_padding_top,
    7312                 :     eCSSProperty_padding_right_value,
    7313                 :     eCSSProperty_padding_bottom,
    7314                 :     eCSSProperty_padding_left_value,
    7315                 :     eCSSProperty_padding_start_value,
    7316                 :     eCSSProperty_padding_end_value,
    7317                 :   };
    7318                 : 
    7319                 :   // Number of properties we care about
    7320               0 :   size_t nValues = 0;
    7321                 : 
    7322                 :   nsCSSValue* values[NS_ARRAY_LENGTH(backgroundValues) +
    7323                 :                      NS_ARRAY_LENGTH(borderValues) +
    7324                 :                      NS_ARRAY_LENGTH(paddingValues)];
    7325                 : 
    7326                 :   nsCSSProperty properties[NS_ARRAY_LENGTH(backgroundValues) +
    7327                 :                            NS_ARRAY_LENGTH(borderValues) +
    7328                 :                            NS_ARRAY_LENGTH(paddingValues)];
    7329                 : 
    7330               0 :   if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BACKGROUND) {
    7331               0 :     for (PRUint32 i = 0, i_end = ArrayLength(backgroundValues);
    7332                 :          i < i_end; ++i) {
    7333               0 :       properties[nValues] = backgroundValues[i];
    7334               0 :       values[nValues++] = ruleData.ValueFor(backgroundValues[i]);
    7335                 :     }
    7336                 :   }
    7337                 : 
    7338               0 :   if (ruleTypeMask & NS_AUTHOR_SPECIFIED_BORDER) {
    7339               0 :     for (PRUint32 i = 0, i_end = ArrayLength(borderValues);
    7340                 :          i < i_end; ++i) {
    7341               0 :       properties[nValues] = borderValues[i];
    7342               0 :       values[nValues++] = ruleData.ValueFor(borderValues[i]);
    7343                 :     }
    7344                 :   }
    7345                 : 
    7346               0 :   if (ruleTypeMask & NS_AUTHOR_SPECIFIED_PADDING) {
    7347               0 :     for (PRUint32 i = 0, i_end = ArrayLength(paddingValues);
    7348                 :          i < i_end; ++i) {
    7349               0 :       properties[nValues] = paddingValues[i];
    7350               0 :       values[nValues++] = ruleData.ValueFor(paddingValues[i]);
    7351                 :     }
    7352                 :   }
    7353                 : 
    7354               0 :   nsStyleContext* styleContext = aStyleContext;
    7355                 : 
    7356                 :   // We need to be careful not to count styles covered up by user-important or
    7357                 :   // UA-important declarations.  But we do want to catch explicit inherit
    7358                 :   // styling in those and check our parent style context to see whether we have
    7359                 :   // user styling for those properties.  Note that we don't care here about
    7360                 :   // inheritance due to lack of a specified value, since all the properties we
    7361                 :   // care about are reset properties.
    7362                 :   bool haveExplicitUAInherit;
    7363               0 :   do {
    7364               0 :     haveExplicitUAInherit = false;
    7365               0 :     for (nsRuleNode* ruleNode = styleContext->GetRuleNode(); ruleNode;
    7366                 :          ruleNode = ruleNode->GetParent()) {
    7367               0 :       nsIStyleRule *rule = ruleNode->GetRule();
    7368               0 :       if (rule) {
    7369               0 :         ruleData.mLevel = ruleNode->GetLevel();
    7370               0 :         ruleData.mIsImportantRule = ruleNode->IsImportantRule();
    7371                 : 
    7372               0 :         rule->MapRuleInfoInto(&ruleData);
    7373                 : 
    7374               0 :         if (ruleData.mLevel == nsStyleSet::eAgentSheet ||
    7375                 :             ruleData.mLevel == nsStyleSet::eUserSheet) {
    7376                 :           // This is a rule whose effect we want to ignore, so if any of
    7377                 :           // the properties we care about were set, set them to the dummy
    7378                 :           // value that they'll never otherwise get.
    7379               0 :           for (PRUint32 i = 0; i < nValues; ++i) {
    7380               0 :             nsCSSUnit unit = values[i]->GetUnit();
    7381               0 :             if (unit != eCSSUnit_Null &&
    7382                 :                 unit != eCSSUnit_Dummy &&
    7383                 :                 unit != eCSSUnit_DummyInherit) {
    7384               0 :               if (unit == eCSSUnit_Inherit) {
    7385               0 :                 haveExplicitUAInherit = true;
    7386               0 :                 values[i]->SetDummyInheritValue();
    7387                 :               } else {
    7388               0 :                 values[i]->SetDummyValue();
    7389                 :               }
    7390                 :             }
    7391               0 :           }
    7392                 :         } else {
    7393                 :           // If any of the values we care about was set by the above rule,
    7394                 :           // we have author style.
    7395               0 :           for (PRUint32 i = 0; i < nValues; ++i) {
    7396               0 :             if (values[i]->GetUnit() != eCSSUnit_Null &&
    7397               0 :                 values[i]->GetUnit() != eCSSUnit_Dummy && // see above
    7398               0 :                 values[i]->GetUnit() != eCSSUnit_DummyInherit) {
    7399                 :               // If author colors are not allowed, only claim to have
    7400                 :               // author-specified rules if we're looking at a non-color
    7401                 :               // property or if we're looking at the background color and it's
    7402                 :               // set to transparent.  Anything else should get set to a dummy
    7403                 :               // value instead.
    7404               0 :               if (aAuthorColorsAllowed ||
    7405                 :                   !nsCSSProps::PropHasFlags(properties[i],
    7406               0 :                      CSS_PROPERTY_IGNORED_WHEN_COLORS_DISABLED) ||
    7407               0 :                   (properties[i] == eCSSProperty_background_color &&
    7408               0 :                    !values[i]->IsNonTransparentColor())) {
    7409               0 :                 return true;
    7410                 :               }
    7411                 : 
    7412               0 :               values[i]->SetDummyValue();
    7413                 :             }
    7414                 :           }
    7415                 :         }
    7416                 :       }
    7417                 :     }
    7418                 : 
    7419               0 :     if (haveExplicitUAInherit) {
    7420                 :       // reset all the eCSSUnit_Null values to eCSSUnit_Dummy (since they're
    7421                 :       // not styled by the author, or by anyone else), and then reset all the
    7422                 :       // eCSSUnit_DummyInherit values to eCSSUnit_Null (so we will be able to
    7423                 :       // detect them being styled by the author) and move up to our parent
    7424                 :       // style context.
    7425               0 :       for (PRUint32 i = 0; i < nValues; ++i)
    7426               0 :         if (values[i]->GetUnit() == eCSSUnit_Null)
    7427               0 :           values[i]->SetDummyValue();
    7428               0 :       for (PRUint32 i = 0; i < nValues; ++i)
    7429               0 :         if (values[i]->GetUnit() == eCSSUnit_DummyInherit)
    7430               0 :           values[i]->Reset();
    7431               0 :       styleContext = styleContext->GetParent();
    7432                 :     }
    7433                 :   } while (haveExplicitUAInherit && styleContext);
    7434                 : 
    7435               0 :   return false;
    7436                 : }

Generated by: LCOV version 1.7