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