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