Home | History | Annotate | Download | only in css
      1 /*
      2  * (C) 1999-2003 Lars Knoll (knoll (at) kde.org)
      3  * Copyright (C) 2004, 2005, 2006, 2007, 2008, 2012 Apple Inc. All rights reserved.
      4  *
      5  * This library is free software; you can redistribute it and/or
      6  * modify it under the terms of the GNU Library General Public
      7  * License as published by the Free Software Foundation; either
      8  * version 2 of the License, or (at your option) any later version.
      9  *
     10  * This library is distributed in the hope that it will be useful,
     11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13  * Library General Public License for more details.
     14  *
     15  * You should have received a copy of the GNU Library General Public License
     16  * along with this library; see the file COPYING.LIB.  If not, write to
     17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     18  * Boston, MA 02110-1301, USA.
     19  */
     20 
     21 #include "config.h"
     22 #include "core/css/CSSPrimitiveValue.h"
     23 
     24 #include "bindings/v8/ExceptionState.h"
     25 #include "core/css/CSSBasicShapes.h"
     26 #include "core/css/CSSCalculationValue.h"
     27 #include "core/css/CSSHelper.h"
     28 #include "core/css/CSSParser.h"
     29 #include "core/css/CSSToLengthConversionData.h"
     30 #include "core/css/Counter.h"
     31 #include "core/css/Pair.h"
     32 #include "core/css/RGBColor.h"
     33 #include "core/css/Rect.h"
     34 #include "core/css/StyleSheetContents.h"
     35 #include "core/dom/ExceptionCode.h"
     36 #include "core/dom/Node.h"
     37 #include "core/rendering/style/RenderStyle.h"
     38 #include "platform/LayoutUnit.h"
     39 #include "wtf/DecimalNumber.h"
     40 #include "wtf/StdLibExtras.h"
     41 #include "wtf/text/StringBuffer.h"
     42 #include "wtf/text/StringBuilder.h"
     43 
     44 using namespace WTF;
     45 
     46 namespace WebCore {
     47 
     48 // Max/min values for CSS, needs to slightly smaller/larger than the true max/min values to allow for rounding without overflowing.
     49 // Subtract two (rather than one) to allow for values to be converted to float and back without exceeding the LayoutUnit::max.
     50 const int maxValueForCssLength = INT_MAX / kFixedPointDenominator - 2;
     51 const int minValueForCssLength = INT_MIN / kFixedPointDenominator + 2;
     52 
     53 static inline bool isValidCSSUnitTypeForDoubleConversion(CSSPrimitiveValue::UnitTypes unitType)
     54 {
     55     switch (unitType) {
     56     case CSSPrimitiveValue::CSS_CALC:
     57     case CSSPrimitiveValue::CSS_CALC_PERCENTAGE_WITH_NUMBER:
     58     case CSSPrimitiveValue::CSS_CALC_PERCENTAGE_WITH_LENGTH:
     59     case CSSPrimitiveValue::CSS_CM:
     60     case CSSPrimitiveValue::CSS_DEG:
     61     case CSSPrimitiveValue::CSS_DIMENSION:
     62     case CSSPrimitiveValue::CSS_DPPX:
     63     case CSSPrimitiveValue::CSS_DPI:
     64     case CSSPrimitiveValue::CSS_DPCM:
     65     case CSSPrimitiveValue::CSS_EMS:
     66     case CSSPrimitiveValue::CSS_EXS:
     67     case CSSPrimitiveValue::CSS_GRAD:
     68     case CSSPrimitiveValue::CSS_HZ:
     69     case CSSPrimitiveValue::CSS_IN:
     70     case CSSPrimitiveValue::CSS_KHZ:
     71     case CSSPrimitiveValue::CSS_MM:
     72     case CSSPrimitiveValue::CSS_MS:
     73     case CSSPrimitiveValue::CSS_NUMBER:
     74     case CSSPrimitiveValue::CSS_PERCENTAGE:
     75     case CSSPrimitiveValue::CSS_PC:
     76     case CSSPrimitiveValue::CSS_PT:
     77     case CSSPrimitiveValue::CSS_PX:
     78     case CSSPrimitiveValue::CSS_RAD:
     79     case CSSPrimitiveValue::CSS_REMS:
     80     case CSSPrimitiveValue::CSS_CHS:
     81     case CSSPrimitiveValue::CSS_S:
     82     case CSSPrimitiveValue::CSS_TURN:
     83     case CSSPrimitiveValue::CSS_VW:
     84     case CSSPrimitiveValue::CSS_VH:
     85     case CSSPrimitiveValue::CSS_VMIN:
     86     case CSSPrimitiveValue::CSS_VMAX:
     87     case CSSPrimitiveValue::CSS_FR:
     88         return true;
     89     case CSSPrimitiveValue::CSS_ATTR:
     90     case CSSPrimitiveValue::CSS_COUNTER:
     91     case CSSPrimitiveValue::CSS_COUNTER_NAME:
     92     case CSSPrimitiveValue::CSS_IDENT:
     93     case CSSPrimitiveValue::CSS_PROPERTY_ID:
     94     case CSSPrimitiveValue::CSS_VALUE_ID:
     95     case CSSPrimitiveValue::CSS_PAIR:
     96     case CSSPrimitiveValue::CSS_PARSER_HEXCOLOR:
     97     case CSSPrimitiveValue::CSS_PARSER_IDENTIFIER:
     98     case CSSPrimitiveValue::CSS_PARSER_INTEGER:
     99     case CSSPrimitiveValue::CSS_PARSER_OPERATOR:
    100     case CSSPrimitiveValue::CSS_RECT:
    101     case CSSPrimitiveValue::CSS_QUAD:
    102     case CSSPrimitiveValue::CSS_RGBCOLOR:
    103     case CSSPrimitiveValue::CSS_SHAPE:
    104     case CSSPrimitiveValue::CSS_STRING:
    105     case CSSPrimitiveValue::CSS_UNICODE_RANGE:
    106     case CSSPrimitiveValue::CSS_UNKNOWN:
    107     case CSSPrimitiveValue::CSS_URI:
    108     case CSSPrimitiveValue::CSS_VARIABLE_NAME:
    109         return false;
    110     }
    111 
    112     ASSERT_NOT_REACHED();
    113     return false;
    114 }
    115 
    116 CSSPrimitiveValue::UnitCategory CSSPrimitiveValue::unitCategory(CSSPrimitiveValue::UnitTypes type)
    117 {
    118     // Here we violate the spec (http://www.w3.org/TR/DOM-Level-2-Style/css.html#CSS-CSSPrimitiveValue) and allow conversions
    119     // between CSS_PX and relative lengths (see cssPixelsPerInch comment in core/css/CSSHelper.h for the topic treatment).
    120     switch (type) {
    121     case CSS_NUMBER:
    122         return CSSPrimitiveValue::UNumber;
    123     case CSS_PERCENTAGE:
    124         return CSSPrimitiveValue::UPercent;
    125     case CSS_PX:
    126     case CSS_CM:
    127     case CSS_MM:
    128     case CSS_IN:
    129     case CSS_PT:
    130     case CSS_PC:
    131         return CSSPrimitiveValue::ULength;
    132     case CSS_MS:
    133     case CSS_S:
    134         return CSSPrimitiveValue::UTime;
    135     case CSS_DEG:
    136     case CSS_RAD:
    137     case CSS_GRAD:
    138     case CSS_TURN:
    139         return CSSPrimitiveValue::UAngle;
    140     case CSS_HZ:
    141     case CSS_KHZ:
    142         return CSSPrimitiveValue::UFrequency;
    143     case CSS_VW:
    144     case CSS_VH:
    145     case CSS_VMIN:
    146     case CSS_VMAX:
    147         return CSSPrimitiveValue::UViewportPercentageLength;
    148     case CSS_DPPX:
    149     case CSS_DPI:
    150     case CSS_DPCM:
    151         return CSSPrimitiveValue::UResolution;
    152     default:
    153         return CSSPrimitiveValue::UOther;
    154     }
    155 }
    156 
    157 bool CSSPrimitiveValue::colorIsDerivedFromElement() const
    158 {
    159     int valueID = getValueID();
    160     switch (valueID) {
    161     case CSSValueWebkitText:
    162     case CSSValueWebkitLink:
    163     case CSSValueWebkitActivelink:
    164     case CSSValueCurrentcolor:
    165         return true;
    166     default:
    167         return false;
    168     }
    169 }
    170 
    171 typedef HashMap<const CSSPrimitiveValue*, String> CSSTextCache;
    172 static CSSTextCache& cssTextCache()
    173 {
    174     DEFINE_STATIC_LOCAL(CSSTextCache, cache, ());
    175     return cache;
    176 }
    177 
    178 unsigned short CSSPrimitiveValue::primitiveType() const
    179 {
    180     if (m_primitiveUnitType == CSS_PROPERTY_ID || m_primitiveUnitType == CSS_VALUE_ID)
    181         return CSS_IDENT;
    182 
    183     if (m_primitiveUnitType != CSS_CALC)
    184         return m_primitiveUnitType;
    185 
    186     switch (m_value.calc->category()) {
    187     case CalcNumber:
    188         return CSS_NUMBER;
    189     case CalcPercent:
    190         return CSS_PERCENTAGE;
    191     case CalcLength:
    192         return CSS_PX;
    193     case CalcPercentNumber:
    194         return CSS_CALC_PERCENTAGE_WITH_NUMBER;
    195     case CalcPercentLength:
    196         return CSS_CALC_PERCENTAGE_WITH_LENGTH;
    197     case CalcVariable:
    198         return CSS_UNKNOWN; // The type of a calculation containing a variable cannot be known until the value of the variable is determined.
    199     case CalcOther:
    200         return CSS_UNKNOWN;
    201     }
    202     return CSS_UNKNOWN;
    203 }
    204 
    205 static const AtomicString& propertyName(CSSPropertyID propertyID)
    206 {
    207     ASSERT_ARG(propertyID, propertyID >= 0);
    208     ASSERT_ARG(propertyID, (propertyID >= firstCSSProperty && propertyID < firstCSSProperty + numCSSProperties));
    209 
    210     if (propertyID < 0)
    211         return nullAtom;
    212 
    213     return getPropertyNameAtomicString(propertyID);
    214 }
    215 
    216 static const AtomicString& valueName(CSSValueID valueID)
    217 {
    218     ASSERT_ARG(valueID, valueID >= 0);
    219     ASSERT_ARG(valueID, valueID < numCSSValueKeywords);
    220 
    221     if (valueID < 0)
    222         return nullAtom;
    223 
    224     static AtomicString* keywordStrings = new AtomicString[numCSSValueKeywords]; // Leaked intentionally.
    225     AtomicString& keywordString = keywordStrings[valueID];
    226     if (keywordString.isNull())
    227         keywordString = getValueName(valueID);
    228     return keywordString;
    229 }
    230 
    231 CSSPrimitiveValue::CSSPrimitiveValue(CSSValueID valueID)
    232     : CSSValue(PrimitiveClass)
    233 {
    234     m_primitiveUnitType = CSS_VALUE_ID;
    235     m_value.valueID = valueID;
    236 }
    237 
    238 CSSPrimitiveValue::CSSPrimitiveValue(CSSPropertyID propertyID)
    239     : CSSValue(PrimitiveClass)
    240 {
    241     m_primitiveUnitType = CSS_PROPERTY_ID;
    242     m_value.propertyID = propertyID;
    243 }
    244 
    245 CSSPrimitiveValue::CSSPrimitiveValue(int parserOperator)
    246     : CSSValue(PrimitiveClass)
    247 {
    248     m_primitiveUnitType = CSS_PARSER_OPERATOR;
    249     m_value.parserOperator = parserOperator;
    250 }
    251 
    252 CSSPrimitiveValue::CSSPrimitiveValue(double num, UnitTypes type)
    253     : CSSValue(PrimitiveClass)
    254 {
    255     m_primitiveUnitType = type;
    256     ASSERT(std::isfinite(num));
    257     m_value.num = num;
    258 }
    259 
    260 CSSPrimitiveValue::CSSPrimitiveValue(const String& str, UnitTypes type)
    261     : CSSValue(PrimitiveClass)
    262 {
    263     m_primitiveUnitType = type;
    264     if ((m_value.string = str.impl()))
    265         m_value.string->ref();
    266 }
    267 
    268 
    269 CSSPrimitiveValue::CSSPrimitiveValue(RGBA32 color)
    270     : CSSValue(PrimitiveClass)
    271 {
    272     m_primitiveUnitType = CSS_RGBCOLOR;
    273     m_value.rgbcolor = color;
    274 }
    275 
    276 CSSPrimitiveValue::CSSPrimitiveValue(const Length& length, float zoom)
    277     : CSSValue(PrimitiveClass)
    278 {
    279     switch (length.type()) {
    280     case Auto:
    281     case Intrinsic:
    282     case MinIntrinsic:
    283     case MinContent:
    284     case MaxContent:
    285     case FillAvailable:
    286     case FitContent:
    287     case ExtendToZoom:
    288     case Percent:
    289     case ViewportPercentageWidth:
    290     case ViewportPercentageHeight:
    291     case ViewportPercentageMin:
    292     case ViewportPercentageMax:
    293         init(length);
    294         return;
    295     case Fixed:
    296         m_primitiveUnitType = CSS_PX;
    297         m_value.num = length.value() / zoom;
    298         return;
    299     case Calculated:
    300         init(CSSCalcValue::create(length.calculationValue(), zoom));
    301         return;
    302     case Undefined:
    303         ASSERT_NOT_REACHED();
    304         break;
    305     }
    306 }
    307 
    308 void CSSPrimitiveValue::init(const Length& length)
    309 {
    310     switch (length.type()) {
    311         case Auto:
    312             m_primitiveUnitType = CSS_VALUE_ID;
    313             m_value.valueID = CSSValueAuto;
    314             break;
    315         case Fixed:
    316             m_primitiveUnitType = CSS_PX;
    317             m_value.num = length.value();
    318             break;
    319         case Intrinsic:
    320             m_primitiveUnitType = CSS_VALUE_ID;
    321             m_value.valueID = CSSValueIntrinsic;
    322             break;
    323         case MinIntrinsic:
    324             m_primitiveUnitType = CSS_VALUE_ID;
    325             m_value.valueID = CSSValueMinIntrinsic;
    326             break;
    327         case MinContent:
    328             m_primitiveUnitType = CSS_VALUE_ID;
    329             m_value.valueID = CSSValueMinContent;
    330             break;
    331         case MaxContent:
    332             m_primitiveUnitType = CSS_VALUE_ID;
    333             m_value.valueID = CSSValueMaxContent;
    334             break;
    335         case FillAvailable:
    336             m_primitiveUnitType = CSS_VALUE_ID;
    337             m_value.valueID = CSSValueWebkitFillAvailable;
    338             break;
    339         case FitContent:
    340             m_primitiveUnitType = CSS_VALUE_ID;
    341             m_value.valueID = CSSValueWebkitFitContent;
    342             break;
    343         case ExtendToZoom:
    344             m_primitiveUnitType = CSS_VALUE_ID;
    345             m_value.valueID = CSSValueInternalExtendToZoom;
    346             break;
    347         case Percent:
    348             m_primitiveUnitType = CSS_PERCENTAGE;
    349             ASSERT(std::isfinite(length.percent()));
    350             m_value.num = length.percent();
    351             break;
    352         case ViewportPercentageWidth:
    353             m_primitiveUnitType = CSS_VW;
    354             m_value.num = length.viewportPercentageLength();
    355             break;
    356         case ViewportPercentageHeight:
    357             m_primitiveUnitType = CSS_VH;
    358             m_value.num = length.viewportPercentageLength();
    359             break;
    360         case ViewportPercentageMin:
    361             m_primitiveUnitType = CSS_VMIN;
    362             m_value.num = length.viewportPercentageLength();
    363             break;
    364         case ViewportPercentageMax:
    365             m_primitiveUnitType = CSS_VMAX;
    366             m_value.num = length.viewportPercentageLength();
    367             break;
    368         case Calculated:
    369         case Undefined:
    370             ASSERT_NOT_REACHED();
    371             break;
    372     }
    373 }
    374 
    375 void CSSPrimitiveValue::init(PassRefPtr<Counter> c)
    376 {
    377     m_primitiveUnitType = CSS_COUNTER;
    378     m_hasCachedCSSText = false;
    379     m_value.counter = c.leakRef();
    380 }
    381 
    382 void CSSPrimitiveValue::init(PassRefPtr<Rect> r)
    383 {
    384     m_primitiveUnitType = CSS_RECT;
    385     m_hasCachedCSSText = false;
    386     m_value.rect = r.leakRef();
    387 }
    388 
    389 void CSSPrimitiveValue::init(PassRefPtr<Quad> quad)
    390 {
    391     m_primitiveUnitType = CSS_QUAD;
    392     m_hasCachedCSSText = false;
    393     m_value.quad = quad.leakRef();
    394 }
    395 
    396 void CSSPrimitiveValue::init(PassRefPtr<Pair> p)
    397 {
    398     m_primitiveUnitType = CSS_PAIR;
    399     m_hasCachedCSSText = false;
    400     m_value.pair = p.leakRef();
    401 }
    402 
    403 void CSSPrimitiveValue::init(PassRefPtr<CSSCalcValue> c)
    404 {
    405     m_primitiveUnitType = CSS_CALC;
    406     m_hasCachedCSSText = false;
    407     m_value.calc = c.leakRef();
    408 }
    409 
    410 void CSSPrimitiveValue::init(PassRefPtr<CSSBasicShape> shape)
    411 {
    412     m_primitiveUnitType = CSS_SHAPE;
    413     m_hasCachedCSSText = false;
    414     m_value.shape = shape.leakRef();
    415 }
    416 
    417 CSSPrimitiveValue::~CSSPrimitiveValue()
    418 {
    419     cleanup();
    420 }
    421 
    422 void CSSPrimitiveValue::cleanup()
    423 {
    424     switch (static_cast<UnitTypes>(m_primitiveUnitType)) {
    425     case CSS_STRING:
    426     case CSS_URI:
    427     case CSS_ATTR:
    428     case CSS_COUNTER_NAME:
    429     case CSS_VARIABLE_NAME:
    430     case CSS_PARSER_HEXCOLOR:
    431         if (m_value.string)
    432             m_value.string->deref();
    433         break;
    434     case CSS_COUNTER:
    435         m_value.counter->deref();
    436         break;
    437     case CSS_RECT:
    438         m_value.rect->deref();
    439         break;
    440     case CSS_QUAD:
    441         m_value.quad->deref();
    442         break;
    443     case CSS_PAIR:
    444         m_value.pair->deref();
    445         break;
    446     case CSS_CALC:
    447         m_value.calc->deref();
    448         break;
    449     case CSS_CALC_PERCENTAGE_WITH_NUMBER:
    450     case CSS_CALC_PERCENTAGE_WITH_LENGTH:
    451         ASSERT_NOT_REACHED();
    452         break;
    453     case CSS_SHAPE:
    454         m_value.shape->deref();
    455         break;
    456     case CSS_NUMBER:
    457     case CSS_PARSER_INTEGER:
    458     case CSS_PERCENTAGE:
    459     case CSS_EMS:
    460     case CSS_EXS:
    461     case CSS_REMS:
    462     case CSS_CHS:
    463     case CSS_PX:
    464     case CSS_CM:
    465     case CSS_MM:
    466     case CSS_IN:
    467     case CSS_PT:
    468     case CSS_PC:
    469     case CSS_DEG:
    470     case CSS_RAD:
    471     case CSS_GRAD:
    472     case CSS_MS:
    473     case CSS_S:
    474     case CSS_HZ:
    475     case CSS_KHZ:
    476     case CSS_TURN:
    477     case CSS_VW:
    478     case CSS_VH:
    479     case CSS_VMIN:
    480     case CSS_VMAX:
    481     case CSS_DPPX:
    482     case CSS_DPI:
    483     case CSS_DPCM:
    484     case CSS_FR:
    485     case CSS_IDENT:
    486     case CSS_RGBCOLOR:
    487     case CSS_DIMENSION:
    488     case CSS_UNKNOWN:
    489     case CSS_UNICODE_RANGE:
    490     case CSS_PARSER_OPERATOR:
    491     case CSS_PARSER_IDENTIFIER:
    492     case CSS_PROPERTY_ID:
    493     case CSS_VALUE_ID:
    494         break;
    495     }
    496     m_primitiveUnitType = 0;
    497     if (m_hasCachedCSSText) {
    498         cssTextCache().remove(this);
    499         m_hasCachedCSSText = false;
    500     }
    501 }
    502 
    503 double CSSPrimitiveValue::computeDegrees()
    504 {
    505     switch (m_primitiveUnitType) {
    506     case CSS_DEG:
    507         return getDoubleValue();
    508     case CSS_RAD:
    509         return rad2deg(getDoubleValue());
    510     case CSS_GRAD:
    511         return grad2deg(getDoubleValue());
    512     case CSS_TURN:
    513         return turn2deg(getDoubleValue());
    514     default:
    515         ASSERT_NOT_REACHED();
    516         return 0;
    517     }
    518 }
    519 
    520 template<> int CSSPrimitiveValue::computeLength(const CSSToLengthConversionData& conversionData)
    521 {
    522     return roundForImpreciseConversion<int>(computeLengthDouble(conversionData));
    523 }
    524 
    525 template<> unsigned CSSPrimitiveValue::computeLength(const CSSToLengthConversionData& conversionData)
    526 {
    527     return roundForImpreciseConversion<unsigned>(computeLengthDouble(conversionData));
    528 }
    529 
    530 template<> Length CSSPrimitiveValue::computeLength(const CSSToLengthConversionData& conversionData)
    531 {
    532     return Length(clampTo<float>(computeLengthDouble(conversionData), minValueForCssLength, maxValueForCssLength), Fixed);
    533 }
    534 
    535 template<> short CSSPrimitiveValue::computeLength(const CSSToLengthConversionData& conversionData)
    536 {
    537     return roundForImpreciseConversion<short>(computeLengthDouble(conversionData));
    538 }
    539 
    540 template<> unsigned short CSSPrimitiveValue::computeLength(const CSSToLengthConversionData& conversionData)
    541 {
    542     return roundForImpreciseConversion<unsigned short>(computeLengthDouble(conversionData));
    543 }
    544 
    545 template<> float CSSPrimitiveValue::computeLength(const CSSToLengthConversionData& conversionData)
    546 {
    547     return static_cast<float>(computeLengthDouble(conversionData));
    548 }
    549 
    550 template<> double CSSPrimitiveValue::computeLength(const CSSToLengthConversionData& conversionData)
    551 {
    552     return computeLengthDouble(conversionData);
    553 }
    554 
    555 double CSSPrimitiveValue::computeLengthDouble(const CSSToLengthConversionData& conversionData)
    556 {
    557     if (m_primitiveUnitType == CSS_CALC)
    558         return m_value.calc->computeLengthPx(conversionData);
    559 
    560     const RenderStyle& style = conversionData.style();
    561     const RenderStyle& rootStyle = conversionData.rootStyle();
    562     bool computingFontSize = conversionData.computingFontSize();
    563 
    564     double factor;
    565 
    566     switch (primitiveType()) {
    567         case CSS_EMS:
    568             factor = computingFontSize ? style.fontDescription().specifiedSize() : style.fontDescription().computedSize();
    569             break;
    570         case CSS_EXS:
    571             // FIXME: We have a bug right now where the zoom will be applied twice to EX units.
    572             // We really need to compute EX using fontMetrics for the original specifiedSize and not use
    573             // our actual constructed rendering font.
    574             if (style.fontMetrics().hasXHeight())
    575                 factor = style.fontMetrics().xHeight();
    576             else
    577                 factor = (computingFontSize ? style.fontDescription().specifiedSize() : style.fontDescription().computedSize()) / 2.0;
    578             break;
    579         case CSS_REMS:
    580             factor = computingFontSize ? rootStyle.fontDescription().specifiedSize() : rootStyle.fontDescription().computedSize();
    581             break;
    582         case CSS_CHS:
    583             factor = style.fontMetrics().zeroWidth();
    584             break;
    585         case CSS_PX:
    586             factor = 1.0;
    587             break;
    588         case CSS_CM:
    589             factor = cssPixelsPerCentimeter;
    590             break;
    591         case CSS_MM:
    592             factor = cssPixelsPerMillimeter;
    593             break;
    594         case CSS_IN:
    595             factor = cssPixelsPerInch;
    596             break;
    597         case CSS_PT:
    598             factor = cssPixelsPerPoint;
    599             break;
    600         case CSS_PC:
    601             factor = cssPixelsPerPica;
    602             break;
    603         case CSS_CALC_PERCENTAGE_WITH_LENGTH:
    604         case CSS_CALC_PERCENTAGE_WITH_NUMBER:
    605             ASSERT_NOT_REACHED();
    606             return -1.0;
    607         default:
    608             ASSERT_NOT_REACHED();
    609             return -1.0;
    610     }
    611 
    612     // We do not apply the zoom factor when we are computing the value of the font-size property. The zooming
    613     // for font sizes is much more complicated, since we have to worry about enforcing the minimum font size preference
    614     // as well as enforcing the implicit "smart minimum."
    615     double result = getDoubleValue() * factor;
    616     if (computingFontSize || isFontRelativeLength())
    617         return result;
    618 
    619     return result * conversionData.zoom();
    620 }
    621 
    622 void CSSPrimitiveValue::setFloatValue(unsigned short, double, ExceptionState& exceptionState)
    623 {
    624     // Keeping values immutable makes optimizations easier and allows sharing of the primitive value objects.
    625     // No other engine supports mutating style through this API. Computed style is always read-only anyway.
    626     // Supporting setter would require making primitive value copy-on-write and taking care of style invalidation.
    627     exceptionState.throwUninformativeAndGenericDOMException(NoModificationAllowedError);
    628 }
    629 
    630 double CSSPrimitiveValue::conversionToCanonicalUnitsScaleFactor(unsigned short unitType)
    631 {
    632     double factor = 1.0;
    633     // FIXME: the switch can be replaced by an array of scale factors.
    634     switch (unitType) {
    635     // These are "canonical" units in their respective categories.
    636     case CSS_PX:
    637     case CSS_DEG:
    638     case CSS_MS:
    639     case CSS_HZ:
    640         break;
    641     case CSS_CM:
    642         factor = cssPixelsPerCentimeter;
    643         break;
    644     case CSS_DPCM:
    645         factor = 1 / cssPixelsPerCentimeter;
    646         break;
    647     case CSS_MM:
    648         factor = cssPixelsPerMillimeter;
    649         break;
    650     case CSS_IN:
    651         factor = cssPixelsPerInch;
    652         break;
    653     case CSS_DPI:
    654         factor = 1 / cssPixelsPerInch;
    655         break;
    656     case CSS_PT:
    657         factor = cssPixelsPerPoint;
    658         break;
    659     case CSS_PC:
    660         factor = cssPixelsPerPica;
    661         break;
    662     case CSS_RAD:
    663         factor = 180 / piDouble;
    664         break;
    665     case CSS_GRAD:
    666         factor = 0.9;
    667         break;
    668     case CSS_TURN:
    669         factor = 360;
    670         break;
    671     case CSS_S:
    672     case CSS_KHZ:
    673         factor = 1000;
    674         break;
    675     default:
    676         break;
    677     }
    678 
    679     return factor;
    680 }
    681 
    682 double CSSPrimitiveValue::getDoubleValue(unsigned short unitType, ExceptionState& exceptionState) const
    683 {
    684     double result = 0;
    685     bool success = getDoubleValueInternal(static_cast<UnitTypes>(unitType), &result);
    686     if (!success) {
    687         exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
    688         return 0.0;
    689     }
    690 
    691     return result;
    692 }
    693 
    694 double CSSPrimitiveValue::getDoubleValue(unsigned short unitType) const
    695 {
    696     double result = 0;
    697     getDoubleValueInternal(static_cast<UnitTypes>(unitType), &result);
    698     return result;
    699 }
    700 
    701 double CSSPrimitiveValue::getDoubleValue() const
    702 {
    703     return m_primitiveUnitType != CSS_CALC ? m_value.num : m_value.calc->doubleValue();
    704 }
    705 
    706 CSSPrimitiveValue::UnitTypes CSSPrimitiveValue::canonicalUnitTypeForCategory(UnitCategory category)
    707 {
    708     // The canonical unit type is chosen according to the way CSSParser::validUnit() chooses the default unit
    709     // in each category (based on unitflags).
    710     switch (category) {
    711     case UNumber:
    712         return CSS_NUMBER;
    713     case ULength:
    714         return CSS_PX;
    715     case UPercent:
    716         return CSS_UNKNOWN; // Cannot convert between numbers and percent.
    717     case UTime:
    718         return CSS_MS;
    719     case UAngle:
    720         return CSS_DEG;
    721     case UFrequency:
    722         return CSS_HZ;
    723     case UViewportPercentageLength:
    724         return CSS_UNKNOWN; // Cannot convert between numbers and relative lengths.
    725     case UResolution:
    726         return CSS_DPPX;
    727     default:
    728         return CSS_UNKNOWN;
    729     }
    730 }
    731 
    732 bool CSSPrimitiveValue::getDoubleValueInternal(UnitTypes requestedUnitType, double* result) const
    733 {
    734     if (!isValidCSSUnitTypeForDoubleConversion(static_cast<UnitTypes>(m_primitiveUnitType)) || !isValidCSSUnitTypeForDoubleConversion(requestedUnitType))
    735         return false;
    736 
    737     UnitTypes sourceUnitType = static_cast<UnitTypes>(primitiveType());
    738     if (requestedUnitType == sourceUnitType || requestedUnitType == CSS_DIMENSION) {
    739         *result = getDoubleValue();
    740         return true;
    741     }
    742 
    743     UnitCategory sourceCategory = unitCategory(sourceUnitType);
    744     ASSERT(sourceCategory != UOther);
    745 
    746     UnitTypes targetUnitType = requestedUnitType;
    747     UnitCategory targetCategory = unitCategory(targetUnitType);
    748     ASSERT(targetCategory != UOther);
    749 
    750     // Cannot convert between unrelated unit categories if one of them is not UNumber.
    751     if (sourceCategory != targetCategory && sourceCategory != UNumber && targetCategory != UNumber)
    752         return false;
    753 
    754     if (targetCategory == UNumber) {
    755         // We interpret conversion to CSS_NUMBER as conversion to a canonical unit in this value's category.
    756         targetUnitType = canonicalUnitTypeForCategory(sourceCategory);
    757         if (targetUnitType == CSS_UNKNOWN)
    758             return false;
    759     }
    760 
    761     if (sourceUnitType == CSS_NUMBER) {
    762         // We interpret conversion from CSS_NUMBER in the same way as CSSParser::validUnit() while using non-strict mode.
    763         sourceUnitType = canonicalUnitTypeForCategory(targetCategory);
    764         if (sourceUnitType == CSS_UNKNOWN)
    765             return false;
    766     }
    767 
    768     double convertedValue = getDoubleValue();
    769 
    770     // First convert the value from m_primitiveUnitType to canonical type.
    771     double factor = conversionToCanonicalUnitsScaleFactor(sourceUnitType);
    772     convertedValue *= factor;
    773 
    774     // Now convert from canonical type to the target unitType.
    775     factor = conversionToCanonicalUnitsScaleFactor(targetUnitType);
    776     convertedValue /= factor;
    777 
    778     *result = convertedValue;
    779     return true;
    780 }
    781 
    782 void CSSPrimitiveValue::setStringValue(unsigned short, const String&, ExceptionState& exceptionState)
    783 {
    784     // Keeping values immutable makes optimizations easier and allows sharing of the primitive value objects.
    785     // No other engine supports mutating style through this API. Computed style is always read-only anyway.
    786     // Supporting setter would require making primitive value copy-on-write and taking care of style invalidation.
    787     exceptionState.throwUninformativeAndGenericDOMException(NoModificationAllowedError);
    788 }
    789 
    790 String CSSPrimitiveValue::getStringValue(ExceptionState& exceptionState) const
    791 {
    792     switch (m_primitiveUnitType) {
    793         case CSS_STRING:
    794         case CSS_ATTR:
    795         case CSS_URI:
    796         case CSS_VARIABLE_NAME:
    797             return m_value.string;
    798         case CSS_VALUE_ID:
    799             return valueName(m_value.valueID);
    800         case CSS_PROPERTY_ID:
    801             return propertyName(m_value.propertyID);
    802         default:
    803             exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
    804             break;
    805     }
    806 
    807     return String();
    808 }
    809 
    810 String CSSPrimitiveValue::getStringValue() const
    811 {
    812     switch (m_primitiveUnitType) {
    813         case CSS_STRING:
    814         case CSS_ATTR:
    815         case CSS_URI:
    816         case CSS_VARIABLE_NAME:
    817             return m_value.string;
    818         case CSS_VALUE_ID:
    819             return valueName(m_value.valueID);
    820         case CSS_PROPERTY_ID:
    821             return propertyName(m_value.propertyID);
    822         default:
    823             break;
    824     }
    825 
    826     return String();
    827 }
    828 
    829 Counter* CSSPrimitiveValue::getCounterValue(ExceptionState& exceptionState) const
    830 {
    831     if (m_primitiveUnitType != CSS_COUNTER) {
    832         exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
    833         return 0;
    834     }
    835 
    836     return m_value.counter;
    837 }
    838 
    839 Rect* CSSPrimitiveValue::getRectValue(ExceptionState& exceptionState) const
    840 {
    841     if (m_primitiveUnitType != CSS_RECT) {
    842         exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
    843         return 0;
    844     }
    845 
    846     return m_value.rect;
    847 }
    848 
    849 Quad* CSSPrimitiveValue::getQuadValue(ExceptionState& exceptionState) const
    850 {
    851     if (m_primitiveUnitType != CSS_QUAD) {
    852         exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
    853         return 0;
    854     }
    855 
    856     return m_value.quad;
    857 }
    858 
    859 PassRefPtr<RGBColor> CSSPrimitiveValue::getRGBColorValue(ExceptionState& exceptionState) const
    860 {
    861     if (m_primitiveUnitType != CSS_RGBCOLOR) {
    862         exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
    863         return 0;
    864     }
    865 
    866     // FIMXE: This should not return a new object for each invocation.
    867     return RGBColor::create(m_value.rgbcolor);
    868 }
    869 
    870 Pair* CSSPrimitiveValue::getPairValue(ExceptionState& exceptionState) const
    871 {
    872     if (m_primitiveUnitType != CSS_PAIR) {
    873         exceptionState.throwUninformativeAndGenericDOMException(InvalidAccessError);
    874         return 0;
    875     }
    876 
    877     return m_value.pair;
    878 }
    879 
    880 static String formatNumber(double number, const char* suffix, unsigned suffixLength)
    881 {
    882     DecimalNumber decimal(number);
    883 
    884     StringBuffer<LChar> buffer(decimal.bufferLengthForStringDecimal() + suffixLength);
    885     unsigned length = decimal.toStringDecimal(buffer.characters(), buffer.length());
    886     ASSERT(length + suffixLength == buffer.length());
    887 
    888     for (unsigned i = 0; i < suffixLength; ++i)
    889         buffer[length + i] = static_cast<LChar>(suffix[i]);
    890 
    891     return String::adopt(buffer);
    892 }
    893 
    894 template <unsigned characterCount>
    895 ALWAYS_INLINE static String formatNumber(double number, const char (&characters)[characterCount])
    896 {
    897     return formatNumber(number, characters, characterCount - 1);
    898 }
    899 
    900 String CSSPrimitiveValue::customCSSText(CSSTextFormattingFlags formattingFlag) const
    901 {
    902     // FIXME: return the original value instead of a generated one (e.g. color
    903     // name if it was specified) - check what spec says about this
    904 
    905     if (m_hasCachedCSSText) {
    906         ASSERT(cssTextCache().contains(this));
    907         return cssTextCache().get(this);
    908     }
    909 
    910     String text;
    911     switch (m_primitiveUnitType) {
    912         case CSS_UNKNOWN:
    913             // FIXME
    914             break;
    915         case CSS_NUMBER:
    916         case CSS_PARSER_INTEGER:
    917             text = formatNumber(m_value.num, "");
    918             break;
    919         case CSS_PERCENTAGE:
    920             text = formatNumber(m_value.num, "%");
    921             break;
    922         case CSS_EMS:
    923             text = formatNumber(m_value.num, "em");
    924             break;
    925         case CSS_EXS:
    926             text = formatNumber(m_value.num, "ex");
    927             break;
    928         case CSS_REMS:
    929             text = formatNumber(m_value.num, "rem");
    930             break;
    931         case CSS_CHS:
    932             text = formatNumber(m_value.num, "ch");
    933             break;
    934         case CSS_PX:
    935             text = formatNumber(m_value.num, "px");
    936             break;
    937         case CSS_CM:
    938             text = formatNumber(m_value.num, "cm");
    939             break;
    940         case CSS_DPPX:
    941             text = formatNumber(m_value.num, "dppx");
    942             break;
    943         case CSS_DPI:
    944             text = formatNumber(m_value.num, "dpi");
    945             break;
    946         case CSS_DPCM:
    947             text = formatNumber(m_value.num, "dpcm");
    948             break;
    949         case CSS_MM:
    950             text = formatNumber(m_value.num, "mm");
    951             break;
    952         case CSS_IN:
    953             text = formatNumber(m_value.num, "in");
    954             break;
    955         case CSS_PT:
    956             text = formatNumber(m_value.num, "pt");
    957             break;
    958         case CSS_PC:
    959             text = formatNumber(m_value.num, "pc");
    960             break;
    961         case CSS_DEG:
    962             text = formatNumber(m_value.num, "deg");
    963             break;
    964         case CSS_RAD:
    965             text = formatNumber(m_value.num, "rad");
    966             break;
    967         case CSS_GRAD:
    968             text = formatNumber(m_value.num, "grad");
    969             break;
    970         case CSS_MS:
    971             text = formatNumber(m_value.num, "ms");
    972             break;
    973         case CSS_S:
    974             text = formatNumber(m_value.num, "s");
    975             break;
    976         case CSS_HZ:
    977             text = formatNumber(m_value.num, "hz");
    978             break;
    979         case CSS_KHZ:
    980             text = formatNumber(m_value.num, "khz");
    981             break;
    982         case CSS_TURN:
    983             text = formatNumber(m_value.num, "turn");
    984             break;
    985         case CSS_DIMENSION:
    986             // FIXME: We currently don't handle CSS_DIMENSION properly as we don't store
    987             // the actual dimension, just the numeric value as a string.
    988             break;
    989         case CSS_STRING:
    990             text = formattingFlag == AlwaysQuoteCSSString ? quoteCSSString(m_value.string) : quoteCSSStringIfNeeded(m_value.string);
    991             break;
    992         case CSS_URI:
    993             text = "url(" + quoteCSSURLIfNeeded(m_value.string) + ")";
    994             break;
    995         case CSS_VALUE_ID:
    996             text = valueName(m_value.valueID);
    997             break;
    998         case CSS_PROPERTY_ID:
    999             text = propertyName(m_value.propertyID);
   1000             break;
   1001         case CSS_ATTR: {
   1002             StringBuilder result;
   1003             result.reserveCapacity(6 + m_value.string->length());
   1004             result.appendLiteral("attr(");
   1005             result.append(m_value.string);
   1006             result.append(')');
   1007 
   1008             text = result.toString();
   1009             break;
   1010         }
   1011         case CSS_COUNTER_NAME:
   1012             text = "counter(" + String(m_value.string) + ')';
   1013             break;
   1014         case CSS_COUNTER: {
   1015             StringBuilder result;
   1016             String separator = m_value.counter->separator();
   1017             if (separator.isEmpty())
   1018                 result.appendLiteral("counter(");
   1019             else
   1020                 result.appendLiteral("counters(");
   1021 
   1022             result.append(m_value.counter->identifier());
   1023             if (!separator.isEmpty()) {
   1024                 result.appendLiteral(", ");
   1025                 result.append(quoteCSSStringIfNeeded(separator));
   1026             }
   1027             String listStyle = m_value.counter->listStyle();
   1028             if (!listStyle.isEmpty()) {
   1029                 result.appendLiteral(", ");
   1030                 result.append(listStyle);
   1031             }
   1032             result.append(')');
   1033 
   1034             text = result.toString();
   1035             break;
   1036         }
   1037         case CSS_RECT:
   1038             text = getRectValue()->cssText();
   1039             break;
   1040         case CSS_QUAD:
   1041             text = getQuadValue()->cssText();
   1042             break;
   1043         case CSS_RGBCOLOR:
   1044         case CSS_PARSER_HEXCOLOR: {
   1045             RGBA32 rgbColor = m_value.rgbcolor;
   1046             if (m_primitiveUnitType == CSS_PARSER_HEXCOLOR)
   1047                 Color::parseHexColor(m_value.string, rgbColor);
   1048             Color color(rgbColor);
   1049 
   1050             StringBuilder result;
   1051             result.reserveCapacity(32);
   1052             bool colorHasAlpha = color.hasAlpha();
   1053             if (colorHasAlpha)
   1054                 result.append("rgba(", 5);
   1055             else
   1056                 result.append("rgb(", 4);
   1057 
   1058             result.appendNumber(static_cast<unsigned char>(color.red()));
   1059             result.append(", ", 2);
   1060 
   1061             result.appendNumber(static_cast<unsigned char>(color.green()));
   1062             result.append(", ", 2);
   1063 
   1064             result.appendNumber(static_cast<unsigned char>(color.blue()));
   1065             if (colorHasAlpha) {
   1066                 result.append(", ", 2);
   1067 
   1068                 NumberToStringBuffer buffer;
   1069                 const char* alphaString = numberToFixedPrecisionString(color.alpha() / 255.0f, 6, buffer, true);
   1070                 result.append(alphaString, strlen(alphaString));
   1071             }
   1072 
   1073             result.append(')');
   1074             text = result.toString();
   1075             break;
   1076         }
   1077         case CSS_FR:
   1078             text = formatNumber(m_value.num, "fr");
   1079             break;
   1080         case CSS_PAIR:
   1081             text = getPairValue()->cssText();
   1082             break;
   1083         case CSS_PARSER_OPERATOR: {
   1084             char c = static_cast<char>(m_value.parserOperator);
   1085             text = String(&c, 1U);
   1086             break;
   1087         }
   1088         case CSS_PARSER_IDENTIFIER:
   1089             text = quoteCSSStringIfNeeded(m_value.string);
   1090             break;
   1091         case CSS_CALC:
   1092             text = m_value.calc->cssText();
   1093             break;
   1094         case CSS_SHAPE:
   1095             text = m_value.shape->cssText();
   1096             break;
   1097         case CSS_VW:
   1098             text = formatNumber(m_value.num, "vw");
   1099             break;
   1100         case CSS_VH:
   1101             text = formatNumber(m_value.num, "vh");
   1102             break;
   1103         case CSS_VMIN:
   1104             text = formatNumber(m_value.num, "vmin");
   1105             break;
   1106         case CSS_VMAX:
   1107             text = formatNumber(m_value.num, "vmax");
   1108             break;
   1109         case CSS_VARIABLE_NAME:
   1110             text = "var(" + String(m_value.string) + ")";
   1111             break;
   1112     }
   1113 
   1114     ASSERT(!cssTextCache().contains(this));
   1115     cssTextCache().set(this, text);
   1116     m_hasCachedCSSText = true;
   1117     return text;
   1118 }
   1119 
   1120 String CSSPrimitiveValue::customSerializeResolvingVariables(const HashMap<AtomicString, String>& variables) const
   1121 {
   1122     if (isVariableName()) {
   1123         AtomicString variableName(m_value.string);
   1124         if (variables.contains(variableName))
   1125             return variables.get(variableName);
   1126     }
   1127     if (CSSCalcValue* calcValue = cssCalcValue())
   1128         return calcValue->customSerializeResolvingVariables(variables);
   1129     if (Pair* pairValue = getPairValue())
   1130         return pairValue->serializeResolvingVariables(variables);
   1131     if (Rect* rectVal = getRectValue())
   1132         return rectVal->serializeResolvingVariables(variables);
   1133     if (Quad* quadVal = getQuadValue())
   1134         return quadVal->serializeResolvingVariables(variables);
   1135     if (CSSBasicShape* shapeValue = getShapeValue())
   1136         return shapeValue->serializeResolvingVariables(variables);
   1137     return customCSSText();
   1138 }
   1139 
   1140 bool CSSPrimitiveValue::hasVariableReference() const
   1141 {
   1142     if (CSSCalcValue* calcValue = cssCalcValue())
   1143         return calcValue->hasVariableReference();
   1144     if (Pair* pairValue = getPairValue())
   1145         return pairValue->hasVariableReference();
   1146     if (Quad* quadValue = getQuadValue())
   1147         return quadValue->hasVariableReference();
   1148     if (Rect* rectValue = getRectValue())
   1149         return rectValue->hasVariableReference();
   1150     if (CSSBasicShape* shapeValue = getShapeValue())
   1151         return shapeValue->hasVariableReference();
   1152     return isVariableName();
   1153 }
   1154 
   1155 void CSSPrimitiveValue::addSubresourceStyleURLs(ListHashSet<KURL>& urls, const StyleSheetContents* styleSheet) const
   1156 {
   1157     if (m_primitiveUnitType == CSS_URI)
   1158         addSubresourceURL(urls, styleSheet->completeURL(m_value.string));
   1159 }
   1160 
   1161 Length CSSPrimitiveValue::viewportPercentageLength()
   1162 {
   1163     ASSERT(isViewportPercentageLength());
   1164     Length viewportLength;
   1165     switch (m_primitiveUnitType) {
   1166     case CSS_VW:
   1167         viewportLength = Length(getDoubleValue(), ViewportPercentageWidth);
   1168         break;
   1169     case CSS_VH:
   1170         viewportLength = Length(getDoubleValue(), ViewportPercentageHeight);
   1171         break;
   1172     case CSS_VMIN:
   1173         viewportLength = Length(getDoubleValue(), ViewportPercentageMin);
   1174         break;
   1175     case CSS_VMAX:
   1176         viewportLength = Length(getDoubleValue(), ViewportPercentageMax);
   1177         break;
   1178     default:
   1179         break;
   1180     }
   1181     return viewportLength;
   1182 }
   1183 
   1184 PassRefPtr<CSSPrimitiveValue> CSSPrimitiveValue::cloneForCSSOM() const
   1185 {
   1186     RefPtr<CSSPrimitiveValue> result;
   1187 
   1188     switch (m_primitiveUnitType) {
   1189     case CSS_STRING:
   1190     case CSS_URI:
   1191     case CSS_ATTR:
   1192     case CSS_COUNTER_NAME:
   1193         result = CSSPrimitiveValue::create(m_value.string, static_cast<UnitTypes>(m_primitiveUnitType));
   1194         break;
   1195     case CSS_COUNTER:
   1196         result = CSSPrimitiveValue::create(m_value.counter->cloneForCSSOM());
   1197         break;
   1198     case CSS_RECT:
   1199         result = CSSPrimitiveValue::create(m_value.rect->cloneForCSSOM());
   1200         break;
   1201     case CSS_QUAD:
   1202         result = CSSPrimitiveValue::create(m_value.quad->cloneForCSSOM());
   1203         break;
   1204     case CSS_PAIR:
   1205         // Pair is not exposed to the CSSOM, no need for a deep clone.
   1206         result = CSSPrimitiveValue::create(m_value.pair);
   1207         break;
   1208     case CSS_CALC:
   1209         // CSSCalcValue is not exposed to the CSSOM, no need for a deep clone.
   1210         result = CSSPrimitiveValue::create(m_value.calc);
   1211         break;
   1212     case CSS_SHAPE:
   1213         // CSSShapeValue is not exposed to the CSSOM, no need for a deep clone.
   1214         result = CSSPrimitiveValue::create(m_value.shape);
   1215         break;
   1216     case CSS_NUMBER:
   1217     case CSS_PARSER_INTEGER:
   1218     case CSS_PERCENTAGE:
   1219     case CSS_EMS:
   1220     case CSS_EXS:
   1221     case CSS_REMS:
   1222     case CSS_CHS:
   1223     case CSS_PX:
   1224     case CSS_CM:
   1225     case CSS_MM:
   1226     case CSS_IN:
   1227     case CSS_PT:
   1228     case CSS_PC:
   1229     case CSS_DEG:
   1230     case CSS_RAD:
   1231     case CSS_GRAD:
   1232     case CSS_MS:
   1233     case CSS_S:
   1234     case CSS_HZ:
   1235     case CSS_KHZ:
   1236     case CSS_TURN:
   1237     case CSS_VW:
   1238     case CSS_VH:
   1239     case CSS_VMIN:
   1240     case CSS_VMAX:
   1241     case CSS_DPPX:
   1242     case CSS_DPI:
   1243     case CSS_DPCM:
   1244     case CSS_FR:
   1245         result = CSSPrimitiveValue::create(m_value.num, static_cast<UnitTypes>(m_primitiveUnitType));
   1246         break;
   1247     case CSS_PROPERTY_ID:
   1248         result = CSSPrimitiveValue::createIdentifier(m_value.propertyID);
   1249         break;
   1250     case CSS_VALUE_ID:
   1251         result = CSSPrimitiveValue::createIdentifier(m_value.valueID);
   1252         break;
   1253     case CSS_RGBCOLOR:
   1254         result = CSSPrimitiveValue::createColor(m_value.rgbcolor);
   1255         break;
   1256     case CSS_DIMENSION:
   1257     case CSS_UNKNOWN:
   1258     case CSS_PARSER_OPERATOR:
   1259     case CSS_PARSER_IDENTIFIER:
   1260     case CSS_PARSER_HEXCOLOR:
   1261         ASSERT_NOT_REACHED();
   1262         break;
   1263     }
   1264     if (result)
   1265         result->setCSSOMSafe();
   1266 
   1267     return result;
   1268 }
   1269 
   1270 bool CSSPrimitiveValue::equals(const CSSPrimitiveValue& other) const
   1271 {
   1272     if (m_primitiveUnitType != other.m_primitiveUnitType)
   1273         return false;
   1274 
   1275     switch (m_primitiveUnitType) {
   1276     case CSS_UNKNOWN:
   1277         return false;
   1278     case CSS_NUMBER:
   1279     case CSS_PARSER_INTEGER:
   1280     case CSS_PERCENTAGE:
   1281     case CSS_EMS:
   1282     case CSS_EXS:
   1283     case CSS_REMS:
   1284     case CSS_PX:
   1285     case CSS_CM:
   1286     case CSS_DPPX:
   1287     case CSS_DPI:
   1288     case CSS_DPCM:
   1289     case CSS_MM:
   1290     case CSS_IN:
   1291     case CSS_PT:
   1292     case CSS_PC:
   1293     case CSS_DEG:
   1294     case CSS_RAD:
   1295     case CSS_GRAD:
   1296     case CSS_MS:
   1297     case CSS_S:
   1298     case CSS_HZ:
   1299     case CSS_KHZ:
   1300     case CSS_TURN:
   1301     case CSS_VW:
   1302     case CSS_VH:
   1303     case CSS_VMIN:
   1304     case CSS_VMAX:
   1305     case CSS_DIMENSION:
   1306     case CSS_FR:
   1307         return m_value.num == other.m_value.num;
   1308     case CSS_PROPERTY_ID:
   1309         return propertyName(m_value.propertyID) == propertyName(other.m_value.propertyID);
   1310     case CSS_VALUE_ID:
   1311         return valueName(m_value.valueID) == valueName(other.m_value.valueID);
   1312     case CSS_STRING:
   1313     case CSS_URI:
   1314     case CSS_ATTR:
   1315     case CSS_COUNTER_NAME:
   1316     case CSS_PARSER_IDENTIFIER:
   1317     case CSS_PARSER_HEXCOLOR:
   1318     case CSS_VARIABLE_NAME:
   1319         return equal(m_value.string, other.m_value.string);
   1320     case CSS_COUNTER:
   1321         return m_value.counter && other.m_value.counter && m_value.counter->equals(*other.m_value.counter);
   1322     case CSS_RECT:
   1323         return m_value.rect && other.m_value.rect && m_value.rect->equals(*other.m_value.rect);
   1324     case CSS_QUAD:
   1325         return m_value.quad && other.m_value.quad && m_value.quad->equals(*other.m_value.quad);
   1326     case CSS_RGBCOLOR:
   1327         return m_value.rgbcolor == other.m_value.rgbcolor;
   1328     case CSS_PAIR:
   1329         return m_value.pair && other.m_value.pair && m_value.pair->equals(*other.m_value.pair);
   1330     case CSS_PARSER_OPERATOR:
   1331         return m_value.parserOperator == other.m_value.parserOperator;
   1332     case CSS_CALC:
   1333         return m_value.calc && other.m_value.calc && m_value.calc->equals(*other.m_value.calc);
   1334     case CSS_SHAPE:
   1335         return m_value.shape && other.m_value.shape && m_value.shape->equals(*other.m_value.shape);
   1336     }
   1337     return false;
   1338 }
   1339 
   1340 } // namespace WebCore
   1341