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