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