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