LCOV - code coverage report
Current view: directory - layout/style - Declaration.cpp (source / functions) Found Hit Coverage
Test: app.info Lines: 475 0 0.0 %
Date: 2012-06-02 Functions: 17 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.org 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                 :  *   Daniel Glazman <glazman@netscape.com>
      24                 :  *   Mats Palmgren <mats.palmgren@bredband.net>
      25                 :  *   Jonathon Jongsma <jonathon.jongsma@collabora.co.uk>, Collabora Ltd.
      26                 :  *   L. David Baron <dbaron@dbaron.org>, Mozilla Corporation
      27                 :  *
      28                 :  * Alternatively, the contents of this file may be used under the terms of
      29                 :  * either of the GNU General Public License Version 2 or later (the "GPL"),
      30                 :  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
      31                 :  * in which case the provisions of the GPL or the LGPL are applicable instead
      32                 :  * of those above. If you wish to allow use of your version of this file only
      33                 :  * under the terms of either the GPL or the LGPL, and not to allow others to
      34                 :  * use your version of this file under the terms of the MPL, indicate your
      35                 :  * decision by deleting the provisions above and replace them with the notice
      36                 :  * and other provisions required by the GPL or the LGPL. If you do not delete
      37                 :  * the provisions above, a recipient may use your version of this file under
      38                 :  * the terms of any one of the MPL, the GPL or the LGPL.
      39                 :  *
      40                 :  * ***** END LICENSE BLOCK ***** */
      41                 : 
      42                 : /*
      43                 :  * representation of a declaration block (or style attribute) in a CSS
      44                 :  * stylesheet
      45                 :  */
      46                 : 
      47                 : #include "mozilla/Util.h"
      48                 : 
      49                 : #include "mozilla/css/Declaration.h"
      50                 : #include "nsPrintfCString.h"
      51                 : 
      52                 : namespace mozilla {
      53                 : namespace css {
      54                 : 
      55                 : // check that we can fit all the CSS properties into a PRUint8
      56                 : // for the mOrder array - if not, might need to use PRUint16!
      57                 : MOZ_STATIC_ASSERT(eCSSProperty_COUNT_no_shorthands - 1 <= PR_UINT8_MAX,
      58                 :                   "CSS longhand property numbers no longer fit in a PRUint8");
      59                 : 
      60               0 : Declaration::Declaration()
      61               0 :   : mImmutable(false)
      62                 : {
      63               0 :   MOZ_COUNT_CTOR(mozilla::css::Declaration);
      64               0 : }
      65                 : 
      66               0 : Declaration::Declaration(const Declaration& aCopy)
      67                 :   : mOrder(aCopy.mOrder),
      68               0 :     mData(aCopy.mData ? aCopy.mData->Clone() : nsnull),
      69                 :     mImportantData(aCopy.mImportantData
      70               0 :                    ? aCopy.mImportantData->Clone() : nsnull),
      71               0 :     mImmutable(false)
      72                 : {
      73               0 :   MOZ_COUNT_CTOR(mozilla::css::Declaration);
      74               0 : }
      75                 : 
      76               0 : Declaration::~Declaration()
      77                 : {
      78               0 :   MOZ_COUNT_DTOR(mozilla::css::Declaration);
      79               0 : }
      80                 : 
      81                 : void
      82               0 : Declaration::ValueAppended(nsCSSProperty aProperty)
      83                 : {
      84               0 :   NS_ABORT_IF_FALSE(!mData && !mImportantData,
      85                 :                     "should only be called while expanded");
      86               0 :   NS_ABORT_IF_FALSE(!nsCSSProps::IsShorthand(aProperty),
      87                 :                     "shorthands forbidden");
      88                 :   // order IS important for CSS, so remove and add to the end
      89               0 :   mOrder.RemoveElement(aProperty);
      90               0 :   mOrder.AppendElement(aProperty);
      91               0 : }
      92                 : 
      93                 : void
      94               0 : Declaration::RemoveProperty(nsCSSProperty aProperty)
      95                 : {
      96               0 :   nsCSSExpandedDataBlock data;
      97               0 :   ExpandTo(&data);
      98               0 :   NS_ABORT_IF_FALSE(!mData && !mImportantData, "Expand didn't null things out");
      99                 : 
     100               0 :   if (nsCSSProps::IsShorthand(aProperty)) {
     101               0 :     CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(p, aProperty) {
     102               0 :       data.ClearLonghandProperty(*p);
     103               0 :       mOrder.RemoveElement(*p);
     104                 :     }
     105                 :   } else {
     106               0 :     data.ClearLonghandProperty(aProperty);
     107               0 :     mOrder.RemoveElement(aProperty);
     108                 :   }
     109                 : 
     110               0 :   CompressFrom(&data);
     111               0 : }
     112                 : 
     113                 : bool
     114               0 : Declaration::HasProperty(nsCSSProperty aProperty) const
     115                 : {
     116               0 :   NS_ABORT_IF_FALSE(0 <= aProperty &&
     117                 :                     aProperty < eCSSProperty_COUNT_no_shorthands,
     118                 :                     "property ID out of range");
     119                 : 
     120               0 :   nsCSSCompressedDataBlock *data = GetValueIsImportant(aProperty)
     121               0 :                                       ? mImportantData : mData;
     122               0 :   const nsCSSValue *val = data->ValueFor(aProperty);
     123               0 :   return !!val;
     124                 : }
     125                 : 
     126                 : bool
     127               0 : Declaration::AppendValueToString(nsCSSProperty aProperty,
     128                 :                                  nsAString& aResult) const
     129                 : {
     130               0 :   NS_ABORT_IF_FALSE(0 <= aProperty &&
     131                 :                     aProperty < eCSSProperty_COUNT_no_shorthands,
     132                 :                     "property ID out of range");
     133                 : 
     134               0 :   nsCSSCompressedDataBlock *data = GetValueIsImportant(aProperty)
     135               0 :                                       ? mImportantData : mData;
     136               0 :   const nsCSSValue *val = data->ValueFor(aProperty);
     137               0 :   if (!val) {
     138               0 :     return false;
     139                 :   }
     140                 : 
     141               0 :   val->AppendToString(aProperty, aResult);
     142               0 :   return true;
     143                 : }
     144                 : 
     145                 : void
     146               0 : Declaration::GetValue(nsCSSProperty aProperty, nsAString& aValue) const
     147                 : {
     148               0 :   aValue.Truncate(0);
     149                 : 
     150                 :   // simple properties are easy.
     151               0 :   if (!nsCSSProps::IsShorthand(aProperty)) {
     152               0 :     AppendValueToString(aProperty, aValue);
     153               0 :     return;
     154                 :   }
     155                 : 
     156                 :   // DOM Level 2 Style says (when describing CSS2Properties, although
     157                 :   // not CSSStyleDeclaration.getPropertyValue):
     158                 :   //   However, if there is no shorthand declaration that could be added
     159                 :   //   to the ruleset without changing in any way the rules already
     160                 :   //   declared in the ruleset (i.e., by adding longhand rules that were
     161                 :   //   previously not declared in the ruleset), then the empty string
     162                 :   //   should be returned for the shorthand property.
     163                 :   // This means we need to check a number of cases:
     164                 :   //   (1) Since a shorthand sets all sub-properties, if some of its
     165                 :   //       subproperties were not specified, we must return the empty
     166                 :   //       string.
     167                 :   //   (2) Since 'inherit' and 'initial' can only be specified as the
     168                 :   //       values for entire properties, we need to return the empty
     169                 :   //       string if some but not all of the subproperties have one of
     170                 :   //       those values.
     171                 :   //   (3) Since a single value only makes sense with or without
     172                 :   //       !important, we return the empty string if some values are
     173                 :   //       !important and some are not.
     174                 :   // Since we're doing this check for 'inherit' and 'initial' up front,
     175                 :   // we can also simplify the property serialization code by serializing
     176                 :   // those values up front as well.
     177               0 :   PRUint32 totalCount = 0, importantCount = 0,
     178               0 :            initialCount = 0, inheritCount = 0;
     179               0 :   CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(p, aProperty) {
     180               0 :     if (*p == eCSSProperty__x_system_font ||
     181               0 :          nsCSSProps::PropHasFlags(*p, CSS_PROPERTY_DIRECTIONAL_SOURCE)) {
     182                 :       // The system-font subproperty and the *-source properties don't count.
     183               0 :       continue;
     184                 :     }
     185               0 :     ++totalCount;
     186               0 :     const nsCSSValue *val = mData->ValueFor(*p);
     187               0 :     NS_ABORT_IF_FALSE(!val || !mImportantData || !mImportantData->ValueFor(*p),
     188                 :                       "can't be in both blocks");
     189               0 :     if (!val && mImportantData) {
     190               0 :       ++importantCount;
     191               0 :       val = mImportantData->ValueFor(*p);
     192                 :     }
     193               0 :     if (!val) {
     194                 :       // Case (1) above: some subproperties not specified.
     195               0 :       return;
     196                 :     }
     197               0 :     if (val->GetUnit() == eCSSUnit_Inherit) {
     198               0 :       ++inheritCount;
     199               0 :     } else if (val->GetUnit() == eCSSUnit_Initial) {
     200               0 :       ++initialCount;
     201                 :     }
     202                 :   }
     203               0 :   if (importantCount != 0 && importantCount != totalCount) {
     204                 :     // Case (3), no consistent importance.
     205               0 :     return;
     206                 :   }
     207               0 :   if (initialCount == totalCount) {
     208                 :     // Simplify serialization below by serializing initial up-front.
     209               0 :     nsCSSValue(eCSSUnit_Initial).AppendToString(eCSSProperty_UNKNOWN, aValue);
     210               0 :     return;
     211                 :   }
     212               0 :   if (inheritCount == totalCount) {
     213                 :     // Simplify serialization below by serializing inherit up-front.
     214               0 :     nsCSSValue(eCSSUnit_Inherit).AppendToString(eCSSProperty_UNKNOWN, aValue);
     215               0 :     return;
     216                 :   }
     217               0 :   if (initialCount != 0 || inheritCount != 0) {
     218                 :     // Case (2): partially initial or inherit.
     219               0 :     return;
     220                 :   }
     221                 : 
     222               0 :   nsCSSCompressedDataBlock *data = importantCount ? mImportantData : mData;
     223               0 :   switch (aProperty) {
     224                 :     case eCSSProperty_margin: 
     225                 :     case eCSSProperty_padding: 
     226                 :     case eCSSProperty_border_color: 
     227                 :     case eCSSProperty_border_style: 
     228                 :     case eCSSProperty_border_width: {
     229                 :       const nsCSSProperty* subprops =
     230               0 :         nsCSSProps::SubpropertyEntryFor(aProperty);
     231               0 :       NS_ABORT_IF_FALSE(nsCSSProps::GetStringValue(subprops[0]).Find("-top") !=
     232                 :                         kNotFound, "first subprop must be top");
     233               0 :       NS_ABORT_IF_FALSE(nsCSSProps::GetStringValue(subprops[1]).Find("-right") !=
     234                 :                         kNotFound, "second subprop must be right");
     235               0 :       NS_ABORT_IF_FALSE(nsCSSProps::GetStringValue(subprops[2]).Find("-bottom") !=
     236                 :                         kNotFound, "third subprop must be bottom");
     237               0 :       NS_ABORT_IF_FALSE(nsCSSProps::GetStringValue(subprops[3]).Find("-left") !=
     238                 :                         kNotFound, "fourth subprop must be left");
     239               0 :       const nsCSSValue &topValue = *data->ValueFor(subprops[0]);
     240               0 :       const nsCSSValue &rightValue = *data->ValueFor(subprops[1]);
     241               0 :       const nsCSSValue &bottomValue = *data->ValueFor(subprops[2]);
     242               0 :       const nsCSSValue &leftValue = *data->ValueFor(subprops[3]);
     243                 : 
     244               0 :       NS_ABORT_IF_FALSE(topValue.GetUnit() != eCSSUnit_Null, "null top");
     245               0 :       topValue.AppendToString(subprops[0], aValue);
     246               0 :       if (topValue != rightValue || topValue != leftValue ||
     247               0 :           topValue != bottomValue) {
     248               0 :         aValue.Append(PRUnichar(' '));
     249               0 :         NS_ABORT_IF_FALSE(rightValue.GetUnit() != eCSSUnit_Null, "null right");
     250               0 :         rightValue.AppendToString(subprops[1], aValue);
     251               0 :         if (topValue != bottomValue || rightValue != leftValue) {
     252               0 :           aValue.Append(PRUnichar(' '));
     253               0 :           NS_ABORT_IF_FALSE(bottomValue.GetUnit() != eCSSUnit_Null, "null bottom");
     254               0 :           bottomValue.AppendToString(subprops[2], aValue);
     255               0 :           if (rightValue != leftValue) {
     256               0 :             aValue.Append(PRUnichar(' '));
     257               0 :             NS_ABORT_IF_FALSE(leftValue.GetUnit() != eCSSUnit_Null, "null left");
     258               0 :             leftValue.AppendToString(subprops[3], aValue);
     259                 :           }
     260                 :         }
     261                 :       }
     262               0 :       break;
     263                 :     }
     264                 :     case eCSSProperty_border_radius:
     265                 :     case eCSSProperty__moz_outline_radius: {
     266                 :       const nsCSSProperty* subprops =
     267               0 :         nsCSSProps::SubpropertyEntryFor(aProperty);
     268                 :       const nsCSSValue* vals[4] = {
     269               0 :         data->ValueFor(subprops[0]),
     270               0 :         data->ValueFor(subprops[1]),
     271               0 :         data->ValueFor(subprops[2]),
     272               0 :         data->ValueFor(subprops[3])
     273               0 :       };
     274                 : 
     275                 :       // For compatibility, only write a slash and the y-values
     276                 :       // if they're not identical to the x-values.
     277               0 :       bool needY = false;
     278               0 :       for (int i = 0; i < 4; i++) {
     279               0 :         if (vals[i]->GetUnit() == eCSSUnit_Pair) {
     280               0 :           needY = true;
     281               0 :           vals[i]->GetPairValue().mXValue.AppendToString(subprops[i], aValue);
     282                 :         } else {
     283               0 :           vals[i]->AppendToString(subprops[i], aValue);
     284                 :         }
     285               0 :         if (i < 3)
     286               0 :           aValue.Append(PRUnichar(' '));
     287                 :       }
     288                 : 
     289               0 :       if (needY) {
     290               0 :         aValue.AppendLiteral(" / ");
     291               0 :         for (int i = 0; i < 4; i++) {
     292               0 :           if (vals[i]->GetUnit() == eCSSUnit_Pair) {
     293               0 :             vals[i]->GetPairValue().mYValue.AppendToString(subprops[i], aValue);
     294                 :           } else {
     295               0 :             vals[i]->AppendToString(subprops[i], aValue);
     296                 :           }
     297               0 :           if (i < 3)
     298               0 :             aValue.Append(PRUnichar(' '));
     299                 :         }
     300                 :       }
     301               0 :       break;
     302                 :     }
     303                 :     case eCSSProperty_border: {
     304                 :       const nsCSSProperty* subproptables[3] = {
     305               0 :         nsCSSProps::SubpropertyEntryFor(eCSSProperty_border_color),
     306               0 :         nsCSSProps::SubpropertyEntryFor(eCSSProperty_border_style),
     307               0 :         nsCSSProps::SubpropertyEntryFor(eCSSProperty_border_width)
     308               0 :       };
     309               0 :       bool match = true;
     310               0 :       for (const nsCSSProperty** subprops = subproptables,
     311               0 :                **subprops_end = ArrayEnd(subproptables);
     312                 :            subprops < subprops_end; ++subprops) {
     313                 :         // Check only the first four subprops in each table, since the
     314                 :         // others are extras for dimensional box properties.
     315               0 :         const nsCSSValue *firstSide = data->ValueFor((*subprops)[0]);
     316               0 :         for (PRInt32 side = 1; side < 4; ++side) {
     317                 :           const nsCSSValue *otherSide =
     318               0 :             data->ValueFor((*subprops)[side]);
     319               0 :           if (*firstSide != *otherSide)
     320               0 :             match = false;
     321                 :         }
     322                 :       }
     323               0 :       if (!match) {
     324                 :         // We can't express what we have in the border shorthand
     325               0 :         break;
     326                 :       }
     327                 :       // tweak aProperty and fall through
     328               0 :       aProperty = eCSSProperty_border_top;
     329                 :     }
     330                 :     case eCSSProperty_border_top:
     331                 :     case eCSSProperty_border_right:
     332                 :     case eCSSProperty_border_bottom:
     333                 :     case eCSSProperty_border_left:
     334                 :     case eCSSProperty_border_start:
     335                 :     case eCSSProperty_border_end:
     336                 :     case eCSSProperty__moz_column_rule:
     337                 :     case eCSSProperty_outline: {
     338                 :       const nsCSSProperty* subprops =
     339               0 :         nsCSSProps::SubpropertyEntryFor(aProperty);
     340               0 :       NS_ABORT_IF_FALSE(StringEndsWith(nsCSSProps::GetStringValue(subprops[2]),
     341                 :                                        NS_LITERAL_CSTRING("-color")) ||
     342                 :                         StringEndsWith(nsCSSProps::GetStringValue(subprops[2]),
     343                 :                                        NS_LITERAL_CSTRING("-color-value")),
     344                 :                         "third subprop must be the color property");
     345               0 :       const nsCSSValue *colorValue = data->ValueFor(subprops[2]);
     346                 :       bool isMozUseTextColor =
     347               0 :         colorValue->GetUnit() == eCSSUnit_Enumerated &&
     348               0 :         colorValue->GetIntValue() == NS_STYLE_COLOR_MOZ_USE_TEXT_COLOR;
     349               0 :       if (!AppendValueToString(subprops[0], aValue) ||
     350               0 :           !(aValue.Append(PRUnichar(' ')),
     351               0 :             AppendValueToString(subprops[1], aValue)) ||
     352                 :           // Don't output a third value when it's -moz-use-text-color.
     353                 :           !(isMozUseTextColor ||
     354               0 :             (aValue.Append(PRUnichar(' ')),
     355               0 :              AppendValueToString(subprops[2], aValue)))) {
     356               0 :         aValue.Truncate();
     357                 :       }
     358               0 :       break;
     359                 :     }
     360                 :     case eCSSProperty_margin_left:
     361                 :     case eCSSProperty_margin_right:
     362                 :     case eCSSProperty_margin_start:
     363                 :     case eCSSProperty_margin_end:
     364                 :     case eCSSProperty_padding_left:
     365                 :     case eCSSProperty_padding_right:
     366                 :     case eCSSProperty_padding_start:
     367                 :     case eCSSProperty_padding_end:
     368                 :     case eCSSProperty_border_left_color:
     369                 :     case eCSSProperty_border_left_style:
     370                 :     case eCSSProperty_border_left_width:
     371                 :     case eCSSProperty_border_right_color:
     372                 :     case eCSSProperty_border_right_style:
     373                 :     case eCSSProperty_border_right_width:
     374                 :     case eCSSProperty_border_start_color:
     375                 :     case eCSSProperty_border_start_style:
     376                 :     case eCSSProperty_border_start_width:
     377                 :     case eCSSProperty_border_end_color:
     378                 :     case eCSSProperty_border_end_style:
     379                 :     case eCSSProperty_border_end_width: {
     380                 :       const nsCSSProperty* subprops =
     381               0 :         nsCSSProps::SubpropertyEntryFor(aProperty);
     382               0 :       NS_ABORT_IF_FALSE(subprops[3] == eCSSProperty_UNKNOWN,
     383                 :                         "not box property with physical vs. logical cascading");
     384               0 :       AppendValueToString(subprops[0], aValue);
     385               0 :       break;
     386                 :     }
     387                 :     case eCSSProperty_background: {
     388                 :       // We know from above that all subproperties were specified.
     389                 :       // However, we still can't represent that in the shorthand unless
     390                 :       // they're all lists of the same length.  So if they're different
     391                 :       // lengths, we need to bail out.
     392                 :       // We also need to bail out if an item has background-clip and
     393                 :       // background-origin that are different and not the default
     394                 :       // values.  (We omit them if they're both default.)
     395                 :       const nsCSSValueList *image =
     396                 :         data->ValueFor(eCSSProperty_background_image)->
     397               0 :         GetListValue();
     398                 :       const nsCSSValuePairList *repeat =
     399                 :         data->ValueFor(eCSSProperty_background_repeat)->
     400               0 :         GetPairListValue();
     401                 :       const nsCSSValueList *attachment =
     402                 :         data->ValueFor(eCSSProperty_background_attachment)->
     403               0 :         GetListValue();
     404                 :       const nsCSSValueList *position =
     405                 :         data->ValueFor(eCSSProperty_background_position)->
     406               0 :         GetListValue();
     407                 :       const nsCSSValueList *clip =
     408                 :         data->ValueFor(eCSSProperty_background_clip)->
     409               0 :         GetListValue();
     410                 :       const nsCSSValueList *origin =
     411                 :         data->ValueFor(eCSSProperty_background_origin)->
     412               0 :         GetListValue();
     413                 :       const nsCSSValuePairList *size =
     414                 :         data->ValueFor(eCSSProperty_background_size)->
     415               0 :         GetPairListValue();
     416               0 :       for (;;) {
     417               0 :         if (size->mXValue.GetUnit() != eCSSUnit_Auto ||
     418               0 :             size->mYValue.GetUnit() != eCSSUnit_Auto) {
     419                 :           // Non-default background-size, so can't be serialized as shorthand.
     420               0 :           aValue.Truncate();
     421               0 :           return;
     422                 :         }
     423               0 :         image->mValue.AppendToString(eCSSProperty_background_image, aValue);
     424               0 :         aValue.Append(PRUnichar(' '));
     425               0 :         repeat->mXValue.AppendToString(eCSSProperty_background_repeat, aValue);
     426               0 :         if (repeat->mYValue.GetUnit() != eCSSUnit_Null) {
     427               0 :           repeat->mYValue.AppendToString(eCSSProperty_background_repeat, aValue);
     428                 :         }
     429               0 :         aValue.Append(PRUnichar(' '));
     430                 :         attachment->mValue.AppendToString(eCSSProperty_background_attachment,
     431               0 :                                           aValue);
     432               0 :         aValue.Append(PRUnichar(' '));
     433                 :         position->mValue.AppendToString(eCSSProperty_background_position,
     434               0 :                                         aValue);
     435                 : 
     436               0 :         NS_ABORT_IF_FALSE(clip->mValue.GetUnit() == eCSSUnit_Enumerated &&
     437                 :                           origin->mValue.GetUnit() == eCSSUnit_Enumerated,
     438                 :                           "should not have inherit/initial within list");
     439                 : 
     440               0 :         if (clip->mValue.GetIntValue() != NS_STYLE_BG_CLIP_BORDER ||
     441               0 :             origin->mValue.GetIntValue() != NS_STYLE_BG_ORIGIN_PADDING) {
     442                 :           // The shorthand only has a single clip/origin value which sets
     443                 :           // both properties.  So if they're different (and non-default),
     444                 :           // we can't represent the state using the shorthand.
     445                 :           MOZ_STATIC_ASSERT(NS_STYLE_BG_CLIP_BORDER ==
     446                 :                             NS_STYLE_BG_ORIGIN_BORDER &&
     447                 :                             NS_STYLE_BG_CLIP_PADDING ==
     448                 :                             NS_STYLE_BG_ORIGIN_PADDING &&
     449                 :                             NS_STYLE_BG_CLIP_CONTENT ==
     450                 :                             NS_STYLE_BG_ORIGIN_CONTENT,
     451                 :                             "bg-clip and bg-origin style constants must agree");
     452               0 :           if (clip->mValue != origin->mValue) {
     453               0 :             aValue.Truncate();
     454               0 :             return;
     455                 :           }
     456                 : 
     457               0 :           aValue.Append(PRUnichar(' '));
     458               0 :           clip->mValue.AppendToString(eCSSProperty_background_clip, aValue);
     459                 :         }
     460                 : 
     461               0 :         image = image->mNext;
     462               0 :         repeat = repeat->mNext;
     463               0 :         attachment = attachment->mNext;
     464               0 :         position = position->mNext;
     465               0 :         clip = clip->mNext;
     466               0 :         origin = origin->mNext;
     467               0 :         size = size->mNext;
     468                 : 
     469               0 :         if (!image) {
     470               0 :           if (repeat || attachment || position || clip || origin || size) {
     471                 :             // Uneven length lists, so can't be serialized as shorthand.
     472               0 :             aValue.Truncate();
     473               0 :             return;
     474                 :           }
     475                 :           break;
     476                 :         }
     477               0 :         if (!repeat || !attachment || !position || !clip || !origin || !size) {
     478                 :           // Uneven length lists, so can't be serialized as shorthand.
     479               0 :           aValue.Truncate();
     480               0 :           return;
     481                 :         }
     482               0 :         aValue.Append(PRUnichar(','));
     483               0 :         aValue.Append(PRUnichar(' '));
     484                 :       }
     485                 : 
     486               0 :       aValue.Append(PRUnichar(' '));
     487               0 :       AppendValueToString(eCSSProperty_background_color, aValue);
     488               0 :       break;
     489                 :     }
     490                 :     case eCSSProperty_font: {
     491                 :       // systemFont might not be present; the others are guaranteed to be
     492                 :       // based on the shorthand check at the beginning of the function
     493                 :       const nsCSSValue *systemFont =
     494               0 :         data->ValueFor(eCSSProperty__x_system_font);
     495                 :       const nsCSSValue &style =
     496               0 :         *data->ValueFor(eCSSProperty_font_style);
     497                 :       const nsCSSValue &variant =
     498               0 :         *data->ValueFor(eCSSProperty_font_variant);
     499                 :       const nsCSSValue &weight =
     500               0 :         *data->ValueFor(eCSSProperty_font_weight);
     501                 :       const nsCSSValue &size =
     502               0 :         *data->ValueFor(eCSSProperty_font_size);
     503                 :       const nsCSSValue &lh =
     504               0 :         *data->ValueFor(eCSSProperty_line_height);
     505                 :       const nsCSSValue &family =
     506               0 :         *data->ValueFor(eCSSProperty_font_family);
     507                 :       const nsCSSValue &stretch =
     508               0 :         *data->ValueFor(eCSSProperty_font_stretch);
     509                 :       const nsCSSValue &sizeAdjust =
     510               0 :         *data->ValueFor(eCSSProperty_font_size_adjust);
     511                 :       const nsCSSValue &featureSettings =
     512               0 :         *data->ValueFor(eCSSProperty_font_feature_settings);
     513                 :       const nsCSSValue &languageOverride =
     514               0 :         *data->ValueFor(eCSSProperty_font_language_override);
     515                 : 
     516               0 :       if (systemFont &&
     517               0 :           systemFont->GetUnit() != eCSSUnit_None &&
     518               0 :           systemFont->GetUnit() != eCSSUnit_Null) {
     519               0 :         if (style.GetUnit() != eCSSUnit_System_Font ||
     520               0 :             variant.GetUnit() != eCSSUnit_System_Font ||
     521               0 :             weight.GetUnit() != eCSSUnit_System_Font ||
     522               0 :             size.GetUnit() != eCSSUnit_System_Font ||
     523               0 :             lh.GetUnit() != eCSSUnit_System_Font ||
     524               0 :             family.GetUnit() != eCSSUnit_System_Font ||
     525               0 :             stretch.GetUnit() != eCSSUnit_System_Font ||
     526               0 :             sizeAdjust.GetUnit() != eCSSUnit_System_Font ||
     527               0 :             featureSettings.GetUnit() != eCSSUnit_System_Font ||
     528               0 :             languageOverride.GetUnit() != eCSSUnit_System_Font) {
     529                 :           // This can't be represented as a shorthand.
     530               0 :           return;
     531                 :         }
     532               0 :         systemFont->AppendToString(eCSSProperty__x_system_font, aValue);
     533                 :       } else {
     534                 :         // The font-stretch, font-size-adjust,
     535                 :         // -moz-font-feature-settings, and -moz-font-language-override
     536                 :         // properties are reset by this shorthand property to their
     537                 :         // initial values, but can't be represented in its syntax.
     538               0 :         if (stretch.GetUnit() != eCSSUnit_Enumerated ||
     539               0 :             stretch.GetIntValue() != NS_STYLE_FONT_STRETCH_NORMAL ||
     540               0 :             sizeAdjust.GetUnit() != eCSSUnit_None ||
     541               0 :             featureSettings.GetUnit() != eCSSUnit_Normal ||
     542               0 :             languageOverride.GetUnit() != eCSSUnit_Normal) {
     543               0 :           return;
     544                 :         }
     545                 : 
     546               0 :         if (style.GetUnit() != eCSSUnit_Enumerated ||
     547               0 :             style.GetIntValue() != NS_FONT_STYLE_NORMAL) {
     548               0 :           style.AppendToString(eCSSProperty_font_style, aValue);
     549               0 :           aValue.Append(PRUnichar(' '));
     550                 :         }
     551               0 :         if (variant.GetUnit() != eCSSUnit_Enumerated ||
     552               0 :             variant.GetIntValue() != NS_FONT_VARIANT_NORMAL) {
     553               0 :           variant.AppendToString(eCSSProperty_font_variant, aValue);
     554               0 :           aValue.Append(PRUnichar(' '));
     555                 :         }
     556               0 :         if (weight.GetUnit() != eCSSUnit_Enumerated ||
     557               0 :             weight.GetIntValue() != NS_FONT_WEIGHT_NORMAL) {
     558               0 :           weight.AppendToString(eCSSProperty_font_weight, aValue);
     559               0 :           aValue.Append(PRUnichar(' '));
     560                 :         }
     561               0 :         size.AppendToString(eCSSProperty_font_size, aValue);
     562               0 :         if (lh.GetUnit() != eCSSUnit_Normal) {
     563               0 :           aValue.Append(PRUnichar('/'));
     564               0 :           lh.AppendToString(eCSSProperty_line_height, aValue);
     565                 :         }
     566               0 :         aValue.Append(PRUnichar(' '));
     567               0 :         family.AppendToString(eCSSProperty_font_family, aValue);
     568                 :       }
     569               0 :       break;
     570                 :     }
     571                 :     case eCSSProperty_list_style:
     572               0 :       if (AppendValueToString(eCSSProperty_list_style_type, aValue))
     573               0 :         aValue.Append(PRUnichar(' '));
     574               0 :       if (AppendValueToString(eCSSProperty_list_style_position, aValue))
     575               0 :         aValue.Append(PRUnichar(' '));
     576               0 :       AppendValueToString(eCSSProperty_list_style_image, aValue);
     577               0 :       break;
     578                 :     case eCSSProperty_overflow: {
     579                 :       const nsCSSValue &xValue =
     580               0 :         *data->ValueFor(eCSSProperty_overflow_x);
     581                 :       const nsCSSValue &yValue =
     582               0 :         *data->ValueFor(eCSSProperty_overflow_y);
     583               0 :       if (xValue == yValue)
     584               0 :         xValue.AppendToString(eCSSProperty_overflow_x, aValue);
     585               0 :       break;
     586                 :     }
     587                 :     case eCSSProperty_text_decoration: {
     588                 :       // If text-decoration-color or text-decoration-style isn't initial value,
     589                 :       // we cannot serialize the text-decoration shorthand value.
     590                 :       const nsCSSValue &decorationColor =
     591               0 :         *data->ValueFor(eCSSProperty_text_decoration_color);
     592                 :       const nsCSSValue &decorationStyle =
     593               0 :         *data->ValueFor(eCSSProperty_text_decoration_style);
     594                 : 
     595               0 :       NS_ABORT_IF_FALSE(decorationStyle.GetUnit() == eCSSUnit_Enumerated,
     596                 :                         nsPrintfCString(32, "bad text-decoration-style unit %d",
     597                 :                                         decorationStyle.GetUnit()).get());
     598                 : 
     599               0 :       if (decorationColor.GetUnit() != eCSSUnit_Enumerated ||
     600               0 :           decorationColor.GetIntValue() != NS_STYLE_COLOR_MOZ_USE_TEXT_COLOR ||
     601               0 :           decorationStyle.GetIntValue() !=
     602                 :             NS_STYLE_TEXT_DECORATION_STYLE_SOLID) {
     603               0 :         return;
     604                 :       }
     605                 : 
     606                 :       const nsCSSValue &textBlink =
     607               0 :         *data->ValueFor(eCSSProperty_text_blink);
     608                 :       const nsCSSValue &decorationLine =
     609               0 :         *data->ValueFor(eCSSProperty_text_decoration_line);
     610                 : 
     611               0 :       NS_ABORT_IF_FALSE(textBlink.GetUnit() == eCSSUnit_Enumerated,
     612                 :                         nsPrintfCString(32, "bad text-blink unit %d",
     613                 :                                         textBlink.GetUnit()).get());
     614               0 :       NS_ABORT_IF_FALSE(decorationLine.GetUnit() == eCSSUnit_Enumerated,
     615                 :                         nsPrintfCString(32, "bad text-decoration-line unit %d",
     616                 :                                         decorationLine.GetUnit()).get());
     617                 : 
     618               0 :       bool blinkNone = (textBlink.GetIntValue() == NS_STYLE_TEXT_BLINK_NONE);
     619                 :       bool lineNone =
     620               0 :         (decorationLine.GetIntValue() == NS_STYLE_TEXT_DECORATION_LINE_NONE);
     621                 : 
     622               0 :       if (blinkNone && lineNone) {
     623               0 :         AppendValueToString(eCSSProperty_text_decoration_line, aValue);
     624                 :       } else {
     625               0 :         if (!blinkNone) {
     626               0 :           AppendValueToString(eCSSProperty_text_blink, aValue);
     627                 :         }
     628               0 :         if (!lineNone) {
     629               0 :           if (!aValue.IsEmpty()) {
     630               0 :             aValue.Append(PRUnichar(' '));
     631                 :           }
     632               0 :           AppendValueToString(eCSSProperty_text_decoration_line, aValue);
     633                 :         }
     634                 :       }
     635               0 :       break;
     636                 :     }
     637                 :     case eCSSProperty_transition: {
     638                 :       const nsCSSValue &transProp =
     639               0 :         *data->ValueFor(eCSSProperty_transition_property);
     640                 :       const nsCSSValue &transDuration =
     641               0 :         *data->ValueFor(eCSSProperty_transition_duration);
     642                 :       const nsCSSValue &transTiming =
     643               0 :         *data->ValueFor(eCSSProperty_transition_timing_function);
     644                 :       const nsCSSValue &transDelay =
     645               0 :         *data->ValueFor(eCSSProperty_transition_delay);
     646                 : 
     647               0 :       NS_ABORT_IF_FALSE(transDuration.GetUnit() == eCSSUnit_List ||
     648                 :                         transDuration.GetUnit() == eCSSUnit_ListDep,
     649                 :                         nsPrintfCString(32, "bad t-duration unit %d",
     650                 :                                         transDuration.GetUnit()).get());
     651               0 :       NS_ABORT_IF_FALSE(transTiming.GetUnit() == eCSSUnit_List ||
     652                 :                         transTiming.GetUnit() == eCSSUnit_ListDep,
     653                 :                         nsPrintfCString(32, "bad t-timing unit %d",
     654                 :                                         transTiming.GetUnit()).get());
     655               0 :       NS_ABORT_IF_FALSE(transDelay.GetUnit() == eCSSUnit_List ||
     656                 :                         transDelay.GetUnit() == eCSSUnit_ListDep,
     657                 :                         nsPrintfCString(32, "bad t-delay unit %d",
     658                 :                                         transDelay.GetUnit()).get());
     659                 : 
     660               0 :       const nsCSSValueList* dur = transDuration.GetListValue();
     661               0 :       const nsCSSValueList* tim = transTiming.GetListValue();
     662               0 :       const nsCSSValueList* del = transDelay.GetListValue();
     663                 : 
     664               0 :       if (transProp.GetUnit() == eCSSUnit_None ||
     665               0 :           transProp.GetUnit() == eCSSUnit_All) {
     666                 :         // If any of the other three lists has more than one element,
     667                 :         // we can't use the shorthand.
     668               0 :         if (!dur->mNext && !tim->mNext && !del->mNext) {
     669               0 :           transProp.AppendToString(eCSSProperty_transition_property, aValue);
     670               0 :           aValue.Append(PRUnichar(' '));
     671               0 :           dur->mValue.AppendToString(eCSSProperty_transition_duration,aValue);
     672               0 :           aValue.Append(PRUnichar(' '));
     673                 :           tim->mValue.AppendToString(eCSSProperty_transition_timing_function,
     674               0 :                                      aValue);
     675               0 :           aValue.Append(PRUnichar(' '));
     676               0 :           del->mValue.AppendToString(eCSSProperty_transition_delay, aValue);
     677               0 :           aValue.Append(PRUnichar(' '));
     678                 :         } else {
     679               0 :           aValue.Truncate();
     680                 :         }
     681                 :       } else {
     682               0 :         NS_ABORT_IF_FALSE(transProp.GetUnit() == eCSSUnit_List ||
     683                 :                           transProp.GetUnit() == eCSSUnit_ListDep,
     684                 :                           nsPrintfCString(32, "bad t-prop unit %d",
     685                 :                                           transProp.GetUnit()).get());
     686               0 :         const nsCSSValueList* pro = transProp.GetListValue();
     687               0 :         for (;;) {
     688                 :           pro->mValue.AppendToString(eCSSProperty_transition_property,
     689               0 :                                         aValue);
     690               0 :           aValue.Append(PRUnichar(' '));
     691                 :           dur->mValue.AppendToString(eCSSProperty_transition_duration,
     692               0 :                                         aValue);
     693               0 :           aValue.Append(PRUnichar(' '));
     694                 :           tim->mValue.AppendToString(eCSSProperty_transition_timing_function,
     695               0 :                                         aValue);
     696               0 :           aValue.Append(PRUnichar(' '));
     697                 :           del->mValue.AppendToString(eCSSProperty_transition_delay,
     698               0 :                                         aValue);
     699               0 :           pro = pro->mNext;
     700               0 :           dur = dur->mNext;
     701               0 :           tim = tim->mNext;
     702               0 :           del = del->mNext;
     703               0 :           if (!pro || !dur || !tim || !del) {
     704                 :             break;
     705                 :           }
     706               0 :           aValue.AppendLiteral(", ");
     707                 :         }
     708               0 :         if (pro || dur || tim || del) {
     709                 :           // Lists not all the same length, can't use shorthand.
     710               0 :           aValue.Truncate();
     711                 :         }
     712                 :       }
     713               0 :       break;
     714                 :     }
     715                 :     case eCSSProperty_animation: {
     716                 :       const nsCSSProperty* subprops =
     717               0 :         nsCSSProps::SubpropertyEntryFor(eCSSProperty_animation);
     718                 :       static const size_t numProps = 7;
     719               0 :       NS_ABORT_IF_FALSE(subprops[numProps] == eCSSProperty_UNKNOWN,
     720                 :                         "unexpected number of subproperties");
     721                 :       const nsCSSValue* values[numProps];
     722                 :       const nsCSSValueList* lists[numProps];
     723                 : 
     724               0 :       for (PRUint32 i = 0; i < numProps; ++i) {
     725               0 :         values[i] = data->ValueFor(subprops[i]);
     726               0 :         NS_ABORT_IF_FALSE(values[i]->GetUnit() == eCSSUnit_List ||
     727                 :                           values[i]->GetUnit() == eCSSUnit_ListDep,
     728                 :                           nsPrintfCString(32, "bad a-duration unit %d",
     729                 :                                           values[i]->GetUnit()).get());
     730               0 :         lists[i] = values[i]->GetListValue();
     731                 :       }
     732                 : 
     733               0 :       for (;;) {
     734                 :         // We must serialize 'animation-name' last in case it has
     735                 :         // a value that conflicts with one of the other keyword properties.
     736               0 :         NS_ABORT_IF_FALSE(subprops[numProps - 1] ==
     737                 :                             eCSSProperty_animation_name,
     738                 :                           "animation-name must be last");
     739               0 :         bool done = false;
     740               0 :         for (PRUint32 i = 0;;) {
     741               0 :           lists[i]->mValue.AppendToString(subprops[i], aValue);
     742               0 :           lists[i] = lists[i]->mNext;
     743               0 :           if (!lists[i]) {
     744               0 :             done = true;
     745                 :           }
     746               0 :           if (++i == numProps) {
     747                 :             break;
     748                 :           }
     749               0 :           aValue.Append(PRUnichar(' '));
     750                 :         }
     751               0 :         if (done) {
     752                 :           break;
     753                 :         }
     754               0 :         aValue.AppendLiteral(", ");
     755                 :       }
     756               0 :       for (PRUint32 i = 0; i < numProps; ++i) {
     757               0 :         if (lists[i]) {
     758                 :           // Lists not all the same length, can't use shorthand.
     759               0 :           aValue.Truncate();
     760               0 :           break;
     761                 :         }
     762                 :       }
     763               0 :       break;
     764                 :     }
     765                 :     case eCSSProperty_marker: {
     766                 :       const nsCSSValue &endValue =
     767               0 :         *data->ValueFor(eCSSProperty_marker_end);
     768                 :       const nsCSSValue &midValue =
     769               0 :         *data->ValueFor(eCSSProperty_marker_mid);
     770                 :       const nsCSSValue &startValue =
     771               0 :         *data->ValueFor(eCSSProperty_marker_start);
     772               0 :       if (endValue == midValue && midValue == startValue)
     773               0 :         AppendValueToString(eCSSProperty_marker_end, aValue);
     774               0 :       break;
     775                 :     }
     776                 :     case eCSSProperty__moz_columns: {
     777                 :       // Two values, column-count and column-width, separated by a space.
     778                 :       const nsCSSProperty* subprops =
     779               0 :         nsCSSProps::SubpropertyEntryFor(aProperty);
     780               0 :       AppendValueToString(subprops[0], aValue);
     781               0 :       aValue.Append(PRUnichar(' '));
     782               0 :       AppendValueToString(subprops[1], aValue);
     783               0 :       break;
     784                 :     }
     785                 :     default:
     786               0 :       NS_ABORT_IF_FALSE(false, "no other shorthands");
     787               0 :       break;
     788                 :   }
     789                 : }
     790                 : 
     791                 : bool
     792               0 : Declaration::GetValueIsImportant(const nsAString& aProperty) const
     793                 : {
     794               0 :   nsCSSProperty propID = nsCSSProps::LookupProperty(aProperty);
     795               0 :   if (propID == eCSSProperty_UNKNOWN) {
     796               0 :     return false;
     797                 :   }
     798               0 :   return GetValueIsImportant(propID);
     799                 : }
     800                 : 
     801                 : bool
     802               0 : Declaration::GetValueIsImportant(nsCSSProperty aProperty) const
     803                 : {
     804               0 :   if (!mImportantData)
     805               0 :     return false;
     806                 : 
     807                 :   // Calling ValueFor is inefficient, but we can assume '!important' is rare.
     808                 : 
     809               0 :   if (!nsCSSProps::IsShorthand(aProperty)) {
     810               0 :     return mImportantData->ValueFor(aProperty) != nsnull;
     811                 :   }
     812                 : 
     813               0 :   CSSPROPS_FOR_SHORTHAND_SUBPROPERTIES(p, aProperty) {
     814               0 :     if (*p == eCSSProperty__x_system_font) {
     815                 :       // The system_font subproperty doesn't count.
     816               0 :       continue;
     817                 :     }
     818               0 :     if (!mImportantData->ValueFor(*p)) {
     819               0 :       return false;
     820                 :     }
     821                 :   }
     822               0 :   return true;
     823                 : }
     824                 : 
     825                 : void
     826               0 : Declaration::AppendPropertyAndValueToString(nsCSSProperty aProperty,
     827                 :                                             nsAutoString& aValue,
     828                 :                                             nsAString& aResult) const
     829                 : {
     830               0 :   NS_ABORT_IF_FALSE(0 <= aProperty && aProperty < eCSSProperty_COUNT,
     831                 :                     "property enum out of range");
     832               0 :   NS_ABORT_IF_FALSE((aProperty < eCSSProperty_COUNT_no_shorthands) ==
     833                 :                     aValue.IsEmpty(),
     834                 :                     "aValue should be given for shorthands but not longhands");
     835               0 :   AppendASCIItoUTF16(nsCSSProps::GetStringValue(aProperty), aResult);
     836               0 :   aResult.AppendLiteral(": ");
     837               0 :   if (aValue.IsEmpty())
     838               0 :     AppendValueToString(aProperty, aResult);
     839                 :   else
     840               0 :     aResult.Append(aValue);
     841               0 :   if (GetValueIsImportant(aProperty)) {
     842               0 :     aResult.AppendLiteral(" ! important");
     843                 :   }
     844               0 :   aResult.AppendLiteral("; ");
     845               0 : }
     846                 : 
     847                 : void
     848               0 : Declaration::ToString(nsAString& aString) const
     849                 : {
     850                 :   // Someone cares about this declaration's contents, so don't let it
     851                 :   // change from under them.  See e.g. bug 338679.
     852               0 :   SetImmutable();
     853                 : 
     854                 :   nsCSSCompressedDataBlock *systemFontData =
     855               0 :     GetValueIsImportant(eCSSProperty__x_system_font) ? mImportantData : mData;
     856                 :   const nsCSSValue *systemFont =
     857               0 :     systemFontData->ValueFor(eCSSProperty__x_system_font);
     858                 :   const bool haveSystemFont = systemFont &&
     859               0 :                                 systemFont->GetUnit() != eCSSUnit_None &&
     860               0 :                                 systemFont->GetUnit() != eCSSUnit_Null;
     861               0 :   bool didSystemFont = false;
     862                 : 
     863               0 :   PRInt32 count = mOrder.Length();
     864                 :   PRInt32 index;
     865               0 :   nsAutoTArray<nsCSSProperty, 16> shorthandsUsed;
     866               0 :   for (index = 0; index < count; index++) {
     867               0 :     nsCSSProperty property = OrderValueAt(index);
     868               0 :     bool doneProperty = false;
     869                 : 
     870                 :     // If we already used this property in a shorthand, skip it.
     871               0 :     if (shorthandsUsed.Length() > 0) {
     872               0 :       for (const nsCSSProperty *shorthands =
     873               0 :              nsCSSProps::ShorthandsContaining(property);
     874                 :            *shorthands != eCSSProperty_UNKNOWN; ++shorthands) {
     875               0 :         if (shorthandsUsed.Contains(*shorthands)) {
     876               0 :           doneProperty = true;
     877               0 :           break;
     878                 :         }
     879                 :       }
     880               0 :       if (doneProperty)
     881               0 :         continue;
     882                 :     }
     883                 : 
     884                 :     // Try to use this property in a shorthand.
     885               0 :     nsAutoString value;
     886               0 :     for (const nsCSSProperty *shorthands =
     887               0 :            nsCSSProps::ShorthandsContaining(property);
     888                 :          *shorthands != eCSSProperty_UNKNOWN; ++shorthands) {
     889                 :       // ShorthandsContaining returns the shorthands in order from those
     890                 :       // that contain the most subproperties to those that contain the
     891                 :       // least, which is exactly the order we want to test them.
     892               0 :       nsCSSProperty shorthand = *shorthands;
     893                 : 
     894                 :       // If GetValue gives us a non-empty string back, we can use that
     895                 :       // value; otherwise it's not possible to use this shorthand.
     896               0 :       GetValue(shorthand, value);
     897               0 :       if (!value.IsEmpty()) {
     898               0 :         AppendPropertyAndValueToString(shorthand, value, aString);
     899               0 :         shorthandsUsed.AppendElement(shorthand);
     900               0 :         doneProperty = true;
     901               0 :         break;
     902                 :       }
     903                 : 
     904               0 :       NS_ABORT_IF_FALSE(shorthand != eCSSProperty_font ||
     905                 :                         *(shorthands + 1) == eCSSProperty_UNKNOWN,
     906                 :                         "font should always be the only containing shorthand");
     907               0 :       if (shorthand == eCSSProperty_font) {
     908               0 :         if (haveSystemFont && !didSystemFont) {
     909                 :           // Output the shorthand font declaration that we will
     910                 :           // partially override later.  But don't add it to
     911                 :           // |shorthandsUsed|, since we will have to override it.
     912               0 :           systemFont->AppendToString(eCSSProperty__x_system_font, value);
     913               0 :           AppendPropertyAndValueToString(eCSSProperty_font, value, aString);
     914               0 :           value.Truncate();
     915               0 :           didSystemFont = true;
     916                 :         }
     917                 : 
     918                 :         // That we output the system font is enough for this property if:
     919                 :         //   (1) it's the hidden system font subproperty (which either
     920                 :         //       means we output it or we don't have it), or
     921                 :         //   (2) its value is the hidden system font value and it matches
     922                 :         //       the hidden system font subproperty in importance, and
     923                 :         //       we output the system font subproperty.
     924               0 :         const nsCSSValue *val = systemFontData->ValueFor(property);
     925               0 :         if (property == eCSSProperty__x_system_font ||
     926               0 :             (haveSystemFont && val && val->GetUnit() == eCSSUnit_System_Font)) {
     927               0 :           doneProperty = true;
     928                 :         }
     929                 :       }
     930                 :     }
     931               0 :     if (doneProperty)
     932               0 :       continue;
     933                 : 
     934               0 :     NS_ABORT_IF_FALSE(value.IsEmpty(), "value should be empty now");
     935               0 :     AppendPropertyAndValueToString(property, value, aString);
     936                 :   }
     937               0 :   if (! aString.IsEmpty()) {
     938                 :     // if the string is not empty, we have trailing whitespace we
     939                 :     // should remove
     940               0 :     aString.Truncate(aString.Length() - 1);
     941                 :   }
     942               0 : }
     943                 : 
     944                 : #ifdef DEBUG
     945                 : void
     946               0 : Declaration::List(FILE* out, PRInt32 aIndent) const
     947                 : {
     948               0 :   for (PRInt32 index = aIndent; --index >= 0; ) fputs("  ", out);
     949                 : 
     950               0 :   fputs("{ ", out);
     951               0 :   nsAutoString s;
     952               0 :   ToString(s);
     953               0 :   fputs(NS_ConvertUTF16toUTF8(s).get(), out);
     954               0 :   fputs("}", out);
     955               0 : }
     956                 : #endif
     957                 : 
     958                 : void
     959               0 : Declaration::GetNthProperty(PRUint32 aIndex, nsAString& aReturn) const
     960                 : {
     961               0 :   aReturn.Truncate();
     962               0 :   if (aIndex < mOrder.Length()) {
     963               0 :     nsCSSProperty property = OrderValueAt(aIndex);
     964               0 :     if (0 <= property) {
     965               0 :       AppendASCIItoUTF16(nsCSSProps::GetStringValue(property), aReturn);
     966                 :     }
     967                 :   }
     968               0 : }
     969                 : 
     970                 : void
     971               0 : Declaration::InitializeEmpty()
     972                 : {
     973               0 :   NS_ABORT_IF_FALSE(!mData && !mImportantData, "already initialized");
     974               0 :   mData = nsCSSCompressedDataBlock::CreateEmptyBlock();
     975               0 : }
     976                 : 
     977                 : Declaration*
     978               0 : Declaration::EnsureMutable()
     979                 : {
     980               0 :   NS_ABORT_IF_FALSE(mData, "should only be called when not expanded");
     981               0 :   if (!IsMutable()) {
     982               0 :     return new Declaration(*this);
     983                 :   } else {
     984               0 :     return this;
     985                 :   }
     986                 : }
     987                 : 
     988                 : size_t
     989               0 : Declaration::SizeOfIncludingThis(nsMallocSizeOfFun aMallocSizeOf) const
     990                 : {
     991               0 :   size_t n = aMallocSizeOf(this);
     992               0 :   n += mOrder.SizeOfExcludingThis(aMallocSizeOf);
     993               0 :   n += mData          ? mData         ->SizeOfIncludingThis(aMallocSizeOf) : 0;
     994               0 :   n += mImportantData ? mImportantData->SizeOfIncludingThis(aMallocSizeOf) : 0;
     995               0 :   return n;
     996                 : }
     997                 : 
     998                 : } // namespace mozilla::css
     999                 : } // namespace mozilla

Generated by: LCOV version 1.7