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

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

Generated by: LCOV version 1.7